; -*- fill-column: 79 -*-
;
; acl2-doc.lisp - Documentation for the ACL2 Theorem Prover
;
; ACL2 Version 8.0 -- A Computational Logic for Applicative Common Lisp
; Copyright (C) 2017, Regents of the University of Texas
;
; This documentation was derived from the ACL2 system in October 2013, which
; was a descendant of ACL2 Version 1.9, Copyright (C) 1997 Computational Logic,
; Inc.  See the documentation topic NOTE-2-0.
;
; This program is free software; you can redistribute it and/or modify it under
; the terms of the LICENSE file distributed with ACL2.
;
; This program is distributed in the hope that it will be useful, but WITHOUT
; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
; FOR A PARTICULAR PURPOSE.  See the LICENSE file distributed with ACL2 for
; more details.
;
; Here are the original authors of this book.
;
; Written by:  Matt Kaufmann               and J Strother Moore
; email:       Kaufmann@cs.utexas.edu      and Moore@cs.utexas.edu
; Department of Computer Science
; University of Texas at Austin
; Austin, TX 78712 U.S.A.
;
; The ACL2 community is invited to contribute to this book through the github
; project https://github.com/acl2/acl2/.  If you edit this book, then please
; conform to its style, for example restricting to 79 columns, avoiding tab
; characters, and keeping topics in alphabetical order.  Please add additional
; instructions here as appropriate.  For general information about writing
; documentation, see the ACL2+Books Manual (see :DOC documentation), in
; particular the topic DEFXDOC and the related topics XDOC::MARKUP and
; XDOC::PREPROCESSOR.

; Note that :long is optional; if its value is "", feel free to omit it.

; Many topics are nothing but links, as generated by calls of defpointer,
; below.

(in-package "ACL2")
(include-book "xdoc/top" :dir :system)

(defconst *acl2-broken-links-alist*

; The value of this constant is an alist whose keys are the XDOC topics
; referenced in the ACL2-only manual that are not in the ACL2-only manual
; (i.e. that are in the Books part of the ACL2+Books manual).  Each key in this
; alist is associated with the name of the file where the referenced topic is
; defined.  Each file name is a string starting with [books]/ (see below).  So
; these links are "broken" in the ACL2-only manual.

; So in practice, if you link to an ACL2+Books topic that is not in the
; ACL2-only manual, just add an entry following the pattern below.  It would be
; best if you keep it sorted by the SYMBOL-NAME of the CAR.

; The remaining long comment can generally be ignored except at release time,
; as a final check.

; The following long comment shows how to create this value.  It would be good
; to re-create it on occasion, or better yet, to automate a check that the
; value is up-to-date.

#||
 (include-book ; break line to avoid confusing dependency scanner
  "system/doc/acl2-doc" :dir :system)

 (make-event
 ; This make-event form is adapted from acl2-doc-wrap.lisp.

  ;; This constant is used in acl2-manual.lisp to ensure that we are only
  ;; writing the topics from this file.  Because of our use of make-event,
  ;; this will be written into the .cert file.
  (let ((topics (xdoc::get-xdoc-table (w state))))
    `(defconst *acl2-sources-xdoc-topics-prelim*
       ',topics)))

 (include-book ; break line to avoid confusing dependency scanner
  "xdoc/importance" :dir :system)

 (set-state-ok t)
 (program)

 (make-event
  (mv-let
   (names state)
   #!xdoc(mv-let
          (xtopics state)
          (xtopics-from-topics acl2::*acl2-sources-xdoc-topics-prelim* state)
          (let* ((links-fal (make-links-fal xtopics))
                 (keys-fal  (make-fast-alist
                             (pairlis$ (make-keys (xtopiclist->names xtopics))
                                       nil)))
                 (broken (find-broken-links links-fal keys-fal)))
            (mv (strip-cars broken) state)))
   (value `(defconst *acl2-broken-links-mangled-names* ',names))))

 (defun topic-source-alist (keys all-topics)
   (cond ((endp all-topics) nil)
         (t (let* ((topic (car all-topics))
                   (name (cdr (assoc-eq :name topic)))
                   (key (xdoc::make-key name)))
              (cond ((member-equal key keys)
                     (cons (list name (cdr (assoc-eq :from topic)))
                           (topic-source-alist keys (cdr all-topics))))
                    (t (topic-source-alist keys (cdr all-topics))))))))

 ; WARNING: Unless doc/top.lisp is certified, the following will build manual/
 ; under the current directory and will also build
 ; books/system/doc/rendered-doc-combined.lsp!  (Presumably that could be
 ; avoided with a little effort.)  Something like the following could work
 ; instead of the following include-book, but we would need to define more
 ; packages than just those in books/doc/top.acl2:
 ; (serialize-read "/Users/kaufmann/acl2/devel/books/centaur/xdoc.sao")
 (include-book ; break line to avoid confusing dependency scanner
  "doc/top" :dir :system)

 (defun acl2-broken-links-alist (state)
   (merge-sort-lexorder
    (topic-source-alist *acl2-broken-links-mangled-names*
                        (xdoc::get-xdoc-table (w state)))))

 ; Finally, compare the value, V, of the following to what is below.  But note
 ; that V may contain some entries with value "Current Interactive Session",
 ; which should be replaced with a more appropriate string, e.g., the file
 ; found by going to the entry's topic in the online combined manual.
 (acl2-broken-links-alist state)

||#

  '((*ACL2-SYSTEM-EXPORTS* "[books]/system/acl2-system-exports.lisp")
    (<< "[books]/misc/total-order.lisp")
    (APPEND-WITHOUT-GUARD "[books]/std/lists/flatten.lisp")
    (OSLIB::ARGV "[books]/oslib/argv-logic.lisp")
    (ARITH-EQUIVS "[books]/std/basic/arith-equiv-defs.lisp")
    (ARITHMETIC "[books]/doc/more-topics.lisp")
    (ARITHMETIC-1 "[books]/arithmetic/top.lisp")
    (ARITHMETIC/NATP-POSP "[books]/arithmetic/natp-posp.lisp")
    (ARITY+ "[books]/kestrel/utilities/world-queries.lisp")
    (ASSERT! "[books]/misc/assert.lisp")
    (B* "[books]/std/util/bstar.lisp")
    (BRIDGE "[books]/centaur/bridge/top.lisp")
    (BUILD::CERT.PL "[books]/build/doc.lisp")
    (BUILD::CERT_PARAM "[books]/build/doc.lisp")
    (STD::DEFAGGREGATE "[books]/std/util/defaggregate.lisp")
    (DEFCONSTS "[books]/std/util/defconsts.lisp")
    (DEFDATA "[books]/acl2s/defdata/top.lisp")
    (DEFINE "[books]/std/util/define.lisp")
    (DEFMAC "[books]/misc/defmac.lisp")
    (DEFMACROQ "[books]/kestrel/utilities/defmacroq.lisp")
    (FTY::DEFPROD "[books]/centaur/fty/top.lisp")
    (DEFPUN "[books]/misc/defpun.lisp")
    (DEFTHMG "[books]/tools/defthmg.lisp")
    (GETOPT-DEMO::DEMO2 "[books]/centaur/getopt/demo2.lisp")
    (DO-NOT-HINT "[books]/tools/do-not.lisp")
    (EASY-SIMPLIFY-TERM "[books]/tools/easy-simplify.lisp")
    (ER-SOFT+ "[books]/kestrel/utilities/er-soft-plus.lisp")
    (ER-SOFT-LOGIC "[books]/tools/er-soft-logic.lisp")
    (FTY "[books]/centaur/fty/top.lisp")
    (GETOPT "[books]/centaur/getopt/top.lisp")
    (GL "[books]/centaur/gl/doc.lisp")
    (HACKER "[books]/hacking/hacking-xdoc.lisp")
    (IHS "[books]/ihs/ihs-doc-topic.lisp")
    (INCLUDE-RAW "[books]/tools/include-raw.lisp")
    (INSTALL-NOT-NORMALIZED "[books]/misc/install-not-normalized.lisp")
    (LOGBITP-REASONING "[books]/centaur/bitops/equal-by-logbitp.lisp")
    (MAKE-FLAG "[books]/tools/flag.lisp")
    (MAKE-TERMINATION-THEOREM
     "[books]/kestrel/utilities/make-termination-theorem.lisp")
    (STR::NATSTR "[books]/std/strings/decimal.lisp")
    (NON-PARALLEL-BOOK "[books]/std/system/non-parallel-book.lisp")
    (NOTE-6-4-BOOKS "[books]/doc/relnotes.lisp")
    (NOTE-6-5-BOOKS "[books]/doc/relnotes.lisp")
    (NOTE-7-0-BOOKS "[books]/doc/relnotes.lisp")
    (NOTE-7-1-BOOKS "[books]/doc/relnotes.lisp")
    (NOTE-7-2-BOOKS "[books]/doc/relnotes.lisp")
    (NOTE-8-0-BOOKS "[books]/doc/relnotes.lisp")
    (STR::NUMBERS "[books]/std/strings/top.lisp")
    (ORACLE-TIMELIMIT "[books]/tools/oracle-timelimit.lisp")
    (OSLIB "[books]/oslib/top-logic.lisp")
    (PATBIND-THE "[books]/std/util/bstar.lisp")
    (BUILD::PRE-CERTIFY-BOOK-COMMANDS "[books]/build/doc.lisp")
    (XDOC::PREPROCESSOR "[books]/xdoc/topics.lisp")
    (STR::PRETTY "[books]/std/strings/pretty.lisp")
    (STR::PRETTY-PRINTING "[books]/std/strings/pretty.lisp")
    (PROFILE-ACL2 "[books]/centaur/memoize/old/profile.lisp")
    (PROFILE-ALL "[books]/centaur/memoize/old/profile.lisp")
    (QUICKLISP "[books]/centaur/quicklisp/top.lisp")
    (RELEASE-NOTES-BOOKS "[books]/doc/relnotes.lisp")
    (REMOVABLE-RUNES "[books]/tools/removable-runes.lisp")
    (RUN-SCRIPT "[books]/tools/run-script.lisp")
    (SATLINK::SAT-SOLVER-OPTIONS "[books]/centaur/satlink/top.lisp")
    (SATLINK "[books]/centaur/satlink/top.lisp")
    (XDOC::SAVE "[books]/xdoc/topics.lisp")
    (XDOC::SAVE-RENDERED "[books]/xdoc/topics.lisp")
    (XDOC::SAVE-RENDERED-EVENT "[books]/xdoc/topics.lisp")
    (SET-MAX-MEM "[books]/centaur/misc/memory-mgmt-logic.lisp")
    (SPACEWALK "[books]/centaur/misc/spacewalk.lisp")
    (STD "[books]/std/top.lisp")
    (STD/IO "[books]/std/io/top.lisp")
    (STD/STRINGS "[books]/std/strings/top.lisp")
    (STD/UTIL "[books]/std/util/top.lisp")
    (STD::STRICT-LIST-RECOGNIZERS "[books]/std/util/deflist-base.lisp")
    (SUBSEQ-LIST "[books]/std/lists/subseq.lisp")
    (TRANS-EVAL-ERROR-TRIPLE "[books]/kestrel/utilities/trans-eval-error-triple.lisp")
    (TRANS-EVAL-STATE "[books]/kestrel/utilities/trans-eval-error-triple.lisp")
    (UNSOUND-READ "[books]/std/io/unsound-read.lisp")
    (UNTRANSLATE-PATTERNS "[books]/misc/untranslate-patterns.lisp")
    (BUILD::USING-EXTENDED-ACL2-IMAGES "[books]/build/doc.lisp")
    (WITH-RAW-MODE "[books]/hacking/hacking-xdoc.lisp")
    (WITH-REDEF-ALLOWED "[books]/hacking/hacking-xdoc.lisp")
    (WITH-TIMEOUT "[books]/acl2s/cgen/with-timeout.lisp")
    (WORKING-WITH-PACKAGES "[books]/doc/practices.lisp")
    (XDOC "[books]/xdoc/topics.lisp")))

(defconst *acl2-url*

; Warning: This event appears identically in acl2-doc.lisp and
; acl2-doc-wrap.lisp.  If you change one, then change the other the same way!

; We use the specific release rather than "current" in the URL, so that those
; who are looking at an older version of ACL2 will see the corresponding
; ACL2+Books Manual at this link.

  "http://www.cs.utexas.edu/users/moore/acl2/v8-0/")

(defconst *installation-url*

; Warning: This event appears identically in acl2-doc.lisp and
; acl2-doc-wrap.lisp.  If you change one, then change the other the same way!

  (concatenate 'string *acl2-url* "HTML/installation/installation.html"))

(defun combined-manual-ref ()

; Warning: This event appears identically in acl2-doc.lisp and
; acl2-doc-wrap.lisp.  If you change one, then change the other the same way!

  (concatenate
   'string
   "<a href='"
   (concatenate 'string *acl2-url* "combined-manual/index.html") ; url
   "'>"
   "ACL2+Books Manual"
   "</a>"))

(defun clhs (url title)

; Warning: This event appears identically in acl2-doc.lisp and
; acl2-doc-wrap.lisp.  If you change one, then change the other the same way!

  (declare (xargs :guard (and (or (not url)
                                  (stringp url))
                              (stringp title))))
  (concatenate 'string
               "<a href='http://www.lispworks.com/documentation/HyperSpec/"
               (or url "")
               "'>" title "</a>"))

(defxdoc *
  :parents (numbers acl2-built-ins)
  :short "Multiplication macro"
  :long "<p>@('*') is really a macro that expands to calls of the function
 @(tsee binary-*).  So for example</p>

 @({
  (* x y 4 z)
 })

 <p>represents the same term as</p>

 @({
  (binary-* x (binary-* y (binary-* 4 z))).
 })

 <p>See @(see binary-*).</p>

 <p>@('*') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>")

(defxdoc *acl2-exports*
   :parents (packages acl2-built-ins)
   :short "Symbols that are often imported into new @(see packages) to provide
 easy access to ACL2 functionality."

   :long "<p>When you define a new package for your own work with @(see defpkg),
 you will usually want to import many symbols from the @('\"ACL2\"') package;
 for instance you will usually want to be able to use symbols like @(see
 defthm), @(see in-theory), @(see xargs), @(see state), etc., without an
 @('acl2::') prefix.</p>

 <p>The constant @('*acl2-exports*') lists @(`(len *acl2-exports*)`) symbols,
 including most documented ACL2 system constants, functions, and macros.  You
 will typically also want to import many symbols from Common Lisp; see @(see
 *common-lisp-symbols-from-main-lisp-package*).</p>

 <p>Those who write code using ACL2 system functions (see @(see
 system-utilities)) may wish to import symbols into their package from the
 large list @(tsee *acl2-system-exports*).</p>

 @(`(:code *acl2-exports*)`)")

 (defxdoc *common-lisp-symbols-from-main-lisp-package*
   :parents (packages acl2-built-ins)
   :short "Symbols that are often imported into new packages to provide easy
 access to Common Lisp functionality."

   :long "<p>When you define a new package for your own work with @(see defpkg),
 you will usually want to import many symbols from the @('\"COMMON-LISP\"')
 package so that you can access them without a @('common-lisp::') or @('acl2::')
 prefix.</p>

 <p>The constant @('*common-lisp-symbols-from-main-lisp-package*') lists the
 @(`(len *common-lisp-symbols-from-main-lisp-package*)`) symbols of the
 @('COMMON-LISP') package found in <a
 href='http://dx.doi.org/10.1145/147135.147249'>dpAns</a>.  You will typically
 also want to import many symbols from ACL2; see @(see *acl2-exports*).</p>

 @(`(:code *common-lisp-symbols-from-main-lisp-package*)`)")

(defxdoc *standard-ci*
  :parents (io acl2-built-ins)
  :short "An ACL2 character-based analogue of CLTL's @('*standard-input*')"
  :long "<p>The value of the ACL2 constant @('*standard-ci*') is an open
 character input channel that is synonymous to Common Lisp's
 @('*standard-input*').</p>

 <p>ACL2 character input from @('*standard-ci*') is actually obtained by
 reading @(see characters) from the stream named by Common Lisp's
 @('*standard-input*').  That is, by changing the setting of
 @('*standard-input*') in raw Common Lisp you can change the source from which
 ACL2 reads on the channel @('*standard-ci*').  See @(see *standard-co*).</p>")

(defxdoc *standard-co*
  :parents (io acl2-built-ins)
  :short "The ACL2 analogue of CLTL's @('*standard-output*')"
  :long "<p>The value of the ACL2 constant @('*standard-co*') is an open
 character output channel that is synonymous to Common Lisp's
 @('*standard-output*').</p>

 <p>ACL2 character output to @('*standard-co*') will go to the stream named by
 Common Lisp's @('*standard-output*').  That is, by changing the setting of
 @('*standard-output*') in raw Common Lisp you can change the actual
 destination of ACL2 output on the channel named by @('*standard-co*').
 Observe that this happens without changing the logical value of
 @('*standard-co*') (which is some channel symbol).  Changing the setting of
 @('*standard-output*') in raw Common Lisp essentially just changes the map
 that relates ACL2 to the physical world of terminals, files, etc.</p>

 <p>To see the value of this observation, consider the following.  Suppose you
 write an ACL2 function which does character output to the constant channel
 @('*standard-co*').  During testing you see that the output actually goes to
 your terminal.  Can you use the function to output to a file?  Yes, if you are
 willing to do a little work in raw Common Lisp: open a stream to the file in
 question, set @('*standard-output*') to that stream, call your ACL2 function,
 and then close the stream and restore @('*standard-output*') to its nominal
 value.  Similar observations can be made about the two ACL2 input channels,
 @(tsee *standard-oi*) and @(tsee *standard-ci*), which are analogues of
 @('*standard-input*').</p>

 <p>Another reason you might have for wanting to change the actual streams
 associated with @(tsee *standard-oi*) and @('*standard-co*') is to drive the
 ACL2 top-level loop, @(tsee ld), on alternative input and output streams.
 This end can be accomplished easily within ACL2 by either calling @(tsee ld)
 on the desired channels or file names or by resetting the ACL2 @(tsee state)
 global variables @(''')@(tsee standard-oi) and @(''')@(tsee standard-co) which
 are used by @(tsee ld).  See @(see standard-oi) and see @(see
 standard-co).</p>")

(defxdoc *standard-oi*
  :parents (io acl2-built-ins)
  :short "An ACL2 object-based analogue of CLTL's @('*standard-input*')"
  :long "<p>The value of the ACL2 constant @('*standard-oi*') is an open object
 input channel that is synonymous to Common Lisp's @('*standard-input*').</p>

 <p>ACL2 object input from @('*standard-oi*') is actually obtained by reading
 from the stream named by Common Lisp's @('*standard-input*').  That is, by
 changing the setting of @('*standard-input*') in raw Common Lisp you can
 change the source from which ACL2 reads on the channel @('*standard-oi*').
 See @(see *standard-co*).</p>")

(defxdoc +
  :parents (numbers acl2-built-ins)
  :short "Addition macro"
  :long "<p>@('+') is really a macro that expands to calls of the function
 @(tsee binary-+).  So for example</p>

 @({
  (+ x y 4 z)
 })

 <p>represents the same term as</p>

 @({
  (binary-+ x (binary-+ y (binary-+ 4 z))).
 })

 <p>See @(see binary-+).</p>

 @(def +)")

(defxdoc -
  :parents (numbers acl2-built-ins)
  :short "Macro for subtraction and negation"
  :long "<p>See @(see binary-+) for addition and see @(see unary--) for
 negation.</p>

 <p>Note that @('-') represents subtraction as follows:</p>

 @({
  (- x y)
 })

 <p>represents the same term as</p>

 @({
  (+ x (- y))
 })

 <p>which is really</p>

 @({
  (binary-+ x (unary-- y)).
 })

 <p>Also note that @('-') represents arithmetic negation as follows:</p>

 @({
  (- x)
 })

 <p>expands to</p>

 @({
  (unary-- x).
 })

 @(def -)")

(defxdoc /
  :parents (numbers acl2-built-ins)
  :short "Macro for division and reciprocal"
  :long "<p>See @(see binary-*) for multiplication and see @(see unary-/) for
 reciprocal.</p>

 <p>Note that @('/') represents division as follows:</p>

 @({
  (/ x y)
 })

 <p>represents the same term as</p>

 @({
  (* x (/ y))
 })

 <p>which is really</p>

 @({
  (binary-* x (unary-/ y)).
 })

 <p>Also note that @('/') represents reciprocal as follows:</p>

 @({
  (/ x)
 })

 <p>expands to</p>

 @({
  (unary-/ x).
 })

 <p>@('/') is a Common Lisp macro.  See any Common Lisp documentation for more
 information.</p>

 @(def /)")

(defxdoc /=
  :parents (numbers acl2-built-ins)
  :short "Test inequality of two numbers"
  :long "<p>@('(/= x y)') is logically equivalent to @('(not (equal x
  y))').</p>

 <p>Unlike @(tsee equal), @('/=') has a @(see guard) requiring both of its
 arguments to be numbers.  Generally, @('/=') is executed more efficiently than
 a combination of @(tsee not) and @(tsee equal).</p>

 <p>For a discussion of the various ways to test against 0, See @(see
 zero-test-idioms).</p>

 <p>@('/=') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def /=)")

(defxdoc 1+
  :parents (numbers acl2-built-ins)
  :short "Increment by 1"
  :long "<p>@('(1+ x)') is the same as @('(+ 1 x)').  See @(see +).</p>

 <p>@('1+') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def 1+)")

(defxdoc 1-
  :parents (numbers acl2-built-ins)
  :short "Decrement by 1"
  :long "<p>@('(1- x)') is the same as @('(- x 1)').  See @(see -).</p>

 <p>@('1-') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def 1-)")

(defxdoc <
  :parents (numbers acl2-built-ins)
  :short "Less-than"
  :long "<p>Completion Axiom (@('completion-of-<')):</p>

 @({
  (equal (< x y)
         (if (and (rationalp x)
                  (rationalp y))
             (< x y)
           (let ((x1 (if (acl2-numberp x) x 0))
                 (y1 (if (acl2-numberp y) y 0)))
             (or (< (realpart x1) (realpart y1))
                 (and (equal (realpart x1) (realpart y1))
                      (< (imagpart x1) (imagpart y1)))))))
 })

 <p>@(see Guard) for @('(< x y)'):</p>

 @({
  (and (rationalp x) (rationalp y))
 })

 <p>Notice that like all arithmetic functions, @('<') treats non-numeric inputs
 as @('0').</p>

 <p>This function has the usual meaning on the rational numbers, but is
 extended to the complex rational numbers using the lexicographic order: first
 the real parts are compared, and if they are equal, then the imaginary parts
 are compared.</p>")

(defxdoc <=
  :parents (numbers acl2-built-ins)
  :short "Less-than-or-equal test"
  :long "<p>@('<=') is a macro, and @('(<= x y)') expands to the same thing as
 @('(not (< y x))').  See @(see <).</p>

 <p>@('<=') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def <=)")

(defxdoc =
  :parents (numbers equal equality-variants acl2-built-ins)
  :short "Test equality of two numbers"
  :long "<p>@('(= x y)') is logically equivalent to @('(equal x y)').</p>

 <p>Unlike @(tsee equal), @('=') has a @(see guard) requiring both of its
 arguments to be numbers.  Generally, @('=') is executed more efficiently than
 @(tsee equal).</p>

 <p>For a discussion of the various ways to test against 0, See @(see
 zero-test-idioms).</p>

 <p>@('=') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def =)")

(defxdoc >
  :parents (numbers acl2-built-ins)
  :short "Greater-than test"
  :long "<p>@('>') is a macro, and @('(> x y)') expands to the same thing as
 @('(< y x)').  See @(see <).</p>

 <p>@('>') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def >)")

(defxdoc >=
  :parents (numbers acl2-built-ins)
  :short "Greater-than-or-equal test"
  :long "<p>@('>=') is a macro, and @('(>= x y)') expands to the same thing as
 @('(not (< x y))').  See @(see <).</p>

 <p>@('>=') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def >=)")

(defxdoc @
  :parents (programming-with-state acl2-built-ins)
  :short "Get the value of a global variable in @(tsee state)"
  :long "@({
  Examples:
  (+ (@ y) 1)
  (assign a (aset1 'ascii-map-array (@ a) 66 'Upper-case-B))

  General Form:
  (@ symbol)
 })

 <p>where @('symbol') is any symbol to which you have @(tsee assign)ed a global
 value.  This macro expands into @('(f-get-global 'symbol state)'), which
 retrieves the stored value of the symbol.</p>

 <p>The macro @('f-get-global') is closely related to @(tsee @): @('(@ var)')
 macroexpands to @('(f-get-global 'var state)').</p>

 <p>The macro @(tsee assign) makes it convenient to set the value of a symbol.
 The @(':')@(tsee ubt) operation has no effect on the @('global-table') of
 @(tsee state).  Thus, you may use these globals to hang onto useful data
 structures even though you may undo back past where you computed and saved
 them.</p>")

(defxdoc |A Flying Tour of ACL2|
  :parents (|Pages Written Especially for the Tours|)
  :short "A Flying Tour of ACL2"
  :long "<p><see topic='@(url |About the ACL2 Home Page|)'><img
 src='res/tours/large-flying.gif'></img></see></p>

 <p>On this tour you will learn a little about what ACL2 is for rather than how
 ACL2 works.  At the top and bottom bottom of the ``page'' there are ``flying
 tour'' icons.  Click on either icon to go to the next page of the tour.</p>

 <p>The tour visits the following topics sequentially.  But on your first
 reading, don't navigate through the tour by clicking on these links; they are
 shown as live links only so that later you can determine what you've visited.
 Instead, just use the flying tour icons.</p>

 <code>
 <b>The Flight Plan</b>
 * <see topic='@(url |About the ACL2 Home Page|)'>This Documentation</see>
 * <see topic='@(url |What Is ACL2(Q)|)'>What is ACL2?</see>
 * <see topic='@(url |What is a Mathematical Logic(Q)|)'>Mathematical Logic</see>
 * <see topic='@(url |What is a Mechanical Theorem Prover(Q)|)'>Mechanical Theorem Proving</see>
 * <see topic='@(url |About Models|)'>Mathematical Models in General</see>
 * <see topic='@(url |Models of Computer Hardware and Software|)'>Mathematical Models of Computing Machines</see>
      <see topic='@(url |A Typical State|)'>Formalizing Models</see>
      <see topic='@(url |Running Models|)'>Running Models</see>
      <see topic='@(url |Symbolic Execution of Models|)'>Symbolic Execution of Models</see>
      <see topic='@(url |Proving Theorems about Models|)'>Proving Theorems about Models</see>
 * Requirements of ACL2
      <see topic='@(url |What is Required of the User(Q)|)'>The User's Skills</see>
      <see topic='@(url |How Long Does It Take to Become an Effective User(Q)|)'>Training</see>
      <see topic='@(url |Other Requirements|)'>Host System</see>
 </code>

 <p>On your first reading, don't explore other links you see in the tour.  Some
 of them lead to the Walking Tour, which you can take coherently when you
 finish this tour.  Others lead into the extensive hypertext documentation and
 you are liable to get lost there unless you're trying to answer a specific
 question.  We intend the tour to take about 10 minutes of your time.</p>

 <p><see topic='@(url |About the ACL2 Home Page|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |A Sketch of How the Rewriter Works|
  :parents (|Pages Written Especially for the Tours|)
  :short "A Sketch of How the Rewriter Works"
  :long "<p>Below we show the first target term, extracted from the current
 conjecture.  Below it we show the associativity rule.</p>

 <p><img src='res/tours/uaa-rewrite.gif'></img></p>

 <p>The variables of the rewrite rule are <b>instantiated</b> so that the
 <b>left-hand side</b> of the rule matches the target:</p>

 @({
       variable          term from target
         a                     x1
         b                     x2
         c                     (app x3 x4)
 })

 <p>Then the target is <b>replaced</b> by the instantiated <b>right-hand
 side</b> of the rule.</p>

 <p>Sometimes rules have <b>hypotheses</b>.  To make a long story short, if the
 rule has hypotheses, then after matching the left-hand side, the rewriter
 instantiates the hypotheses and rewrites them recursively.  This is called
 <b>backchaining</b>.  If they all rewrite to true, then the target is replaced
 as above.</p>

 <p>We discuss the rewriter in more detail in the extended introduction to how
 to use the theorem prover, see @(see introduction-to-the-theorem-prover),
 which we will recommend you work through <b>after</b> you have finished the
 two tours.</p>")

(defxdoc |A Tiny Warning Sign|
  :parents (|Pages Written Especially for the Tours|)
  :short "A Tiny Warning Sign"
  :long "<p><img src='res/tours/warning.gif'></img></p>

 <p>This warning sign, which usually appears as ``<icon src='res/tours/twarning.gif'/>'',
 indicates that the link it marks takes you into ACL2's online
 documentation.</p>

 <p>The documentation is a vast graph of documented topics intended to help the
 <i>user</i> of ACL2 rather than the <i>potential user</i>.  If you are
 exploring ACL2's home page to learn about the system, perhaps you should go
 back rather than follow the link marked with this sign.  But you are welcome
 to explore the online documentation as well.  Good luck.</p>")

(defxdoc |A Trivial Proof|
  :parents (|Pages Written Especially for the Tours|)
  :short "A Trivial Proof"
  :long "<p><img src='res/tours/concrete-proof.gif'></img></p>")

(defxdoc |A Typical State|
  :parents (|Pages Written Especially for the Tours|)
  :short "A Typical State"
  :long "<p><see topic='@(url |Functions for Manipulating these Objects|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p><img src='res/tours/state-object.gif'></img></p>

 <p>Observe that the states in typical models talk about</p>

 <code>
 <b>booleans</b>    <b>integers</b>   <b>vectors</b>     <b>records</b>   <b>caches</b>
 <b>bits</b>        <b>symbols</b>    <b>arrays</b>      <b>stacks</b>    <b>files</b>
 <b>characters</b>  <b>strings</b>    <b>sequences</b>   <b>tables</b>    <b>directories</b>
 </code>

 <p>These objects are <b>discrete</b> rather than <b>continuous</b>;
 furthermore they are built incrementally or <b>inductively</b> by repeatedly
 using primitive operations to put together smaller pieces.</p>

 <p>The functions we need to manipulate these objects do things like
 <b>concatenate</b>, <b>reverse</b>, <b>sort</b>, <b>search</b>, <b>count</b>,
 etc.</p>

 <p><see topic='@(url |Functions for Manipulating these Objects|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |A Walking Tour of ACL2|
  :parents (|Pages Written Especially for the Tours|)
  :short "A Walking Tour of ACL2"
  :long "<p><see topic='@(url |Common Lisp|)'><img
 src='res/tours/large-walking.gif'></img></see></p>

 <p>On this tour you will learn a little more about the ACL2 logic, the theorem
 prover, and the user interface.</p>

 <p>This time we will stick with really simple things, such as the
 associativity of list concatenation.</p>

 <p>We assume you have taken the Flying Tour but that you did not necessarily
 follow all the ``off-tour'' links because we encouraged you not to.  With the
 Walking Tour we encourage you to visit off-tour links &mdash; provided they
 are not marked with the tiny warning sign (<see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>).
 But they are ``branches'' in the tour that lead to ``dead ends.''  When you
 reach a dead end, remember to use your browser's Back Button to return to the
 Walking Tour to continue.</p>

 <p>When you get to the end of the tour we'll give you a chance to repeat
 quickly both the Flying and the Walking Tours to visit any off-tour links
 still of interest.</p>

 <p><see topic='@(url |Common Lisp|)'><img src='res/tours/walking.gif'></img></see></p>")

(defxdoc a!
  :parents (ld)
  :short "To return to the top-level of ACL2's command loop"
  :long "<p>When @('(a!)') is evaluated inside of ACL2's command loop, the
 current computation is aborted and control returns to the top of the command
 loop, exactly as though the user had interrupted and aborted the current
 computation.  (Note: Versions of ACL2 up to Version_3.4 provided `@('#.')' for
 this purpose, but no longer; see @(see sharp-dot-reader).)</p>

 <p>If you are at an ACL2 prompt (as opposed to a raw Lisp break), then you may
 type @(':a!') in place of @('(a!)'); see @(see keyword-commands).</p>

 <p>For a related feature that only pops up one level, see @(see p!).</p>

 <p>Logically speaking, @('(a!) = nil').  But imagine that it is defined in
 such a way that it causes a stack overflow or other resource exhaustion when
 called.</p>")

(defxdoc abort!
  :parents (ld)
  :short "To return to the top-level of ACL2's command loop"
  :long "<p>This is an alias for @('a!'); see @(see a!).  For a related feature
 that only pops up one level, see @(see p!).</p>")

(defxdoc about-acl2
  :parents (acl2)
  :short "General information About ACL2"
  :long "<p>This is @(`(:raw (@ acl2-version))`), @(see copyright) (C) 2017,
 Regents of the University of Texas, authored by Matt Kaufmann and J Strother
 Moore.</p>

 <p>See the <a href='http://www.cs.utexas.edu/users/moore/acl2/'>ACL2 home
 page</a> for additional information including tutorials, installation
 instructions, mailing lists, related publications, ACL2 workshops and
 seminars, acknowledgments, and other ACL2 releases.</p>

 <p>See @(see documentation) for how to access the ACL2 User's Manual.</p>

 <p>For statistics on ACL2 code size, see file @('doc/acl2-code-size.txt').</p>")

(defxdoc abs
  :parents (numbers acl2-built-ins)
  :short "The absolute value of a real number"
  :long "<p>@('(Abs x)') is @('-x') if @('x') is negative and is @('x')
 otherwise.</p>

 <p>The @(see guard) for @('abs') requires its argument to be a rational (@(see
 real), in ACL2(r)) number.</p>

 <p>@('Abs') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 <p>From ``Common Lisp the Language'' page 205, we must not allow complex
 @('x') as an argument to @('abs') in ACL2, because if we did we would have to
 return a number that might be a floating point number and hence not an ACL2
 object.</p>

 @(def abs)")

(defxdoc access
  :parents (defrec acl2-built-ins)
  :short "Accessor macro for @(see defrec) structures."
  :long "<p>The @('access') macro is built into ACL2, and allows you to access
 particular fields from structures that have been introduced with @(see
 defrec).  For instance:</p>

 @({
    (access employee x :name)
 })

 <p>would return the @('name') field from the employee @('x').  See @(see
 defrec) for more information.</p>")

(defxdoc accumulated-persistence
  :parents (debugging)
  :short "To get statistics on which @(see rune)s are being tried"
  :long "@({
  Useful Forms:
  (accumulated-persistence t)              ; Activate statistics gathering.
  (accumulated-persistence :all)           ; As above, ``enhanced'' (see below)

  (show-accumulated-persistence :frames)   ; Display statistics ordered by
  (show-accumulated-persistence :tries)    ; frames built, times tried,
  (show-accumulated-persistence :ratio)    ; or their ratio.
  (show-accumulated-persistence)           ; Same as supplying :frames argument.

  (accumulated-persistence nil)            ; Deactivate.

  (accumulated-persistence-oops)           ; Undo the clearing effect of
                                           ; (accumulated-persistence nil).

  Advanced forms:
  (show-accumulated-persistence :frames-s) ; The `s', `f', and `a' suffixes
  (show-accumulated-persistence :frames-f) ; stand for `success' (`useful'),
  (show-accumulated-persistence :frames-a) ; `failure' (`useless'), and `all',
  (show-accumulated-persistence :tries-s)  ; respectively.  The only effect of
  (show-accumulated-persistence :tries-f)  ; the `s' and `f' versions is to
  (show-accumulated-persistence :tries-a)  ; sort first by useful or useless
                                           ; applications, respectively (see
                                           ; below).  The `a' versions avoid
                                           ; showing the useful/useless
                                           ; breakdown.

  (show-accumulated-persistence :runes)    ; Just show runes alphabetically.
  (show-accumulated-persistence :useless)  ; Just show useless runes.
  (show-accumulated-persistence :useless :list)
                                           ; Just show useless runes as a list.
 })

 <p>In summary, @('(accumulated-persistence t)') turns on fresh statistics
 gathering for rules, @('(accumulated-persistence nil)') turns it off,
 @('(show-accumulated-persistence)') displays the statistics that were
 gathered, and @('(accumulated-persistence-oops)') restores the statistics, if
 any, that were cleared by @('(accumulated-persistence t)') or
 @('(accumulated-persistence :all)').</p>

 <p>In general, if the optional second argument of
 @('show-accumulated-persistence') is supplied as @(':list'), then instead of
 the result being displayed a ``pretty'' human-readable format, the result will
 be displayed as a corresponding list of entries of the form @('(frames tries
 xrune)').</p>

 <p>Note: @('set-accumulated-persistence') is equivalent to
 @('accumulated-persistence').</p>

 <p>See the end of this item for a discussion of ``enhanced statistics
 gathering,'' which can be useful for more fine-grained proof debugging.</p>

 <p>Generally speaking, the more ACL2 knows, the slower it runs.  That is
 because the search space grows with the number of alternative rules.  Often,
 the system tries to apply rules that you have forgotten were even there, if
 you knew about them in the first place!  ``Accumulated-persistence'' is a
 statistic (originally developed for Nqthm) that helps you identify the rules
 that are causing ACL2's search space to explode.</p>

 <p>For other proof debugging utilities, see @(see break-rewrite) and see @(see
 dmr).</p>

 <p>Accumulated persistence tracking can be turned on or off.  It is generally
 off.  When on, proofs may take perhaps 50% more time than otherwise!  But some
 useful numbers are collected.  When it is turned on, by</p>

 @({
  ACL2 !>(accumulated-persistence t)
 })

 <p>an accumulation site is initialized and henceforth data about which rules
 are being tried is accumulated into that site.  That accumulated data can be
 displayed with @('show-accumulated-persistence'), as described in detail
 below.  When accumulated persistence is turned off, with
 @('(accumulated-persistence nil)'), the accumulation site is wiped out and the
 data in it is lost.</p>

 <p>The ``accumulated persistence'' of a @(see rune) is the number of @(see
 rune)s the system has attempted to apply (since accumulated persistence was
 last activated) while the given @(see rune) was being tried.</p>

 <p>Consider a @(':')@(tsee rewrite) rule named @(tsee rune).  For simplicity,
 let us imagine that @(tsee rune) is tried only once in the period during which
 accumulated persistence is being monitored.  Recall that to apply a rewrite
 rule we must match the left-hand side of the conclusion to some term we are
 trying to rewrite, establish the hypotheses of @(tsee rune) by rewriting, and,
 if successful, then rewrite the right-hand side of the conclusion.  We say
 @(tsee rune) is ``being tried'' from the time we have matched its left-hand
 side to the time we have either abandoned the attempt or finished rewriting
 its right-hand side.  (By ``match'' we mean to include any loop-stopper
 requirement; see @(see loop-stopper).)  During that period of time other rules
 might be tried, e.g., to establish the hypotheses.  The rules tried while
 @(tsee rune) is being tried are ``billed'' to @(tsee rune) in the sense that
 they are being considered here only because of the demands of @(tsee rune).
 Thus, if no other rules are tried during that period, the accumulated
 persistence of @(tsee rune) is @('1') &mdash; we ``bill'' @(tsee rune) once
 for its own application attempt.  If, on the other hand, we tried @('10')
 rules on behalf of that application of @(tsee rune), then @(tsee rune)'s
 accumulated persistence would be @('11').</p>

 <p>One way to envision accumulated persistence is to imagine that every time a
 @(see rune) is tried it is pushed onto a stack.  The rules tried on behalf of
 a given application of a @(see rune) are thus pushed and popped on the stack
 above that @(see rune).  A lot of work might be done on its behalf &mdash; the
 stack above the @(see rune) grows and shrinks repeatedly as the search
 continues for a way to use the @(see rune).  All the while, the @(see rune)
 itself ``persists'' in the stack, until we finish with the attempt to apply
 it, at which time we pop it off.  The accumulated persistence of a @(see rune)
 application is thus the number of stack frames built while that @(see rune)
 was on the stack.</p>

 <p>Note that accumulated persistence is tallied whether or not the attempt to
 apply a @(see rune) is successful.  Each of the rules tried on its behalf
 might have failed and the attempt to apply the @(see rune) might have also
 failed.  The ACL2 proof script would make no mention of the @(see rune) or the
 rules tried on its behalf because they did not contribute to the proof.  But
 time was spent pursuing the possible application of the @(see rune) and
 accumulated persistence is a measure of that time.</p>

 <p>A high accumulated persistence might come about in two extreme ways.  One
 is that the rule causes a great deal of work every time it is tried.  The
 other is that the rule is ``cheap'' but is tried very often.  We therefore
 keep track of the number of times each rule is tried as well as its
 persistence.  The ratio between the two is the average amount of work done on
 behalf of the rule each time it is tried.</p>

 <p>When the accumulated persistence totals are displayed by the function
 @('show-accumulated-persistence') we sort them so that the most expensive
 @(see rune)s are shown first.  We can sort according to one of three basic
 keys:</p>

 @({
  :frames - the number of frames built on behalf of the rune
  :tries  - the number of times the rune was tried
  :ratio  - frames built per try
 })

 <p>The key simply determines the order in which the information is presented.
 If no argument is supplied to @('show-accumulated-persistence'), @(':frames')
 is used.</p>

 <p>The display breaks each total into ``useful'' and ``useless'' subtotals.  A
 ``useful'' rule try is one that is viewed as contributing to the progress of
 the proof, and the rest are ``useless'' rule applications.  For example, if a
 @(':')@(tsee rewrite) rule is tried but its hypotheses are not successfully
 relieved, then that rule application and all work done on behalf of those
 hypotheses is ``useless'' work.  In general, an attempt to apply a @(see rune)
 is viewed as ``useful'' unless the attempt fails or the attempt is on the
 stack (as described above) for a @(see rune) application that ultimately
 fails.  A large number of ``useless'' @(':frames') or @(':tries') along with
 correspondingly small ``useful'' counts may suggest @(see rune)s to consider
 disabling (see @(see disable) and see @(see in-theory)).  Thus, here is a more
 complete list of the arguments that may be supplied to
 @('show-accumulated-persistence').  Suffixes ``s'', ``f'', and ``a'' are
 intended to suggest ``success'' (``useful''), ``failure'' (``useless''), and
 ``all''.</p>

 @({
  :frames     - sort by the number of frames built on behalf of the rune
     :frames-s -   as above, but sort by useful applications
     :frames-f -   as above, but sort by useless applications
     :frames-a -   as above, but inhibit display of ``useful'' and
                   ``useless'' subtotals
  :tries      - sort by the number of times the rune was tried
     :tries-s  -   as above, but sort by useful applications
     :tries-f  -   as above, but sort by useless applications
     :tries-a  -   as above, but inhibit display of ``useful'' and
                   ``useless'' subtotals
  :ratio      - sort by frames built per try
  :useless    - show only the runes tried whose tries were all ``useless''
 })

 <p>For a given line of the report, every frame credited to a ``useful''
 (respectively, ``useless'') rule application is considered ``useful''
 (respectively, ``useless'').  We illustrate with the following example.</p>

 @({
  (progn
    (defstub hyp (x) t)
    (defstub concl (x) t)
    (defstub bad (x) t)
    (defstub good (x) t)
    (defaxiom good-ax
      (implies (good x) (hyp x)))
    (defaxiom bad-ax
      (implies (bad x) (hyp x)))
    (defaxiom hyp-implies-concl
      (implies (hyp x) (concl x)))
    )
  (accumulated-persistence t)
  (thm (implies (good x) (concl x)))
  (show-accumulated-persistence)
 })

 <p>To prove the @(tsee thm) form, ACL2 attempts to rewrite @('(concl x)') to
 true by applying rule @('hyp-implies-concl').  It then attempts to establish
 @('(hyp x)') first by trying rule @('bad-ax'), which fails, and second by
 trying rule @('good-ax'), which succeeds.  As expected, the report labels as
 ``useless'' the failure of the attempt to establish the hypothesis, @('(bad
 x)').</p>

 @({
     --------------------------------
           1        1 (    1.00) (:REWRITE BAD-AX)
           0        0    [useful]
           1        1    [useless]
     --------------------------------
 })

 <p>Now consider the top-level application of rule @('hyp-implies-concl').
 Even though the above report shows the application of @('bad-ax') as
 ``useless'', note that this rule was applied on behalf of the successful
 (``useful'') application of @('hyp-implies-concl'), and hence is incorporated
 into the ``useful'' line for @('hyp-implies-concl'), as follows.</p>

 @({
     --------------------------------
           3        1 (    3.00) (:REWRITE HYP-IMPLIES-CONCL)
           3        1    [useful]
           0        0    [useless]
     --------------------------------
 })

 <p>In summary: categorization of @(':frames') as ``useful'' or ``useless'' is
 based on whether they support ``useful'' or ``useless'' @(':tries').</p>

 <p>Note that a @(see rune) with high accumulated persistence may not actually
 be the ``culprit.''  For example, suppose @('rune1') is reported to have a
 @(':ratio') of @('101'), meaning that on the average a hundred and one frames
 were built each time @('rune1') was tried.  Suppose @('rune2') has a
 @(':ratio') of @('100').  It could be that the attempt to apply @('rune1')
 resulted in the attempted application of @('rune2') and no other @(see rune).
 Thus, in some sense, @('rune1') is ``cheap'' and @('rune2') is the ``culprit''
 even though it is reported as costing less than @('rune1').</p>

 <p>If a proof is aborted, then in general, @(tsee
 show-accumulated-persistence) will only display totals for runes whose
 attempted application is complete: that is, if the rewriter was in the process
 of relieving hypotheses for a rule, then information for that rule will not be
 included in the tally.  We say ``in general'' because, as indicated near the
 top of the output from @(tsee show-accumulated-persistence) when such
 incomplete information is omitted, you can get this information by using
 argument @(':frames-a') or @(':tries-a').</p>

 <p>There are other subtleties in how rune applications are tallied, documented
 elsewhere: see @(see accumulated-persistence-subtleties).</p>

 <p>We conclude with a discussion of ``enhanced'' statistics gathering, which
 is enabled by supplying @('accumulated-persistence') the argument
 @(':ALL'):</p>

 @({
  (accumulated-persistence :all)
 })

 <p>At some additional performance expense (but probably well under a factor of
 2 altogether), ACL2 then gathers additional statistics for individual
 hypotheses of rules as well as their conclusions.  To understand how this
 works, suppose @('rn') is a @(see rune).  Then we prepend the keyword
 @(':CONC') to @('rn') to form what we call its ``conclusion xrune'', and for
 its @('I')-th hypothesis we prepend @(':HYP I') to @('rn') to form its
 @('I')-th ``hypothesis xrune.''  Here, ``xrune'' is pronounced ``ex rune'',
 and is mnemonic for ``extended rune.''  For example, if @('(REWRITE FOO)') is
 a @(see rune) then @('(:CONC REWRITE FOO)') is its conclusion xrune, and
 @('(:HYP 2 REWRITE FOO)') is a hypothesis xrune corresponding to the second
 hypothesis of the corresponding rewrite rule.</p>

 <p>With @('(accumulated-persistence :all)'), we instruct ACL2 to track not
 only runes but also xrunes.  Then, @('(show-accumulated-persistence)') will
 display information for all xrunes in a format that we consider to be ``raw'',
 in the sense that data for xrunes are displayed just as for runes.  But a
 ``merged'' format is also available.  Here is a summary of display commands,
 followed below by further discussion.</p>

 @({
    (show-accumulated-persistence :frames t) ; t is optional, i.e., the default
       ; Display enhanced statistics sorted by frames, in a ``raw'' format.
    (show-accumulated-persistence :frames :merge)
       ; Display enhanced statistics sorted by frames, in a ``merged'' format.
    (show-accumulated-persistence :frames nil)
       ; Display regular statistics sorted by frames
       ; (runes only, that is, without the enhancements).
    (show-accumulated-persistence :frames :merge)
       ; Display a list of entries (frames tries xrune), sorted by frames

    ; More generally, the descriptions just above apply for any legal first
    ; argument:

    (show-accumulated-persistence KEY t)
    (show-accumulated-persistence KEY :merge)
    (show-accumulated-persistence KEY nil)
    (show-accumulated-persistence KEY :list)

    ; Note also these alternate forms, equivalent to the first of the two forms
    ; just above, i.e., the form with second argument of t:
    (show-accumulated-persistence KEY :raw)
    (show-accumulated-persistence KEY)
 })

 <p>There is a significant difference between how runes are tracked and how
 ACL2 tracks hypothesis and conclusion xrunes: unlike regular runes, these
 xrunes do not contribute to the accumulated @(':frames') counts.  Rather, they
 serve as accumulation sites without contributing their @(':tries') to any
 accumulation.  Consider for example the snippet below, taken from a report
 created with the @(':merge') option (to be discussed further below), i.e., by
 evaluating the form @('(show-accumulated-persistence :frames :merge)').</p>

 @({
     :frames   :tries    :ratio  rune
     --------------------------------
         462      211 (    2.18) (:REWRITE PERM-MEM)
          13        6    [useful]
         449      205    [useless]
        .............................
         251       47 (    5.34) (:HYP 2 :REWRITE PERM-MEM)
           6        6    [useful]
         245       41    [useless]
        .............................
           0      211 (    0.00) (:HYP 1 :REWRITE PERM-MEM)
           0        6    [useful]
           0      205    [useless]
        .............................
           0        7 (    0.00) (:CONC :REWRITE PERM-MEM)
           0        6    [useful]
           0        1    [useless]
     --------------------------------
 })

 <p>Notice that while @(':tries') are recorded for the xrune @('(:HYP 1
 :REWRITE PERM-MEM)'), no @(':frames') are recorded.  This is because no stack
 frames were built for runes while this xrune was on the stack &mdash; only for
 the xrune itself, which as we explained above is not accumulated into the
 total @(':frames') counts.  As it turns out, this lack of stack frames is
 explained by the fact that the rewrite rule @('PERM-MEM') has a free variable
 in the first hypothesis.</p>

 @({
  ACL2 !>:pe perm-mem
           18  (DEFTHM PERM-MEM
                       (IMPLIES (AND (PERM X Y) (MEM A X))
                                (MEM A Y))
                       :RULE-CLASSES ((:REWRITE :MATCH-FREE :ONCE)))
  ACL2 !>
 })

 <p>The second hypothesis, however, does cause additional rewriting in order to
 rewrite it to true, resulting in 251 stack frames for runes.  We see that the
 conclusion does not lead to creation of any rune stack frames, which might
 seem to suggest that only 251 stack frames for runes were created on behalf of
 this rule application &mdash; yet, we see that 462 frames were actually
 created.  The difference is the 211 frames created for the rewrite rule
 itself.  Even if the total had been a bit more than 462, one need not be
 surprised, as there could be some work recorded during application of the
 rewrite rule, such as type-prescription reasoning, that is not done during
 rewriting of a hypothesis or the conclusion.</p>

 <p>Now suppose we have executed @('(accumulated-persistence :all)') and
 attempted some proofs, and now we are ready to see statistics.  The form
 @('(show-accumulated-persistence)') displays statistics exactly as described
 above, treating these extra xrunes just as though they are runes; similarly
 for the form @('(show-accumulated-persistence KEY)'), for any legal @('KEY').
 A second optional argument may however be supplied to
 @('show-accumulated-persistence').  The default for that second argument is
 @('t'), and a second argument of @(':raw') is treated the same as @('t');
 thus, these arguments provide the behavior just described, where data for
 xrunes are displayed just as for runes.  You may restrict output to runes,
 ignoring hypothesis and conclusion xrunes, by giving a second argument of
 @('nil').  (This gives the same behavior as if we had started with the command
 @('(accumulated-persistence t)') instead of the command
 @('(accumulated-persistence :all)').)  You may give a second argument
 of @(':merge'), in which case output will be sorted and displayed as though
 only runes were tracked (not the extra xrunes), but each data item for a
 non-rune xrune will be merged so that it is displayed in suitable order just
 below its corresponding rune, as in the @('PERM-MEM') example displayed
 above.  Finally, you may give a second argument of @(':list'), which is
 equivalent to the default second argument of @('t'), except that the results
 are printed as a list of entries @('(frames tries xrune)').</p>

 <p>We close by mentioning two aspects of enhanced statistics display for
 @(':CONC') xrunes that have potential to be confusing.  First consider the
 following example.</p>

 @({
       :frames   :tries    :ratio  rune
     --------------------------------
          14        4 (    3.50) (:REWRITE DEFAULT-+-2)
           0        0    [useful]
          14        4    [useless]
        .............................
          10        4 (    2.50) (:HYP 1 :REWRITE DEFAULT-+-2)
           0        0    [useful]
          10        4    [useless]
     --------------------------------
 })

 <p>It may be surprising that no data is displayed for the corresponding
 @(':CONC') xrune.  The explanation, however, is simple: the hypothesis never
 rewrote to true, so the conclusion was never rewritten.  This is consistent
 with the marking as ``useless'' of all @(':frames') and @(':tries') for the
 rune and the hypothesis xrune.  Note by the way, once again, that the
 hypothesis xrune does not contribute to any @(':frames') count.</p>

 <p>Another reason not to see data displayed for a @(':CONC') xrune is that if
 a rule has no hypotheses, then no such data is collected.  This decision was
 made because in the case of no hypotheses, we expect it to be very rare that
 information for the @(':CONC') xrune will add any useful insight.</p>

 <p>On a final note: @('(show-accumulated-persistence :runes)') may be used
 simply to see a list of all @(see rune)s (or xrunes) displayed
 alphabetically.</p>

 <p>Users are encouraged to think about other meters we could install in ACL2
 to help diagnose performance problems.</p>")

(defxdoc accumulated-persistence-subtleties
  :parents (accumulated-persistence)
  :short "Some subtle aspects of the counting done by @(tsee accumulated-persistence)"
  :long "<p>In this topic we cover the overcounting of ``useful'' and of
 recursive @(see rune) application attempts, and we describe how ``useless''
 @(see rune) application attempts can actually be critical for a proof's
 success.</p>

 <p><i>Overcounting of ``useful'' and of recursive rune application
 attempts.</i> Not every @(see rune) application may be necessary for a proof's
 success.  Consider for example:</p>

 @({
  (thm (equal (car (cons a (cdr (cons b x))))
              a))
 })

 <p>Then @('show-accumulated-persistence') will tell us that @(':')@(tsee
 rewrite) rules @('car-cons') and @('cdr-cons') each had one useful
 application.  However, the rule @('cdr-cons') is used to simplify @('(cdr
 (cons b x))') to @('x'), and this simplification is unnecessary for the proof.
 Indeed, the proof succeeds even when preceded by the event: @('(in-theory
 (disable cdr-cons))').  We thus see that a @(see rune) application labeled as
 ``useful'' may be simplifying a term that is not relevant to the proof.</p>

 <p>As of this writing, we consider every @(':')@(tsee forward-chaining) rule
 application to be ``useful'', for simplicity of the implementation.  Moreover,
 our counting of these rules is such that a single rule may be counted more
 than once.</p>

 <p>Next we show how recursive rule applications are overcounted.  Consider the
 following example.</p>

 @({
  (defun mem (a x)
    (if (atom x)
        nil
      (or (equal a (car x)) (mem a (cdr x)))))
 })

 <p>Now suppose we consider the sequence of theorems @('(mem a (list a))'),
 @('(mem a (list 1 a))'), @('(mem a (list 1 2 a))'), @('(mem a (list 1 2 3
 a))'), and so on.  We will see that the @(':frames') reported for each
 increases quadratically, even though the @(':tries') increases linearly; so in
 this case the @(':tries') statistics are more appropriate.  Each time the
 definition of @('mem') is applied, a new stack frame is pushed (see @(see
 accumulated-persistence)), and all subsequent applications of that definition
 are accumulated into the @(':frames') count for that stack frame.  The final
 @(':frames') count will be the sum of the counts for those individual frames,
 which form a linear sequence whose sum is therefore quadratic in the number of
 applications of the definition of @('mem').</p>

 <p><i>How ``useless'' attempts can be critical for a proof's success.</i> The
 command @('(accumulated-persistence :useless'))] will list rules that did not
 contribute directly to the proof (see @(see accumulated-persistence), in
 particular the discussion of ``useless'' there).  However, a ``useless'' rule
 can on rare occasions be critical to the success of a proof.  In the following
 example, we have a ``bad'' rule that can take the proof in the wrong
 direction, but a ``useless'' rule does a rewrite that prevents the successful
 relieving of a hypothesis of the ``bad'' rule.  In summary:</p>

 @({
  ; Assume p0.  We want to prove p1.

  ; Key rule:
  p0 -> p1 = t

  ; Bad rule that could ruin the proof:
  p3 -> p1 = p2

  ; But unfortunately, we know p3:
  p0 -> p3

  ; Important ``useless'' rule, preventing ``bad rule'' above from firing:
  p3 = p4
 })

 <p>The following event captures the rules described above.</p>

 @({
  (encapsulate
   ((p0 (x) t)
    (p1 (x) t)
    (p2 (x) t)
    (p3 (x) t)
    (p4 (x) t))
   (local (defun p0 (x) x))
   (local (defun p1 (x) x))
   (local (defun p2 (x) x))
   (local (defun p3 (x) x))
   (local (defun p4 (x) x))

  ; Key rule:
   (defthm p0-implies-p1
     (implies (p0 x)
              (p1 x)))

  ; Bad rule that could ruin the proof:
   (defthm p3-implies-p1-is-p2
     (implies (p3 x)
              (equal (p1 x) (p2 x))))

  ; But unfortunately, we know p3:
   (defthm p0-implies-p3
     (implies (p0 x)
              (p3 x)))

  ; Important ``useless'' rule, preventing p3-implies-p1-is-p2 from firing:
   (defthm p3-is-p4
     (equal (p3 x) (p4 x))))
 })

 <p>Now we can see that @('p3-is-p4') is labeled as ``useless'', by evaluating
 these commands.</p>

 @({
  (accumulated-persistence t)
  (thm (implies (p0 x) (p1 x)))
  (show-accumulated-persistence)
 })

 <p>If instead we first evaluate @('(in-theory (disable p3-is-p4))') before the
 @('thm') above, then the proof fails, even though @('p3-is-p4') was labeled as
 ``useless''!</p>

 <p>Nevertheless, in general it is probably safe to disable rules reported as
 ``useless'' by @('(show-accumulated-persistence :useless)'), and doing so may
 speed up a proof considerably.</p>

 <p>Remark. The example above suggests a surprising fact: on rare occasions, a
 proof may fail when you give an @(':')@(tsee in-theory) hint consisting of
 exactly the @(see rune)s reported in a proof that succeeds.  For, imagine a
 rule R that is needed in part of the proof but is ``bad'' in a second part,
 and that some other, ``useless'' rule prevents the application of R in that
 second part.  The example above suggests that disabling this ``useless'' rule
 can allow the second application of R, thus preventing the proof.</p>")

(defxdoc acknowledgments
  :parents (about-acl2)
  :short "Some contributors to the well-being of ACL2"
  :long "<p>The development of ACL2 was initially made possible by funding from
 the U. S. Department of Defense, including ARPA and ONR.  We thank all the
 organizations that have contributed support, including the following (in
 alphabetical order).</p>

 <ul>

 <li>AMD, for providing significant time over several years for Matt Kaufmann
 to carry out ACL2 research, support, and development</li>

 <li>Computational Logic, Inc. and its president, Don Good, where the first
 eight years of ACL2 development occurred</li>

 <li>Centaur Technology</li>

 <li>DARPA</li>

 <li>Digital Equipment Corporation</li>

 <li>EDS, which provided some time for Matt Kaufmann's ACL2 work 1998-1999</li>

 <li>ForrestHunt and, more generally, Warren A. Hunt, Jr. (see below)</li>

 <li>IBM</li>

 <li>NSF</li>

 <li>ONR</li>

 <li>Rockwell Collins</li>

 <li>SRC</li>

 <li>Sun Microsystems</li>

 <li>University of Texas at Austin (in particular support to J Moore through the
 Admiral B. R.  Inman Chair of Computing Theory)</li>

 </ul>

 <p>We are especially grateful to Warren A. Hunt, Jr. for his unrivaled efforts
 in securing support for the entire ACL2 research group at both Computational
 Logic, Inc., and the University of Texas at Austin.  Without his efforts, we
 would have spent less time working on the system and fewer students would have
 been funded to apply it.</p>

 <p>ACL2 was started in August, 1989 by Boyer and Moore working together.  They
 co-authored the first versions of axioms.lisp and basis.lisp, with Boyer
 taking the lead in the formalization of ``@(see state)'' and the most
 primitive @(see io) functions.  Boyer also had a significant hand in the
 development of the early versions of the files interface-raw.lisp and
 translate.lisp.  For several years, Moore alone was responsible for developing
 the ACL2 system code, though he consulted often with both Boyer and Kaufmann.
 In August, 1993, Kaufmann became jointly responsible with Moore for developing
 the system.  Boyer has continued to provide valuable consulting on an informal
 basis.</p>

 <p>Bishop Brock was the heaviest early user of ACL2, and provided many
 suggestions for improvements.  In particular, the @(':cases') and
 @(':restrict') @(see hints) were his idea; he developed an early version of
 congruence-based reasoning for Nqthm; and he helped in the development of some
 early @(see books) about arithmetic.  In a demonstration of his courage and
 faith in us, he pushed for Computational Logic, Inc., to agree to the Motorola
 CAP contract &mdash; which required formalizing a commercial DSP in the
 untested ACL2 &mdash; and moved to Scottsdale, AZ, to do the work with the
 Motorola design team.  His demonstration of ACL2's utility was an inspiration,
 even to those of us designing ACL2.</p>

 <p>John Cowles also helped in the development of some early @(see books) about
 arithmetic, and also provided valuable feedback and bug reports.</p>

 <p>Other early users of ACL2 at Computational Logic, Inc. helped influence its
 development.  In particular, Warren Hunt helped with the port to Macintosh
 Common Lisp, and Art Flatau and Mike Smith provided useful general
 feedback.</p>

 <p>Mike Smith helped develop the Emacs portion of the implementation of proof
 trees.</p>

 <p>Bill Schelter made some enhancements to akcl (now gcl) that helped to
 enhance ACL2 performance in that Common Lisp implementation, and more
 generally, responded helpfully to our bug reports.  Camm Maguire has since
 provided wonderful gcl support, and has created a Debian package for ACL2
 built on GCL.  We are also grateful to developers of other Common Lisp
 implementations.</p>

 <p>Kent Pitman helped in our interaction with the ANSI Common Lisp
 standardization committee, X3J13.</p>

 <p>John Cowles helped with the port to Windows (98) by answering questions and
 running tests.</p>

 <p>Ruben Gamboa created a modification of ACL2 to allow reasoning about the
 real numbers using non-standard analysis.  His work has been incorporated into
 the ACL2 distribution; see @(see real).</p>

 <p>Rob Sumners has made numerous useful suggestions.  In particular, he has
 designed and implemented improvements for @(see stobj)s and been key in our
 development of locally-bound stobjs; see @(see note-2-6).</p>

 <p>Robert Krug has designed and implemented many changes in the vicinity of
 the linear arithmetic package and its connection to type-set and rewrite.  He
 was also instrumental in the development of @(see extended-metafunctions).</p>

 <p>Pete Manolios has made numerous useful suggestions.  In particular, Pete
 helped us to organize the first workshop and was a wonderful equal partner
 with the two of us (Kaufmann and Moore) in producing the books that arose from
 that workshop.  Pete and his student, Daron Vroon, provided the current
 implementation of @(see ordinals).</p>

 <p>Jared Davis, Sol Swords, and David Rager have our gratitude for starting
 the <a href='https://github.com/acl2/acl2/'>ACL2+Books repository</a>.</p>

 <p>We thank David L. Rager for contributing an initial version of the support
 for @(see parallelism) in an experimental extension of ACL2.</p>

 <p>Bob Boyer and Warren A. Hunt, Jr. developed a canonical representation for
 ACL2 data objects, applicative hash tables, and a function memoization
 mechanism to facilitate reuse of previously computed results.  Subsequently,
 Jared Davis and Sol Swords made further contributions.  We thank them all for
 this work, most of which has been incorporated into ACL2; see @(see
 hons-and-memoization).</p>

 <p>We also thank the contributors to the ACL2 workshops for some suggested
 improvements and for the extensive collection of publicly distributed
 benchmark problems.  And we thank participants at the ACL2 seminar at the
 University of Texas for useful feedback.  More generally, we thank the ACL2
 community for feedback, contributed @(see books) (see @(see community-books)),
 and their interest in the ACL2 project.</p>

 <p><i>Regarding the documentation:</i></p>

 <blockquote><p>Bill Young wrote significant portions of the original
 @('acl2-tutorial') section of the ACL2 documentation, including what is now
 called @(see alternative-introduction).  This was an especially important task
 in the early years when there was no guide for how to use ACL2 and we are very
 grateful.  He, Bishop Brock, Rich Cohen, and Noah Friedman read over
 considerable amounts of the documentation, and made many useful comments.
 Others, particularly Bill Bevier and John Cowles, have also made useful
 comments on the @(see documentation).</p>

 <p>Art Flatau helped develop the ACL2 markup language in which ACL2 @(see
 documentation) was originally developed, along with translators from that
 language to Texinfo and HTML.  Michael ``Bogo'' Bogomolny created a search
 engine, beginning with Version 2.6, and for that purpose modified the HTML
 translator to create one file per topic (a good idea in any case).</p>

 <p>Laura Lawless provided many hours of help in marking up appropriate parts
 of the @(see documentation) in typewriter font.</p>

 <p>Noah Friedman developed an Emacs tool that helped us insert ``invisible
 links'' into the @(see documentation), which improve the usability of that
 documentation under HTML readers such as Mosaic.</p>

 <p>Richard Stallman contributed a texinfo patch, to be found in the file
 @('doc/texinfo.tex').</p>

 <p>Jared Davis created the @(see xdoc) system that is now the basis not only
 for the ACL2 system @(see documentation) (file
 @('books/system/doc/acl2-doc.lisp')), but also for the @(see community-books)
 documentation.</p>

 </blockquote>

 <p>We thank Blake Grugett for designing the current version of the ACL2 logo
 (which for example appears on the ACL2 home page), based on an original design
 created in the 1990s by Computational Logic, Inc.</p>

 ")

(defxdoc acl2
  :parents (top)
  :short "ACL2 documentation (system only, not including the community books)"
  :long "<p>This is the ACL2 documentation.  For the ACL2+Books Manual, which
  that includes both the ACL2 documentation and the ACL2 @(see
  community-books), see the @(`(:raw (combined-manual-ref))`).</p>")

(defxdoc |ACL2 Characters|
  :parents (|Pages Written Especially for the Tours|)
  :short "ACL2 Characters"
  :long "<p>ACL2 accepts 256 distinct characters, which are the characters
 obtained by applying the function @(tsee code-char) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 to each integer from 0 to 255.  Among these, Common Lisp designates certain
 ones as @('*standard-characters*'), namely those of the form @('(code-char
 n)') where n is from 33 to 126, together with @('#\\Newline') and
 @('#\\Space').  The actual standard characters may be viewed by evaluating the
 constant expression @('*standard-chars*').</p>

 <p>The standard character constants are written by writing a hash mark
 followed by a backslash (#\\) followed by the character.</p>

 <p>The function @(tsee characterp) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 recognizes characters.  For more details, See @(see characters) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>")

(defxdoc |ACL2 Conses or Ordered Pairs|
  :parents (|Pages Written Especially for the Tours|)
  :short "ACL2 Conses or Ordered Pairs"
  :long "<p>The function @(tsee cons) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 creates an ordered pair.  @(tsee Car) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> and
 @(tsee cdr) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> return the first and second components,
 respectively, of an ordered pair.  The function @(tsee consp) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 recognizes ordered pairs.</p>

 <p>Ordered pairs are used to represent lists and trees.  See any Common Lisp
 documentation for a discussion of how list constants are written and for the
 many list processing functions available.  Also, see @(see programming) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 where we list all the ACL2 primitive functions.</p>

 <p>Here are some examples of list constants to suggest their syntax.</p>

 @({
  '(a . b)                ; a pair whose car is 'a and cdr is 'b
  '(a . nil)              ; a pair whose car is 'a and cdr is nil
  '(a)                    ; another way to write the same thing
  '(a b)                  ; a pair whose car is 'a and cdr is '(b)
  '(a b c)                ; a pair whose car is 'a and cdr is '(b c)
                          ;  i.e., a list of three symbols, a, b, and c.
  '((a . 1) (b . 2))      ; a list of two pairs
 })

 <p>It is useful to distinguish ``proper'' conses from ``improper'' ones, the
 former being those cons trees whose right-most branch terminates with
 @('nil').  A ``true list'' (see @(see true-listp) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>) is
 either @('nil') or a proper cons.  @('(A b c . 7)') is an improper cons and
 hence not a true list.</p>")

(defxdoc |ACL2 Strings|
  :parents (|Pages Written Especially for the Tours|)
  :short "ACL2 Strings"
  :long "<p>Strings of ACL2 <see topic='@(url
 |ACL2 Characters|)'>characters</see> are written as sequences of characters
 delimited by ``double quotation marks''
 (\").  To put a double quotation mark in a string (or, any other character
 such as backslash or newline that seems to cause problems), escape it by
 preceding it with a backslash (\\).</p>

 <p>The function @(tsee stringp) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 recognizes strings and @(tsee char) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 will fetch the nth character of a string.  There are many other primitives for
 handling strings, such as @(tsee string<) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> for
 comparing two strings lexicographically.  We suggest you See @(see
 programming) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> where we list all of the primitive ACL2 functions.
 Alternatively, see any Common Lisp language documentation.</p>")

(defxdoc |ACL2 Symbols|
  :parents (|Pages Written Especially for the Tours|)
  :short "ACL2 Symbols"
  :long "<p>Common Lisp's symbols are a data type representing words.  They are
 frequently regarded as atomic objects in the sense that they are not
 frequently broken down into their constituents.  Often the only important
 properties of symbols is that they are not numbers, characters, strings, or
 lists and that two symbols are not equal if they look different (!).  Examples
 of symbols include @('PLUS') and @('SMITH::ABC').  All function and variable
 names in ACL2 are symbols.  When symbols are used as constants they must be
 quoted, as in @(''PLUS').</p>

 <p>The symbol @('T') is commonly used as the Boolean ``true.''  The symbol
 @('NIL') is commonly used both as the Boolean ``false'' and as the ``empty
 list.''  Despite sometimes being called the ``empty list'' @('NIL') is a
 <b>symbol</b> not an ``empty cons.''  Unlike other symbols, @('T') and
 @('NIL') may be used as constants without quoting them.</p>

 <p>Usually, symbols are written as sequences of alphanumeric characters other
 than those denoting numbers.  Thus, @('A12'), @('+1A') and @('1+') are symbols
 but @('+12') is a number.  Roughly speaking, when symbols are read lower case
 characters are converted to upper case, so we frequently do not distinguish
 @('ABC') from @('Abc') or @('abc').  Click <see topic='@(url
 |Conversion|)'>here</see> for information about case conversion when symbols
 are read.  However, any character can be used in a symbol, but some characters
 must be ``escaped'' to allow the Lisp reader to parse the sequence as a
 symbol.  For example, @('|Abc|') is a symbol whose first character is
 capitalized and whose remaining characters are in lower case.  @('|An odd
 duck|') is a symbol containing two #\\Space characters.  See any Common Lisp
 documentation for the syntactic rules for symbols.</p>

 <p>Technically, a symbol is a special kind of pair consisting of a package
 name (which is a string) and a symbol name (which is also a string).  (See
 @(see symbol-package-name) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> and
 see @(see symbol-name) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.)  The symbol SMITH::ABC is said to be in package
 \"SMITH\" and to have the symbol name \"ABC\".  The symbol @('ABC') in package
 \"SMITH\" is generally not equal to the symbol @('ABC') in package \"JONES\".
 However, it is possible to ``import'' symbols from one package into another
 one, but in ACL2 this can only be done when the package is created.  (See
 @(see defpkg) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.)  If the @(tsee current-package) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> is
 \"SMITH\" then @('SMITH::ABC') may be more briefly written as just @('ABC').
 @(tsee Intern) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> ``creates'' a symbol of a given name in a given
 package.</p>")

(defxdoc |ACL2 System Architecture|
  :parents (|Pages Written Especially for the Tours|)
  :short "ACL2 System Architecture"
  :long "<p><see topic='@(url
 |Rewrite Rules are Generated from DEFTHM Events|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p><img src='res/tours/acl2-system-architecture.gif'></img></p>

 <p>The user interacts with the theorem prover by giving it definitions,
 theorems and advice.  Most often the advice is about how to store each proved
 theorem as a rule.  Sometimes the advice is about how to prove a specific
 theorem.</p>

 <p>The database consists of all the rules ACL2 ``knows.''  It is possible to
 include in the database all of the rules in some certified file of other
 events.  Such certified files are called @(see books) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p>Interesting proofs are usually built on top of many books, some of which
 are written especially for that problem domain and others of which are about
 oft-used domains, like arithmetic or list processing.  ACL2's distribution
 includes many books written by users.  See the ``books'' link under the
 <b>Lemma Libraries and Utilities</b> <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 link of the ACL2 home page.</p>

 <p><see topic='@(url |Rewrite Rules are Generated from DEFTHM Events|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |ACL2 as an Interactive Theorem Prover|
  :parents (|Pages Written Especially for the Tours|)
  :short "ACL2 as an Interactive Theorem Prover"
  :long "<p>The ACL2 theorem prover finds proofs in the ACL2 logic.  It can be
 automatic.  But most often the user must help it.</p>

 <p><img src='res/tours/interactive-theorem-prover.gif'></img></p>

 <p>The user usually guides ACL2 by suggesting that it first prove key
 <b>lemmas</b>.  Lemmas are just theorems used in the proofs of other
 theorems.</p>")

(defxdoc |ACL2 as an Interactive Theorem Prover (cont)|
  :parents (|Pages Written Especially for the Tours|)
  :short "ACL2 as an Interactive Theorem Prover (cont)"
  :long "<p><see topic='@(url |ACL2 System Architecture|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>When ACL2 proves a lemma, it is converted into one or more <b>rules</b> and
 stored in a <b>database</b>.  The theorem prover is <b>rule-driven</b>.  By
 proving lemmas you can configure ACL2 to behave in certain ways when it is
 trying to prove formulas in a certain problem domain.  The expert user can
 make ACL2 do amazingly ``smart'' looking things.</p>

 <p>But it would be wrong to think that ACL2 <i>knows</i> the mathematical
 content of a formula just because it has proved it.  What ACL2 knows &mdash;
 all ACL2 knows &mdash; is what is encoded in its rules.  There are many types
 of rules (see @(see rule-classes) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>).</p>

 <p>Many formulas can be effectively coded as rules.  But by the same token, it
 is possible to encode a formula as a rule that is so ineffective it cannot
 even prove itself!</p>

 <p>The way a formula is stored as a rule is entirely up to the user.  That is,
 <b>you</b> determine how ACL2 should use each formula that it proves.</p>

 <p>The most common kind of rule is the <b>rewrite rule</b>.  It is so common
 that if you don't tell ACL2 how to store a formula, it stores it as a rewrite
 rule.</p>

 <p><see topic='@(url |ACL2 System Architecture|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |ACL2 is an Untyped Language|
  :parents (|Pages Written Especially for the Tours|)
  :short "ACL2 is an Untyped Language"
  :long "<p>The example</p>

 <code>
 ACL2 !&gt;<b>(app '(a b c) 27)</b>
 (A B C . 27)
 </code>

 <p>illustrates the fact that ACL2's logic is untyped (click <see topic='@(url
 |About Types|)'>here</see> for a brief discussion of the typed versus untyped
 nature of the logic).</p>

 <p>The definition of @('app') makes no restriction of the arguments to lists.
 The definition says that if the first argument satisfies @(tsee endp) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 then return the second argument.  In this example, when @('app') has recursed
 three times down the @('cdr') of its first argument, @(''(a b c)'), it reaches
 the final @('nil'), which satisfies @('endp'), and so 27 is returned.  It is
 naturally consed into the emerging list as the function returns from
 successive recursive calls (since @('cons') does not require its arguments to
 be lists, either).  The result is an ``improper'' list, @('(a b c . 27)').</p>

 <p>You can think of @('(app x y)') as building a binary tree by replacing the
 right-most tip of the tree @('x') with the tree @('y').</p>")

(defxdoc acl2-as-standalone-program
  :parents (acl2-tutorial)
  :short "Calling ACL2 from another program"
  :long "<p>ACL2 is intended for interactive use.  It is generally unrealistic
 to expect it to prove theorems fully automatically; see @(see the-method), and
 see @(see introduction-to-the-theorem-prover) for a more detailed
 tutorial.</p>

 <p>Nevertheless, here we describe an approach for how to call the ACL2 theorem
 prover noninteractively.  These steps can of course be modified according to
 your needs.  Here, we illustrate how to call ACL2 from another Lisp program
 (or an arbitrary program) to attempt to prove an arithmetic theorem.</p>

 <p>See also @(see interfacing-tools).  In particular, if you want to make a
 command-line tool to ACL2 with options, you may be interested in @(see
 oslib::argv), @(see getopt::getopt), and especially @(see getopt-demo::demo2).
 Alternately, if you want to develop a server application on top of ACL2, you
 might consider @(see bridge::bridge).</p>

 <h3>Step 1</h3>

 <p>Build a suitable ACL2 image by starting ACL2 and then executing the
 following forms.  In particular, these define a macro, @('try-thm'), that
 causes ACL2 to exit with with an exit status indicating success or failure of
 a proof attempt.</p>

 @({
  (include-book \"arithmetic-5/top\" :dir :system)
  (defmacro try-thm (&rest args)
    `(mv-let (erp val state)
             (with-prover-time-limit 3 (thm ,@args))
             (declare (ignore val))
             (prog2$ (if erp (exit 1) (exit 0)) state))))
  (reset-prehistory) ; optional
  :q
  (save-exec \"arith-acl2\" \"Included arithmetic-4/top\")
 })

 <p>If you prefer, above you can replace 3 by some other number of seconds as a
 time limit for the prover.  Also, you can replace</p>

 @({
  (with-prover-time-limit 3 (thm ,@args))
 })

 <p>by</p>

 @({
  (with-output :off :all (with-prover-time-limit 3 (thm ,@args)))
 })

 <p>if you want to turn off output.  It may be best to leave the output on,
 instead eliminating it in the calling program (see Step 3 below).</p>

 <h3>Step 2</h3>

 <p>Try a little test.  In that same directory try this:</p>

 @({
  echo '(try-thm (equal x x))' | ./arith-acl2
  echo $?
 })

 <p>The exit status should be 0, indicating success.  Now try this:</p>

 @({
  echo '(try-thm (not (equal x x)))' | ./arith-acl2
  echo $?
 })

 <p>The exit status should be 1, indicating failure.</p>

 <h3>Step 3</h3>

 <p>Create a shell script that automates Step 2, for example:</p>

 @({
  #!/bin/sh
  (echo \"(try-thm $1)\" | ./arith-acl2) >& /dev/null
  exit $?
 })

 <h3>Step 4</h3>

 <p>Try your script from a Lisp program, if you like.  Here is how you can do
 it in SBCL, for example.  (Different Lisps have different ways to do this, as
 summarized in function @('system-call') in ACL2 source file
 @('acl2-init.lisp').)</p>

 @({
  (defun provable? (x)
    (let ((status
           (process-exit-code
            (sb-ext:run-program \"./try-thm.sh\" (list (format nil \"~s\" x))
                                :output t :search t))))
      (eql status 0)))
 })

 <p>Then here is a log:</p>

 @({
    * (provable? '(equal x y))

    NIL
    * (provable? '(equal x x))

    T
    *
 })

 <p>Certainly refinements are possible &mdash; for example the above doesn't
 distinguish between unprovable and ill-formed input.  But it's a start.</p>

 ")

(defxdoc acl2-built-ins
  :parents (programming)
  :short "''Catch-all'' topic for built-in ACL2 functions"
  :long "<p>This @(see documentation) topic is a parent topic under which we
 include documentation for built-in functions, macros, and special forms that
 are typically used in @(see programming).  For others, including those
 typically used as top-level commands or those that create @(see events)
 (@(tsee defun), @(tsee defmacro), @(tsee defthm), and so on), documentation
 may be found as a subtopic of some other parent topic.  We do not document
 some of the more obscure functions provided by ACL2 that do not correspond to
 functions of Common Lisp.</p>

 <p>See any documentation for Common Lisp for more details on many of these
 functions.</p>")

(defxdoc acl2-count
  :parents (basics acl2-built-ins)
  :short "A commonly used measure for justifying recursion"
  :long "<p>@('(Acl2-count x)') returns a nonnegative integer that indicates
 the ``size'' of its argument @('x').</p>

 <p>All @(see characters) and symbols have @('acl2-count 0').  The
 @('acl2-count') of a string is the number of @(see characters) in it, i.e.,
 its length.  The @('acl2-count') of a @(tsee cons) is one greater than the sum
 of the @('acl2-count')s of the @(tsee car) and @(tsee cdr).  The
 @('acl2-count') of an integer is its absolute value.  The @('acl2-count') of a
 rational is the sum of the @('acl2-count')s of the numerator and denominator.
 The @('acl2-count') of a complex rational is one greater than the sum of the
 @('acl2-count')s of the real and imaginary parts.</p>

 @(def acl2-count)")

(defxdoc acl2-customization
  :parents (miscellaneous)
  :short "File of initial commands for ACL2 to run at @(see startup)"
  :long "<p>ACL2 provides a mechanism to load automatically a so-called ``ACL2
 customization file,'' via @(tsee ld), the first time @(tsee lp) is called in
 an ACL2 session.  ACL2 looks for this file as follows.</p>

 <ol>

 <li>If the host Lisp reads a non-empty value for the system's
 environment variable @('ACL2_CUSTOMIZATION'), then that string value is used
 for the customization file name.  In this case, if the file does not exist or
 if the string is \"NONE\" then there is no customization file.  Notes:

     <ul>

     <li>If the customization file name is a relative pathname (see @(see
     pathname)), then the pathname is considered relative to the connected book
     directory (see @(see cbd)).</li>

     <li>If this variable is not already defined, then its value is set to
     @('NONE') when books are certified using @(see BUILD::cert.pl) or other,
     legacy Make-based certification tools.</li>

     </ul></li>

 <li>Otherwise (empty environment variable value), file
 @('\"acl2-customization.lsp\"') or @('\"acl2-customization.lisp\"') on the
 connected book directory (see @(see cbd)), generally the current directory, is
 the customization file (in that order) if either exists.</li>

 <li>Otherwise file @('\"acl2-customization.lsp\"') or
 @('\"acl2-customization.lisp\"') on your home directory is the customization
 file (in that order), if either exists (except, this case is skipped on
 Windows operating systems.</li>

 </ol>

 <p>Except for the fact that this @(tsee ld) command is not typed explicitly by
 you, it is a standard @(tsee ld) command, with one exception: any settings of
 @(tsee ld) specials are remembered once this call of @(tsee ld) has completed.
 For example, suppose that you start your customization file with
 @('(set-ld-skip-proofsp t state)'), so that proofs are skipped as it is loaded
 with @(tsee ld).  Then the @(tsee ld) special @(tsee ld-skip-proofsp) will
 remain @('t') after the @(tsee ld) has completed, causing proofs to be skipped
 in your ACL2 session, unless your customization file sets this variable back
 to @('nil'), say with @('(set-ld-skip-proofsp nil state)').</p>

 <p>If the customization file exists, it is loaded with @(tsee ld) using the
 usual default values for the @(tsee ld) specials (see @(see ld)).  Thus, if an
 error is encountered, no subsequent forms in the file will be evaluated.</p>

 <p>To create a customization file it is recommended that you first give it a
 name other than @('\"acl2-customization.lsp\"') or
 @('\"acl2-customization.lisp\"') so that ACL2 does not try to include it
 prematurely when you next enter @(tsee lp).  Then, while in the uncustomized
 @(tsee lp), explicitly invoke @(tsee ld) on your evolving (but renamed)
 customization file until all forms are successfully evaluated.  The same
 procedure is recommended if for some reason ACL2 cannot successfully evaluate
 all forms in your customization file: temporarily rename your customization
 file so that ACL2 does not try to @(tsee ld) it automatically and then debug
 the new file by explicit calls to @(tsee ld).</p>

 <p>WARNING!  If you certify a book after the (automatic) loading of a
 customization file, the forms in that file will be part of the @(see
 portcullis) of the @(see books) you certify!  That is, the forms in your
 customization file at certification time will be loaded whenever anybody uses
 the @(see books) you are certifying.  Since customization files generally
 contain idiosyncratic @(see command)s, you may not want yours to be part of
 the @(see books) you create for others.  Thus, if you have a customization
 file then you may want to invoke @(':')@(tsee ubt)@(' 1') before certifying
 any @(see books); alternatively, see @(see certify-book!) for automatic
 invocation of @(tsee ubt).</p>

 <p>On the other hand, if you wish to prevent undoing commands from the
 customization file, see @(see reset-prehistory).</p>

 <p>Finally, we note that except on Windows-based systems, if there is a file
 @('acl2-init.lsp') in your home directory, then it will be loaded into raw
 Lisp when ACL2 is invoked.</p>")

(defxdoc acl2-defaults-table
  :parents (table)
  :short "A @(see table) specifying certain defaults, e.g., the default @(see defun-mode)"
  :long "@({
  Example Forms:
  (table acl2-defaults-table :defun-mode) ; current default defun-mode
  (table acl2-defaults-table :defun-mode :program)
             ; set default defun-mode to :program
 })

 <p>See @(see table) for a discussion of tables in general.  The legal keys for
 this @(see table) are shown below.  They may be accessed and changed via the
 general mechanisms provided by @(see table)s.  However, there are often more
 convenient ways to access and/or change the defaults.  (See also the note
 below.)</p>

 @({
  :user
 })

 <p>The @(':user') key is for ACL2 users; the system does not consult this key
 or set it (other than as part of general @('acl2-defaults-table ')
 maintenance).  Its value is required to be an association list (@(tsee
 alistp)), so that different users can read and write their ``own'' keys.  For
 example, suppose user Joe uses key @(':j') while user Mary uses key @(':m');
 then we could see a value for @(':user') of @('((:j . 3) (:m . 4))') after Joe
 sets his value to 3 and Mary sets her value to 4.</p>

 @({
  :defun-mode
 })

 <p>the default @(see defun-mode), which must be @(':')@(tsee program) or
 @(':')@(tsee logic).  See @(see defun-mode) for a general discussion of @(see
 defun-mode)s.  The @(':')@(tsee defun-mode) key may be conveniently set by
 keyword commands naming the new @(see defun-mode), @(':')@(tsee program) and
 @(':')@(tsee logic).  See @(see program) and see @(see logic).</p>

 @({
  :enforce-redundancy
 })

 <p>if @('t'), cause ACL2 to insist that most events are redundant (see @(see
 redundant-events)); if @(':warn'), cause a warning instead of an error for
 such non-redundant events; else, @('nil').  See @(see
 set-enforce-redundancy).</p>

 @({
  :verify-guards-eagerness
 })

 <p>an integer between 0 and 2 indicating how eager the system is to verify the
 @(see guard)s of a @(see defun) event.  See @(see
 set-verify-guards-eagerness).</p>

 @({
  :compile-fns
 })

 <p>When this key's value is @('t'), functions are compiled when they are
 @(tsee defun)'d; otherwise, the value is @('nil').  (Except, this key's value
 is ignored when explicit compilation is suppressed; see @(see compilation).)
 To set the flag, see @(see set-compile-fns).</p>

 @({
  :measure-function
 })

 <p>the default measure function used by @(tsee defun) when no @(':measure') is
 supplied in @(tsee xargs).  The default measure function must be a function
 symbol of one argument. Let @('mfn') be the default measure function and
 suppose no @(':measure') is supplied with some recursive function definition.
 Then @(tsee defun) finds the first formal, @('var'), that is tested along
 every branch and changed in each recursive call.  The system then ``guesses''
 that @('(mfn var)') is the @(':measure') for that @(tsee defun).</p>

 @({
  :well-founded-relation
 })

 <p>the default well-founded relation used by @(tsee defun) when no
 @(':well-founded-relation') is supplied in @(tsee xargs).  The default
 well-founded relation must be a function symbol, @('rel'), of two arguments
 about which a @(':well-founded-relation') rule has been proved.  See @(see
 well-founded-relation-rule).</p>

 @({
  :bogus-defun-hints-ok
 })

 <p>When this key's value is @('t'), ACL2 allows @(':hints') and also
 @(':measure') for nonrecursive function definitions.  Otherwise, the value is
 @('nil') (the default) or @(':warn') (which makes the check but merely warns
 when the check fails).  See @(see set-bogus-defun-hints-ok) and @(see
 set-bogus-measure-ok).</p>

 @({
  :bogus-mutual-recursion-ok
 })

 <p>When this key's value is @('t'), ACL2 skips the check that every function
 in a @(tsee mutual-recursion) (or @(tsee defuns)) ``clique'' calls at least
 one other function in that ``clique.''  Otherwise, the value is @('nil') (the
 default) or @(':warn') (which makes the check but merely warns when the check
 fails).  See @(see set-bogus-mutual-recursion-ok).</p>

 @({
  :irrelevant-formals-ok
 })

 <p>When this key's value is @('t'), the check for irrelevant formals is
 bypassed; otherwise, the value is the keyword @('nil') (the default) or
 @(':warn') (which makes the check but merely warns when the check fails).  See
 @(see irrelevant-formals) and see @(see set-irrelevant-formals-ok).</p>

 @({
  :ignore-ok
 })

 <p>When this key's value is @('t'), the check for ignored variables is
 bypassed; otherwise, the value is the keyword @('nil') (the default) or
 @(':warn') (which makes the check but merely warns when the check fails).  See
 @(see set-ignore-ok).</p>

 @({
  :bdd-constructors
 })

 <p>This key's value is a list of function symbols used to define the notion of
 ``BDD normal form.''  See @(see bdd-algorithm) and see @(see hints).</p>

 @({
  :ttag
 })

 <p>This key's value, when non-@('nil'), allows certain operations that extend
 the trusted code base beyond what is provided by ACL2.  See @(see defttag).
 See @(see defttag).</p>

 @({
  :state-ok
 })

 <p>This key's value is either @('t') or @('nil') and indicates whether the
 user is aware of the syntactic restrictions on the variable symbol @('STATE').
 See @(see set-state-ok).</p>

 @({
  :backchain-limit
 })

 <p>This key's value is a list of two ``numbers.''  Either ``number'' may
 optionally be @('nil'), which is treated like positive infinity.  The numbers
 control backchaining through hypotheses during type-set reasoning and
 rewriting.  See @(see backchain-limit).</p>

 @({
  :default-backchain-limit
 })

 <p>This key's value is a list of two ``numbers.''  Either ``number'' may
 optionally be @('nil'), which is treated like positive infinity.  The numbers
 are used respectively to set the backchain limit of a rule if one has not been
 specified. See @(see backchain-limit).</p>

 @({
  :step-limit
 })

 <p>This key's value is either @('nil') or a natural number not exceeding the
 value of @('*default-step-limit*').  If the value is @('nil') or the value of
 @('*default-step-limit*'), there is no limit on the number of ``steps'' that
 ACL2 counts during a proof: currently, the number of top-level rewriting
 calls.  Otherwise, the value is the maximum number of such calls allowed
 during evaluation of any event.  See @(see set-prover-step-limit).</p>

 @({
  :rewrite-stack-limit
 })

 <p>This key's value is a nonnegative integer less than @('(expt 2 28)').  It
 is used to limit the depth of calls of ACL2 rewriter functions.  See @(see
 rewrite-stack-limit).</p>

 @({
  :let*-abstractionp
 })

 <p>This key affects how the system displays subgoals.  The value is either
 @('t') or @('nil').  When t, let* expressions are introduced before printing
 to eliminate common subexpressions.  The actual goal being worked on is
 unchanged.</p>

 @({
  :case-split-limitations
 })

 <p>This key's value is a list of two ``numbers.''  Either ``number'' may
 optionally be @('nil'), which is treated like positive infinity.  The numbers
 control how the system handles case splits in the simplifier.  See @(see
 set-case-split-limitations).</p>

 @({
  :include-book-dir-alist
 })

 <p>This key's value is used by @(tsee include-book)'s @(':DIR') argument to
 associate a directory with a keyword.  An exception is the keyword
 @(':SYSTEM') for the @('books/') directory; see @(see include-book), in
 particular the section on ``Books Directory.''  Also see @(tsee
 add-include-book-dir) and @(tsee add-include-book-dir!).</p>

 @({
  :match-free-default
 })

 <p>This key's value is either @(':all'), @(':once'), or @('nil').  See @(see
 set-match-free-default).</p>

 @({
  :match-free-override
 })

 <p>This key's value is a list of runes.  See @(see
 add-match-free-override).</p>

 @({
  :match-free-override-nume
 })

 <p>This key's value is an integer used in the implementation of @(see
 add-match-free-override), so that only existing runes are affected by that
 event.</p>

 @({
  :non-linearp
 })

 <p>This key's value is either @('t') or @('nil') and indicates whether the
 user wishes ACL2 to extend the linear arithmetic decision procedure to include
 non-linear reasoning.  See @(see non-linear-arithmetic).</p>

 @({
  :tau-auto-modep
 })

 <p>This key's value is either @('t') or @('nil') and indicates whether the
 user wishes ACL2 to look for opportunities to create @(':')@(tsee tau-system)
 rules from all suitable @('defun')s and from all suitable @('defthm')s (with
 non-@('nil') @(':')@(tsee rule-classes)).  See @(see set-tau-auto-mode).</p>

 @({
  :ruler-extenders
 })

 <p>This key's value may be a list of symbols, indicating those function
 symbols that are not to block the collection of rulers; see @(see defun).
 Otherwise the value is @(':all') to indicate all function symbols, i.e., so
 that no function symbol blocks the collection of rulers.  If a list is
 specified (rather than @(':all')), then it may contain the keyword
 @(':lambdas'), which has the special role of specifying all @('lambda')
 applications.  No other keyword is permitted in the list.  See @(see
 rulers).</p>

 @({
  :memoize-ideal-okp
 })

 <p>This key's value must be either @('t'), @('nil'), or @(':warn').  If the
 value is @('nil') or not present, then it is illegal by default to @(see
 memoize) a @(':')@(tsee logic) mode function that has not been @(see
 guard)-verified (see @(see verify-guards)), sometimes called an ``ideal-mode''
 function.  This illegality is the default because such calls of such functions
 in the ACL2 loop are generally evaluated in the logic (using executable
 counterpart definitions; see @(see evaluation)), rather than directly by
 executing calls of the corresponding (memoized) raw Lisp function.  However,
 such a raw Lisp call can be made when the function is called by a @(':')@(tsee
 program) mode function, so we allow you to override the default behavior by
 associating the value @('t') or @(':warn') with the key
 @(':memoize-ideal-okp'), where with @(':warn') you get a suitable warning.
 Note that you can also allow memoization of ideal-mode functions by supplying
 argument @(':ideal-okp') to your memoization event (see @(see memoize)), in
 which case the value of @(':memoize-ideal-okp') in the
 @('acl2-defaults-table') is irrelevant.</p>

 @({
  :check-invariant-risk
 })

 <p>For an explanation of this key, see @(see set-check-invariant-risk).</p>

 @({
  :register-invariant-risk
 })

 <p>For an explanation of this key, see @(see set-register-invariant-risk).</p>

 <p>Note: Unlike all other @(see table)s, @('acl2-defaults-table') can affect
 the soundness of the system.  The @(see table) mechanism therefore enforces on
 it a restriction not imposed on other @(see table)s: when @(tsee table) is
 used to update the @('acl2-defaults-table'), the key and value must be
 variable-free forms.  Thus, while</p>

 @({
  (table acl2-defaults-table :defun-mode :program),

  (table acl2-defaults-table :defun-mode ':program), and

  (table acl2-defaults-table :defun-mode (compute-mode *my-data*))
 })

 <p>are all examples of legal @(see events) (assuming @('compute-mode') is a
 function of one non-@(tsee state) argument that produces a @(see defun-mode)
 as its single value),</p>

 @({
  (table acl2-defaults-table :defun-mode (compute-mode (w state)))
 })

 <p>is not legal because the value form is @(tsee state)-sensitive.</p>

 <p>Consider for example the following three @(see events) which one might make
 into the text of a book.</p>

 @({
  (in-package \"ACL2\")

  (table acl2-defaults-table
    :defun-mode
    (if (ld-skip-proofsp state) :logic :program))

  (defun crash-and-burn (x) (car x))
 })

 <p>The second event is illegal because its value form is @(tsee
 state)-sensitive.  If it were not illegal, then it would set the @(':')@(tsee
 defun-mode) to @(':')@(tsee program) when the book was being certified but
 would set the @(see defun-mode) to @(':')@(tsee logic) when the book was being
 loaded by @(tsee include-book).  That is because during certification, @(tsee
 ld-skip-proofsp) is @('nil') (proof obligations are generated and proved), but
 during book inclusion @(tsee ld-skip-proofsp) is non-@('nil') (those
 obligations are assumed to have been satisfied.)  Thus, the above book, when
 loaded, would create a function in @(':')@(tsee logic) mode that does not
 actually meet the conditions for such status.</p>

 <p>For similar reasons, @(tsee table) @(see events) affecting
 @('acl2-defaults-table') are illegal within the scope of @(tsee local) forms.
 That is, the text</p>

 @({
  (in-package \"ACL2\")

  (local (table acl2-defaults-table :defun-mode :program))

  (defun crash-and-burn (x) (car x))
 })

 <p>is illegal because @('acl2-defaults-table') is changed locally.  If this
 text were acceptable as a book, then when the book was certified,
 @('crash-and-burn') would be processed in @(':')@(tsee program) mode, but when
 the certified book was included later, @('crash-and-burn') would have
 @(':')@(tsee logic) mode because the @(tsee local) event would be skipped.</p>

 <p>The text</p>

 @({
  (in-package \"ACL2\")

  (program) ;which is (table acl2-defaults-table :defun-mode :program)

  (defun crash-and-burn (x) (car x))
 })

 <p>is acceptable and defines @('crash-and-burn') in @(':')@(tsee program)
 mode, both during certification and subsequent inclusion.</p>

 <p>We conclude with important observations about the interaction of the
 @('acl2-defaults-table') with @(tsee include-book), @(tsee certify-book), and
 @(tsee encapsulate).  If the @('acl2-defaults-table') has value @('V') and you
 evaluate a call of @(tsee include-book), @(tsee certify-book), or @(tsee
 encapsulate), then the @('acl2-defaults-table') has value @('V') when that
 call returns.  Thus, if you want to set the @('acl2-defaults-table') in a way
 that persists, you need to do so using @(see command)s that are not inside
 @(see books).  It may be useful to set your favorite defaults in your @(tsee
 acl2-customization) file; see @(see acl2-customization).</p>

 <p>ACL2 disallows (for logical reasons) setting of the
 @('acl2-defaults-table') in the context of @('LOCAL').  Often it is easy
 simply to avoid wrapping an @('acl2-defaults-table') event, or a macro that
 generates such an event, inside a @('LOCAL'); after all, a local context is
 not useful when setting the @('acl2-defaults-table'), since that table is
 restored as discussed above upon completion of @(tsee include-book), @(tsee
 certify-book), and @(tsee encapsulate) forms.  Occasionally a bit more thought
 is required to work around this restriction, but usually it's not difficult to
 do so.  Suppose for example that you attempt to put following event form into
 a book.</p>

 @({
 (local (progn (defttag t) (defun foo (x) (sys-call x nil))))
 })

 <p>ACL2 responds with the following error message.</p>

 @({
 ACL2 Error in ( PROGN (DEFTTAG T) ...):  The form (DEFTTAG T)
 is not an embedded event form in the context of LOCAL
 because it implicitly sets the acl2-defaults-table in
 a local context; see :DOC acl2-defaults-table, in particular
 the explanation about this error message.  See :DOC
 embedded-event-form.
 })

 <p>A solution is to use @(tsee encapsulate) instead of (or in addition to)
 @(tsee progn), because @(tsee encapsulate) establishes a new context that is
 not considered within a surrounding @('LOCAL').  For example, the following
 replacement for the form above is legal in a book.</p>

 @({
 (local (encapsulate () (defttag t) (defun foo (x) (sys-call x nil))))
 })

 <p>To see that this works, try creating a file @('\"foo.lisp\"') whose first
 form is @('(in-package \"ACL2\")') and whose only other form is the one
 displayed just above.  Then the command @('(certify-book \"foo\" 0 t :ttags
 :all)') will successfully certify that book.</p>")

(defxdoc acl2-doc
  :parents (documentation)
  :short "A custom Emacs browser for reading ACL2 @(see documentation)"
  :long "<p>As discussed elsewhere (see @(see documentation)), the web-based
 @(`(:raw (combined-manual-ref))`) provides a way to browse the combined
 documentation for the ACL2 system and community books.  Such documentation can
 also be read at the terminal using the @(':')@(tsee doc) command, though
 documentation for @(see books) will only be included for those books that have
 been included in the session.  In this topic we describe how to browse the
 documentation using ACL2-Doc, a browser for reading
 documentation inside Emacs.  It supports reading the combined documentation
 (ACL2 plus books), but it also supports reading the ACL2-only manual as well
 as custom manuals.  We assume some familiarity with Emacs, for example, the
 notion of a ``prefix argument'': a numeric value given first with the
 @('meta') key (or, probably the @('control') key), for example, @('meta-0
 control-t g') or @('control-3 control-t /').</p>

 <p>While ACL2-Doc is much like Emacs Info, it is a separate system that
 provides some additional functionality.  ACL2-Doc is text-based.  Any word
 that names a topic is a link: you can hit the @('<Return>') key while standing
 on that topic to go to the page of documentation for that topic.  However,
 many links are shown explicitly, inside square brackets.  For example, here is
 a link that will take you to the BOOKS topic; it should show up surrounded by
 square brackets if you are now reading at the terminal or in ACL2-Doc, but
 there are no square brackets for this link if you are reading on the web.</p>

 <blockquote>

 <p>@(see books)</p>

 </blockquote>

 <p>It should be very rare for square brackets to be intended simply as square
 brackets, not as link indicators.</p>

 <p>In order to use ACL2-Doc, load the distributed file
 <tt>emacs/acl2-doc.el</tt> into Emacs.  This will happen automatically if you
 load <tt>emacs/emacs-acl2.el</tt>, which will happen automatically if you put
 the following form in your <tt>~/.emacs</tt> file, replacing @('DIR') by a
 path to your ACL2 installation.</p>

 @({
 (load \"DIR/emacs/emacs-acl2.el\")
 })

 <p>Then to start the browser at the top-level topic, either execute the Emacs
 command</p>

 @({
 meta-x acl2-doc
 })

 <p>or else type:</p>

 @({
 Control-t g
 })

 <p>Thus, you can put the following form in your @('.emacs') file if you want
 @('acl2-doc') to run automatically when Emacs starts up.</p>

 @({
 (acl2-doc)
 })

 <p>By default you will browse the ACL2+Books Manual, though if you are using a
 git version between ACL2 releases then you may be queried; more on that below.
 Or, see below for how to set a variable in your @('.emacs') file,
 @('*acl2-doc-manual-name*'), so that you will browse a custom manual.  You can
 enter the ACL2-Doc browser at a specific documentation topic as follows (in
 analogy to Emacs command @('Meta-.')):</p>

 @({
 Control-t .
 })

 <p>In each of the cases above, you will now be in a buffer called
 \"<tt>acl2-doc</tt>\", which will be displaying the top-level ACL2 topic in a
 special mode, the ACL2-Doc major mode.  That mode provides the following key
 bindings; you can also see these by typing <tt>Control-h m</tt> while in that
 buffer.</p>

 @({
  <Return>      acl2-doc-go!
  g             acl2-doc-go
  h             acl2-doc-help
  i             acl2-doc-index
  ,             acl2-doc-index-next
  <             acl2-doc-index-previous
  l             acl2-doc-last
  n             acl2-doc-search-next
  p             acl2-doc-search-previous
  q             acl2-doc-quit
  r             acl2-doc-return
  s             acl2-doc-search
  S             acl2-doc-re-search
  t             acl2-doc-top
  u             acl2-doc-up
  w             acl2-doc-where
  SPC           scroll-up
  TAB           acl2-doc-tab
  Control-TAB or <backtab> (which often is Shift-TAB):
                acl2-doc-tab-back
  D             acl2-doc-rendered-combined-download
  H             acl2-doc-history
  I             acl2-doc-initialize
  /             acl2-doc-definition
  Control-t /   acl2-doc-definition
  W             acl2-doc-where-definition
 })

 <p>You can see the documentation for each of these in the usual way, using
 <tt>Control-h k {key}</tt> or <tt>Control-h f {command}</tt>.  Here is what
 you will find in each case if you do that.</p>

 @({
  <Return>      acl2-doc-go!
     Go to the topic occurring at the cursor position.  In the case
     of <NAME>, instead go to the source code definition of NAME for
     the current manual (as for `/', but without a minibuffer query).

  g             acl2-doc-go
     Go to the specified topic; performs completion.

  h             acl2-doc-help
     Go to the ACL2-DOC topic to read about how to use the ACL2-Doc browser.

  i             acl2-doc-index
     Go to the specified topic or else one containing it as a substring;
     performs completion.  If the empty string is supplied, then go to the
     index buffer.  Otherwise, with prefix argument, consider only descendants
     of the topic supplied in response to a prompt.  Note that the index buffer
     is in ACL2-Doc mode; thus, in particular, you can type <RETURN> while
     standing on a topic in order to go directly to that topic.

  ,             acl2-doc-index-next
     Find the next topic containing, as a substring, the topic of the most
     recent i command.  Note: if this is the first \",\" or \"<\" after an
     exact match from \"i\", then start the topic search alphabetically from
     the beginning, but avoid a second hit on the original topic.

  <             acl2-doc-index-previous
     Find the previous topic containing, as a substring, the topic of the
     most recent i command.  Note: if this is the first \",\" or \"<\" after an
     exact match from \"i\", then start the topic search alphabetically
     (backwards) from that exact match.

  l             acl2-doc-last
     Go to the last topic visited.

  n             acl2-doc-search-next
     Find the next occurrence for the most recent search or regular expression
     search.

  p             acl2-doc-search-previous
     Find the previous occurrence for the most recent search or regular
     expression search.  Note: as for \"n\", the cursor will end up at the end
     of the match.

  q             acl2-doc-quit
     Quit the ACL2-Doc browser.

  r             acl2-doc-return
     Return to the last topic visited, popping the stack of such topics.

  s             acl2-doc-search
     Search forward from the top of the manual for the input string.  If the
     search succeeds, then go to that topic with the cursor put immediately
     after the found text, with the topic name displayed in the minibuffer.
     With prefix argument, consider (also for subsequent \"n\" and \"p\"
     commands) only descendants of the topic supplied in response to a prompt.

  S             acl2-doc-re-search
     Perform a regular expression search, forward from the top of the manual,
     for the input string.  If the search succeeds, then go to that topic with
     the cursor put immediately after the found text, with the topic name
     displayed in the minibuffer.  With prefix argument, consider (also for
     subsequent \"n\" and \"p\" commands) only descendants of the topic
     supplied in response to a prompt.

  t             acl2-doc-top
     Go to the top topic.

  u             acl2-doc-up
     Go to the parent of the current topic.

  w             acl2-doc-where
     Display the topic name in the minibuffer, together with the manual name
     (ACL2+Books Manual or ACL2 User's Manual)

  SPC           scroll-up
     Scroll up (same as Control-v)

  TAB           acl2-doc-tab
     Visit the next link after the cursor on the current page, searching from
     the top if no link is below the cursor.

  Control-TAB or <backtab> (which often is Shift-TAB):
                acl2-doc-tab-back
     Visit the previous link before the cursor on the current page, searching
     from the bottom if no link is below the cursor.

  D
     Download the ``bleeding edge'' ACL2+Books Manual from the web; then
     restart the ACL2-Doc browser to view that manual.

  H             acl2-doc-history
     Visit a buffer that displays the names of all visited topics in order,
     newest at the bottom.  That buffer is in acl2-doc mode; thus the usual
     acl2-doc commands may be used.  In particular, you can visit a displayed
     topic name by putting your cursor on it and typing <RETURN>.

  I             acl2-doc-initialize
     Restart the ACL2-Doc browser, clearing its state.  With a prefix argument,
     a query asks you to select the name of an available manual, using
     completion.  See the section on \"Selecting a Manual\", below,
     for more information.

  /             acl2-doc-definition
  (also control-t /)
     Find an ACL2 definition (in analogy to built-in Emacs command meta-.).
     With numeric prefix argument, find the next matching definition;
     otherwise, the user is prompted, where the default is the name at
     the cursor, obtained after stripping off any enclosing square
     brackets (@('[..]')), angle brackets (@('<..>')) as from srclink tags, and
     package prefixes.  With @('control-u') prefix argument, search only
     ACL2 source definitions; otherwise, books are searched as well.
     As with built-in Emacs command @('meta-.') , exact matches are given
     priority.  For more information, see the Section on \"Selecting a
     Manual\" in the acl2-doc online XDOC-based documentation.

  W             acl2-doc-where-definition
     Find an ACL2 definition.  This is the same as
     acl2-doc-definition (the acl2-doc `/' command, as well as
     control-t /), except that the default comes from the name of the
     current page's topic instead of the cursor position.  Searches
     are continued identically when control-t / is given a numeric
     prefix argument, regardless of whether the first command was /,
     control-t /, or W; thus, a search started with W can be continued
     with, for example, meta-3 control-t /.

 })

 <h4>Selecting a Manual, Tags Files, and Custom Manuals</h4>

 <p>ACL2-Doc can display the ACL2 User's Manual, which includes documentation
 for the ACL2 system but not for the @(see community-books).  But by default,
 ACL2-Doc will display the ACL2+Books Manual, which includes documentation for
 those books as well.  To change which of these two manuals you display, just
 give a prefix argument to the `@('I')' command, as described briefly
 above.</p>

 <p>For the `@('/')' and `@('W')' commands, you will need tags table files.
 These come with the ACL2 gzipped tarfile distribution, but if you obtain ACL2
 from github then you will need to build them.  The file @('\"TAGS\"') is used
 when these commands are given a prefix argument (to search only the ACL2
 sources), and is generated when building the @('saved_acl2') executable with
 `@('make')'.  Without a prefix argument the file @('\"TAGS-acl2-doc\"') is
 used for searching both the ACL2 sources and the books, and is created
 automatically if you build the manual by certifying community book
 @('books/doc/top.lisp').  You can also build @('\"TAGS-acl2-doc\"') by running
 the command @('bin/make-tags-acl2-doc.sh'), or by building the ACL2 executable
 after setting variable @('TAGS_ACL2_DOC') to a non-empty value other than
 @('SKIP') either on the command line with `@('make')' or, for example, by
 putting one of the following forms in your @('~/.cshrc') or @('~/.bashrc'),
 respectively.</p>

 @({
 setenv TAGS_ACL2_DOC t

 export TAGS_ACL2_DOC=t
 })

 <p>If you are using a git version of ACL2 and the books, between releases,
 then you may need to download an extra file in order to browse the ACL2+Books
 Manual.  Most likely you will just answer @('y') when queried about
 downloading the file when first using ACL2-Doc.  If you want more details, see
 the last of the notes in the ``Notes'' section below.</p>

 <p>As mentioned above, you can give the `@('I')' command a prefix argument in
 order to select a specific manual.  You will be asked for a name, which by
 default will be the most recently selected such name, if any.  As noted above,
 the only two manuals initially known to acl2-doc are the ACL2+Books Manual and
 the ACL2 User's Manual.  These have the names `@('combined')' and
 `@('acl2-only')', respectively.  You can also tell acl2-doc about a custom
 manual, by evaluating (in Emacs) the following form, e.g., by adding it to
 your @('~/.emacs') file before starting Emacs.  Here, @('filename') is the
 pathname of a file typically created by calling @(see
 xdoc::save-rendered).</p>

 @({
 (extend-acl2-doc-manual-alist
  'name          ; the name of the manual
  filename       ; documentation source, typically of the form *doc*.lsp
  'top           ; the top node name, typically TOP
  printname      ; optional print name (user-level name) of manual
  url            ; optional URL of gzipped file to download into filename
  tags-file-name ; optional tags filename (from output of etags)
  acl2-tags-file-name ; as above, but without files from books/ directory
  )
 })

 <p>For example, acl2-doc is initially built with the following two forms,
 which is why you can respond to the query mentioned above with `@('combined')'
 or `@('acl2-only')'.</p>

 @({
 (extend-acl2-doc-manual-alist
  'combined
  (concat *acl2-sources-dir*
          \"books/system/doc/rendered-doc-combined.lsp\")
  'TOP
  \"ACL2+Books Manual\"
  \"http://www.cs.utexas.edu/users/moore/acl2/manuals/current/rendered-doc-combined.lsp.gz\"
  (concat *acl2-sources-dir* \"TAGS-acl2-doc\")
  (concat *acl2-sources-dir* \"TAGS\"))

 (extend-acl2-doc-manual-alist
  'acl2-only
  (concat *acl2-sources-dir* \"doc.lisp\")
  'ACL2
  \"ACL2 User's Manual\"
  nil
  nil
  (concat *acl2-sources-dir* \"TAGS\"))
 })

 <p>Note that the first of these forms specifies the location of the
 @('\"TAGS-acl2-doc\"') and @('\"TAGS\"') files mentioned above, but the second
 only specifies @('\"TAGS\"') since the second form is for an ACL2-only manual
 (no books).</p>

 <p>If you want a specific manual to come up when you first run acl2-doc in an
 Emacs session, you can put the following into your @('.emacs') file, where
 @(''name') is the name a manual for which you have included a form
 @('(extend-acl2-doc-manual-alist 'name ...)') in your @('.emacs') file.</p>

 @({
 (setq *acl2-doc-manual-name* 'name)
 })

 <h4>Color</h4>

 <p>By default, links (indeed, any text) in square brackets will be shown in
 blue.  You can customize this behavior by setting (e.g., in your @('.emacs')
 file) the Emacs variable @('*acl2-doc-link-color*') to the desired link color,
 or to @('nil') if you don't want the links to be in color.  For example:</p>

 @({
 (setq *acl2-doc-link-color* \"#FF0000\") ; red
 (setq *acl2-doc-link-color* \"Green\")   ; green
 (setq *acl2-doc-link-color* nil)         ; no special color for links
 })

 <h4>Notes</h4>

 <ul>

 <li>You might find that when you attempt to follow @(see some-broken-link),
 you find yourself at the @(see broken-link) topic.  If you are using the ACL2
 User's Manual rather than the ACL2+Books Manual, the reason might be that
 @('some-broken-link') is documented in a book, not in the ACL2 system.  In
 that case, the @('broken-link') page will show you where to find that book;
 but if you want to read the documentation for @('some-broken-link') in the
 ACL2-Doc browser, you can do so by switching to the ACL2+Books Manual.  See
 the @('I') command, documented above.<p/></li>

 <li>Files with names ending in <tt>.acl2-doc</tt> will come up in ACL2-Doc
 mode.  Thus, you may wish to save a file with that extension, for example
 <tt>bookmarks.acl2-doc</tt>, that contains your favorite bookmarks.  You may
 wish to use the history command (<tt>H</tt>) to obtain a list of names of
 visited topics, in order to create an initial such file.<p/></li>

 <li>Many commands offer defaults, and many offer completion.  The default is
 determined by cursor position: if the cursor is sitting on a letter of a
 documentation topic name, or on a space character immediately after it, then
 that name will be offered as the default.  Completion is carried out with the
 usual emacs ``@('completing-read')''; thus, for example, the character
 `@('?')' is a help key, so if you want that character as part of your topic
 name, prefix it with @('control-q').  For example, after the `@('g')' command
 you can go to the topic @(tsee mv?) by typing the character sequence
 @('<m,v,control-q ?>').<p/></li>

 <li>Square brackets typically indicate documentation topic names, for example:
 <tt>[acl2-doc]</tt>.  (As mentioned above, there are occasional exceptions,
 where square brackets are simply part of the intended documentation text.)
 The square brackets are really there, for example when you are searching using
 \"s\", \"S\", or \"n\".  However, for purposes of determining the default
 name (see above), the only effect of the enclosing square brackets is to
 extend the region in which the default is offered.  For example, consider the
 string \"<tt>[acl2-doc]</tt>\": the default name of \"<tt>acl2-doc</tt>\" is
 offered if the cursor is on either square bracket.  But links have some
 idiosyncrasies.<p/>

 <ol>

   <li>Topic names, including links `<tt>[..]</tt>' to topic names, are printed
   relative to the ACL2 package.  Especially in the case of the ACL2+Books
   Manual, you may therefore see links that include package prefixes.  Here,
   for example, is a sentence from the documentation for @(see gl) in the
   ACL2+Books Manual.

   <code>
    We call these structures [gl::symbolic-objects].
   </code>

   The \"<tt>gl</tt>\" package prefix allows commands to pick up
   \"<tt>gl::symbolic-objects</tt>\" as the name to use as a default, so that
   for example, hitting @('<Return>') will take you to that topic.  But when
   reading the sentence, for best results you should ignore package prefixes.
   So for example, you would read the sentence above as follows.

   <code>
    We call these structures symbolic-objects.
   </code><p/></li>

   <li>Inside ACL2-Doc, topic names that originally contained spaces now have
   underscores in place of the spaces.  So for example, the topic @(see
   ACL2-TUTORIAL) in the ACL2+Books Manual contains a link to the topic
   originally named as follows.<br/>

   @('|Pages Written Especially for the Tours|')<br/>

   This link shows up in the ACL2-Doc browser as:<br/>

   @('[Pages_Written_Especially_for_the_Tours]').</li>

 </ol>

 Of course, the web-based browser avoids these idiosyncrasies (see @(see
 xdoc::save)); in particular, that browser is best for ``Tours'' pages like the
 one shown above and its subtopics, in part because that way you may see
 images.  Hence the web-based browser may be more appropriate for some topics,
 and for those who have no particular preference for using Emacs to browse the
 documentation.<p/></li>

 <li>Searching using the \"s\" or \"S\" command is carried out by searching
 top-to-bottom in a hidden Emacs buffer that contains all of the
 documentation.  The topics are listed in the following order according to
 topic name:<p/>

   <ol>

   <li>All topics whose names reside in the \"<tt>ACL2</tt>\" package;</li>

   <li>All topics whose names reside in the \"<tt>ACL2-PC</tt>\" package; and,
   for the ACL2+Books Manual,</li>

   <li>All other topics, sorted by @(tsee symbol-name) and then by @(tsee
   symbol-package-name).</li>

   </ol><p/></li>

 <li>You may be queried, regarding whether you want to browse the ACL2+Books
 Manual, which is preferred, or the ACL2 User's Manual, which omits
 documentation for the books.  Both of these manuals are based on files that
 you will have if you are using a released version of ACL2 (after Version 6.3).
 But if you are using a <a href='https://github.com/acl2/acl2/'>git
 version</a>, then to use the ACL2+Books Manual you will need an extra file.
 You can build this file yourself, as described below but you may prefer to
 download it: for example, when you start ACL2-Doc, you may be given the option
 of downloading <a
 href='http://www.cs.utexas.edu/users/moore/acl2/manuals/current/rendered-doc-combined.lsp.gz'>a
 tarball for the latest ``bleeding edge'' copy</a> and extracting into
 directory @('system/doc/') of your community books directory.  Indeed, the
 system will do all this for you if you answer @('y') to that query.
 Alternatively, you can insist on a download of a ``bleeding edge'' version by
 using the `<tt>D</tt>' command.  However, if you prefer to browse the ACL2
 User's Manual (without the books), you can put the following form into your
 <tt>~/.emacs</tt> file, above the form that loads the code for ACL2-Doc (see
 above).<p/>

 @({
 (defvar *acl2-doc-manual-name* 'acl2-only)
 })

 If you prefer to build @('rendered-doc-combined.lsp') yourself, you can do so
 as follows.<p/>

 <ol>

   <li>Build ACL2:
   @({
   make
   })</li>

   <li>Build the file @('books/system/doc/rendered-doc-combined.lsp') while
   standing in the @('books/') directory, as follows.  If \"<tt>acl2</tt>\"
   invokes the ACL2 executable that you just built, then you may omit
   \"<tt>ACL2=acl2</tt>\" below; otherwise replace \"<tt>acl2</tt>\" by a
   suitable executable.  On a multi-core machine you may wish to use @('-j'),
   e.g., @('make -j 4 ...').
   @({
   cd books
   make doc/top.cert USE_QUICKLISP=1 ACL2=acl2
   })</li>

 </ol></li></ul>")

(defxdoc acl2-help
  :parents (about-acl2)
  :short "The acl2-help mailing list"
  :long "<p>You can email questions about ACL2 usage to the acl2-help mailing
 list: @('acl2-help@utlists.utexas.edu').  If you have more general questions
 about ACL2, for example, about projects completed using ACL2, you may prefer
 the acl2 mailing list, @('acl2@utlists.utexas.edu'), which tends to have wider
 distribution.</p>")

(defxdoc acl2-number-listp
  :parents (numbers lists acl2-built-ins)
  :short "Recognizer for a true list of numbers"
  :long "<p>The predicate @('acl2-number-listp') tests whether its argument is
 a true list of numbers.</p>

 @(def acl2-number-listp)")

(defxdoc acl2-numberp
  :parents (numbers acl2-built-ins)
  :short "Recognizer for numbers"
  :long "<p>@('(acl2-numberp x)') is true if and only if @('x') is a number,
 i.e., a rational or complex rational number.</p>")

(defxdoc acl2-sedan
  :parents (acl2-tutorial)
  :short "ACL2 Sedan interface"
  :long "<p>Many successful ACL2 users run in an shell under Emacs; see @(see
 emacs).  However, those not familiar with Emacs may prefer to start with an
 Eclipse-based interface initially developed by Peter Dillinger and Pete
 Manolios called the <a href='http://acl2s.ccs.neu.edu/acl2s/doc/'>ACL2
 Sedan</a> or ``ACL2s''.</p>

 <p>ACL2 sessions in the ACL2 Sedan can utilize non-standard extensions and
 enhancements, especially geared toward new users, termination reasoning, and
 attaching rich user interfaces.  These extensions are <a
 href='http://acl2s.ccs.neu.edu/acl2s/src/acl2-extensions'>generally
 available</a> as certifiable ACL2 books.
 (Some code originating from this project has been migrated to the ACL2
 community books, but only after it was quite stable.)  Thanks to Peter
 Dillinger, Pete Manolios, Daron Vroon, and Harsh Raju Chamarthi for their work
 on the ACL2 Sedan and for making their books available to ACL2 users.</p>")

(defxdoc acl2-tutorial

; The following comment was near the top of ACL2 source file tutorial.lisp
; before that file was eliminated.

; This document currently has the following form:
;
; :doc ACL2-tutorial
;   introduction
;     OVERVIEW
;     ABOUT THIS TUTORIAL:
;     GETTING STARTED:
;     INTERACTING WITH ACL2:
;   :doc examples
;     EXAMPLE: TOWERS OF HANOI
;     EXAMPLE: EIGHTS PROBLEM
;     A LARGER EXAMPLE: A PHONEBOOK SPECIFICATION
;     DEFUN-SK-EXAMPLE:: example of quantified notions
;     :doc miscellaneous-examples
;       * FILE-READING-EXAMPLE:: example of reading files in ACL2
;       * MUTUAL-RECURSION-PROOF-EXAMPLE:: a small proof about mutually
;            recursive functions
;       * GUARD-EXAMPLE    a brief transcript illustrating guards in ACL2
;   STARTUP
;   TIDBITS
;   TIPS

  :parents (acl2)
  :short "Tutorial introduction to ACL2"
  :long "<p>To learn about ACL2, read at least the following two links.</p>

 <ul>

 <li><see topic='@(url INTERESTING-APPLICATIONS)'>Industrial Applications of
 ACL2</see> (10 minutes) to help you understand what sophisticated users can
 do;</li>

 <li><see topic='@(url |A Flying Tour of ACL2|)'>A Flying Tour</see> (10
 minutes) to get an overview of the system and what skills the user must
 have.</li>

 </ul>

 <p>Alternatively, or in addition, there are @(see talks) that you can peruse,
 many of them introductory in nature.</p>

 <p>If you want to learn <i>how to use</i> ACL2, we recommend that you read a
 selection of the materials referenced below, depending on your learning style,
 and do suggested exercises.</p>

 <ul>

 <li><see topic='@(url |A Walking Tour of ACL2|)'>A Walking
 Tour</see> (1 hour) provides an overview of the theorem prover.</li>

 <li>The <a href='http://tryacl2.org'>Try ACL2</a> web site provides
 interactive lessons to get you started using ACL2.</li>

 <li>See @(see introduction-to-the-theorem-prover) (10-40 hours) for
 instruction on how to interact with the system.  Unlike the three documents
 above, this document expects you to <i>think</i>!  It cites the necessary
 background pages on programming in ACL2 and on the logic and then instructs
 you in @(see the-method), which is how expert users use ACL2.  It concludes
 with some challenge problems for the ACL2 beginner (including solutions) and
 an FAQ.  Most users will spend several hours a day for several days working
 through this material.</li>

 <li>The book <a
 href='http://www.cs.utexas.edu/users/moore/publications/acl2-books/car/index.html'>Computer-Aided
 Reasoning: An Approach</a> is worth a careful read, as you work exercises and
 learn @(see the-method).</li>

 <li><see topic='@(url ANNOTATED-ACL2-SCRIPTS)'>Annotated ACL2 Scripts and
 Demos</see> contains relatively elementary proof scripts that have been
 annotated to help train the newcomer.</li>

 <li>Many files (``books'') in the ACL2 community books (see @(see
 community-books)) are extensively annotated.</li>

 <li>An <see topic='@(url ALTERNATIVE-INTRODUCTION)'>Alternative
 Introduction</see> document, while largely subsumed by the <see topic='@(url
 INTRODUCTION-TO-THE-THEOREM-PROVER)'>Introduction to the Theorem Prover</see>
 mentioned above, still might be useful because it covers much of the tutorial
 material in a different way.</li>

 </ul>

 <p>At this point you are probably ready to use ACL2 on your own <i>small</i>
 projects.  A common mistake for beginners is to browse the documentation and
 then try to do something that is too big!  Think of a very small project and
 then simplify it!</p>

 <p>Note that ACL2 has a very supportive user network.  See the link to
 ``Mailing Lists'' on the <a
 href='http://www.cs.utexas.edu/users/moore/acl2'>ACL2 home page</a>.</p>

 <p>The topics listed below are a hodge podge, developed over time.  Although
 some of these are not mentioned above, you might find some to be useful as
 well.</p>")

(defxdoc acl2-user
  :parents (packages)
  :short "A package the ACL2 user may prefer"
  :long "<p>This package imports the standard Common Lisp symbols that ACL2
 supports and also a few symbols from package @('\"ACL2\"') that are commonly
 used when interacting with ACL2.  You may prefer to select this as your
 current package so as to avoid colliding with ACL2 system names.</p>

 <p>This package imports the symbols listed in
 @('*common-lisp-symbols-from-main-lisp-package*'), which contains hundreds of
 CLTL function and macro names including those supported by ACL2 such as @(tsee
 cons), @(tsee car), and @(tsee cdr).  It also imports the symbols in
 @('*acl2-exports*'), which contains a few symbols that are frequently used
 while interacting with the ACL2 system, such as @(tsee implies), @(tsee
 defthm), and @(tsee rewrite).  It imports nothing else.</p>

 <p>Thus, names such as @(tsee alistp), @(tsee member-equal), and @(tsee
 type-set), which are defined in the @('\"ACL2\"') package are not present
 here.  If you find yourself frequently colliding with names that are defined
 in @('\"ACL2\"') you might consider selecting @('\"ACL2-USER\"') as your
 current package (see @(see in-package)).  If you select @('\"ACL2-USER\"') as
 the current package, you may then simply type @(tsee member-equal) to refer to
 @('acl2-user::member-equal'), which you may define as you see fit.  Of course,
 should you desire to refer to the @('\"ACL2\"') version of @(tsee
 member-equal), you will have to use the @('\"ACL2::\"') prefix, e.g.,
 @('acl2::member-equal').</p>

 <p>If, while using @('\"ACL2-USER\"') as the current package, you find that
 there are symbols from @('\"ACL2\"') that you wish we had imported into it
 (because they are frequently used in interaction), please bring those symbols
 to our attention.  For example, should @(tsee union-theories) and @(tsee
 universal-theory) be imported?  Except for stabilizing on the ``frequently
 used'' names from @('\"ACL2\"'), we intend never to define a symbol whose
 @(tsee symbol-package-name) is @('\"ACL2-USER\"').</p>")

(defxdoc acl2p-key-checkpoints
  :parents (parallel-proof)
  :short "Key checkpoints in ACL2(p)"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 <p>For printing output, the parallel version of the waterfall follows the
 precedent of @(tsee gag-mode).  The idea behind gag mode is to print only the
 subgoals most relevant to debugging a failed proof attempt.  These subgoals
 are called 'key checkpoints' (see @(see set-gag-mode) for the definition of
 ``key'' and ``checkpoint''), and we restrict the default output mode for the
 parallel version of the waterfall to printing checkpoints similar to these key
 checkpoints.</p>

 <p>As of this writing, we are aware of exactly one discrepancy between gag
 mode's key checkpoints and the parallel version of the waterfall's
 checkpoints.  This discrepancy occurs when using ``by'' hints (see @(see
 hints)).  As an example, take the following form, which attempts to prove a
 non-theorem:</p>

 @({
  (thm (equal (append x y z) (append z (append y x)))
       :hints ((\"Subgoal *1/2'''\" :by nil)))
 })

 <p>With waterfall parallelism enabled, @('Subgoal *1/2''') will be printed as
 a key checkpoint.  This is different from using @(tsee gag-mode) while running
 the serial version of the waterfall, which skips printing the subgoal as a
 checkpoint.</p>

 <p>For those familiar with the ACL2 waterfall, we note that that the parallel
 version of the waterfall prints key checkpoints that are unproved in the
 following sense: a subgoal is a key checkpoint if it leads, in the current
 call of the waterfall, to a goal that is pushed for induction.</p>")

(defxdoc acons
  :parents (alists acl2-built-ins)
  :short "Constructor for association lists"
  :long "<p>@('(Acons key datum alist)') equals the result of consing the pair
 @('(cons key datum)') to the front of the association list @('alist').</p>

 <p>@('(Acons key datum alist)') has a @(see guard) of @('(alistp alist)').
 @('Acons') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def acons)")

(defxdoc active-runep
  :parents (theories)
  :short "Check that a @(see rune) exists and is @(see enable)d"
  :long "@({
  Example:
  (active-runep '(:rewrite left-to-right))

  General Form:
  (active-runep rune &optional strict)
 })

 <p>where @('rune') has the shape of a @(see rune).  This macro expands to an
 expression using the variables @('ens') and @('state'), and returns
 non-@('nil') when the given rune exists and is @(see enable)d (according to
 the given ``enabled structure,'' @('ens'), and the current logical @(see
 world) of the given @(tsee state)).  See @(see theory-invariant) for how this
 macro can be of use.</p>

 <p>When the optional argument is @('nil') or is omitted, then although the
 argument is required to have the shape of a @(see rune), it need not be a
 rune.  For example, if there is no rewrite rule named @('left-to-right'), then
 @('(active-runep '(:rewrite left-to-right))') will simply return @('nil').  If
 instead you'd like this call to cause an error, use a non-nil optional
 argument or, equivalently, use @(tsee active-or-non-runep).</p>")

(defxdoc active-or-non-runep
  :parents (theories)
  :short "Require a @(see rune) to exist, and check that it is @(see enable)d"
  :long "<p>This variant of @('active-runep') causes an error if its argument
  is not a @(see rune).  See @(see active-runep).</p>")

(defxdoc add-binop
  :parents (macros)
  :short "Associate a function name with a macro name"
  :long "<p>The form @('(add-binop macro macro-fn)') is an abbreviation for the
 form @('(add-macro-fn macro macro-fn t)').  See @(see add-macro-fn).</p>")

(defxdoc add-custom-keyword-hint
  :parents (events)
  :short "Add a new custom keyword hint"
  :long "@({
  Examples:
  (add-custom-keyword-hint :my-hint (my-hint-fn val ...))

  (add-custom-keyword-hint :my-hint
                           (my-hint-fn val ...)
                           :checker (my-hint-checker-fn val ...))
 })

 @({
  General Form:
  (add-custom-keyword-hint :key term1 :checker term2)
 })

 <p>where @(':key') is a @(tsee keywordp) not among the primitive keyword hints
 listed in @('*hint-keywords*'), the @(':checker') argument is optional, and
 @('term1') and (if supplied) @('term2') are terms with certain free-variable
 and signature restrictions described below.  Henceforth, @(':key') is treated
 as a custom keyword hint, e.g., the user can employ @(':key') in hints to
 @(tsee defthm), such as:</p>

 @({
  (defthm name ...
    :hints ((\"Subgoal *1/1'\" ... :key val ...))).
 })

 <p>Custom keyword hints are complicated.  To use them you must understand
 @(tsee state), multiple values (e.g., @(tsee mv) and @(tsee mv-let)), ACL2's
 notion of error triples (see @(see programming-with-state)), how to generate
 ``soft'' errors with @(tsee er), how to use @(tsee fmt)-strings to control
 output, how to use computed hints (see @(see computed-hints)) and some aspects
 of ACL2's internal event processing.  Furthermore, it is possible to implement
 a custom keyword hint that can make an event non-reproducible!  So we
 recommend that these hints be developed by ACL2 experts.  Basically the custom
 keyword feature allows the implementors and other experts to extend the hint
 facility without modifying the ACL2 sources.</p>

 <p>@('Term1') is called the ``generator'' term and @('term2') is called the
 ``checker'' term of the custom keyword hint @(':key').  Together they specify
 the semantics of the new custom keyword hint @(':key').  Roughly speaking,
 when a custom keyword hint is supplied by the user, as in</p>

 @({
  (defthm name ...
    :hints ((\"Subgoal *1/1'\" ... :my-hint val ...))).
 })

 <p>the checker term is evaluated on @('val') to check that @('val') is of the
 expected shape.  Provided @('val') passes the check, the generator term is
 used to compute a standard hint.  Like computed hints, the generator of a
 custom keyword hint is allowed to inspect the actual clause on which it is
 being fired.  Indeed, it is allowed to inspect the entire list of hints
 (standard and custom) supplied for that clause.  Thus, in the most general
 case, a custom keyword hint is just a very special kind of computed hint.</p>

 <p>The generator, @('term1'), must have no free variables other than:</p>

 @({
  (val keyword-alist
   id clause world stable-under-simplificationp
   hist pspv ctx state).
 })

 <p>Moreover, either @('term1') must evaluate to a single non-@(see stobj)
 value, or else it must be single-threaded in @('state') and have the standard
 @(see error-triple) output signature, @('(mv * * state)').</p>

 <p>The restrictions on the checker, @('term2'), are that it be single-threaded
 in @('state'), have the standard @(see error-triple) output signature, @('(mv * *
 state)'), and have no free variables other than:</p>

 @({
  (val world ctx state).
 })

 <p>For examples, see the community books directory @('books/hints/'), in
 particular @('basic-tests.lisp').</p>

 <p>To delete a previously added custom keyword hint, see @(see
 remove-custom-keyword-hint).</p>

 <p>The community book @('hints/merge-hint.lisp') can be useful in writing
 custom keyword hints.  See the examples near the of the file.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>")

(defxdoc add-default-hints
  :parents (default-hints)
  :short "Add to the default hints"
  :long "@({
  Examples:
  (add-default-hints '((computed-hint-1 clause)
                       (computed-hint-2 clause
                                        stable-under-simplificationp)))
  (add-default-hints '((computed-hint-3 id clause world))
                     :at-end t)
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.  It is
 @(tsee local) to the book or @(tsee encapsulate) form in which it occurs (see
 @(see add-default-hints!) for a corresponding non-@(tsee local) event).</p>

 @({
  General Forms:
  (add-default-hints lst)
  (add-default-hints lst :at-end flg)
 })

 <p>where @('lst') is a list.  Generally speaking, the elements of @('lst')
 should be suitable for use as @(tsee computed-hints).</p>

 <p>This event is completely analogous to @(tsee set-default-hints), the
 difference being that @('add-default-hints') appends the indicated hints to
 the front of the list of default hints, so that they are tried first &mdash;
 or, if @('flg') is supplied and evaluates to other than @('nil'), at the end
 of the list, so that they are tried last &mdash; rather than <b>replacing</b>
 the default hints with the indicated hints.  Each new hint is thus considered
 after each existing hints when both are applied to the same goal.  Also See
 @(see set-default-hints), see @(see remove-default-hints), and see @(see
 default-hints).</p>

 <p>Finally, note that the effects of @('set-default-hints'), @(tsee
 add-default-hints), and @(tsee remove-default-hints) are @(tsee local) to the
 book in which they appear.  Thus, users who include a book with such forms
 will not have their default hints affected by such forms.  In order to export
 the effect of setting the default hints, use @(tsee set-default-hints!),
 @(tsee add-default-hints!), or @(tsee remove-default-hints!).</p>

 <p>For a related feature, which however is only for advanced system builders,
 see @(see override-hints).</p>")

(defxdoc add-default-hints!
  :parents (default-hints)
  :short "Add to the default hints non-@(tsee local)ly"
  :long "<p>Please see @(see add-default-hints), which is the same as
 @('add-default-hints!')  except that the latter is not @(tsee local) to the
 @(tsee encapsulate) or the book in which it occurs.  Probably @(see
 add-default-hints) is to be preferred unless you have a good reason for
 wanting to export the effect of this event outside the enclosing @(tsee
 encapsulate) or book.</p>")

(defxdoc add-dive-into-macro
  :parents (dive-into-macros-table)
  :short "Associate @(see proof-builder) diving function with macro name"
  :long "@({
  Examples:
  (add-dive-into-macro cat expand-address-cat)
 })

 <p>This feature is used so that the interactive @(see proof-builder)'s @('DV')
 command and numeric diving commands (e.g., @('3')) will dive properly into
 subterms.  Please see @(see dive-into-macros-table).</p>")

(defxdoc add-include-book-dir
  :parents (books-reference)
  :short "Link keyword for @(':dir') argument of @(tsee ld) and @(tsee
include-book)"
  :long "@({
 Example Forms:

 ; For (include-book \"foo\" :dir :smith), prepend \"/u/smith/\" to \"foo\".
 (add-include-book-dir :smith \"/u/smith/\")

 ; For (include-book \"bar\" :dir :util), prepend absolute directory pathname
 ; corresponding to the relative pathname, \"utilities/\".
 (add-include-book-dir :util \"utilities\")
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.  It is
 @(tsee local) to the book or @(tsee encapsulate) form in which it occurs.  See
 @(tsee add-include-book-dir!) for a corresponding non-@(tsee local) event.</p>

 @({
  General Form:
  (add-include-book-dir kwd dir)
 })

 <p>where @('kwd') is a @(tsee keywordp) and @('dir') is a relative or absolute
 @(see pathname) for a directory, optionally using the syntax @('(:system
 . filename)') described in @(see full-book-name).  If the final '@('/')' is
 missing for the resulting directory, ACL2 will add it for you.  The effect of
 this event is to modify the meaning of the @(':dir') keyword argument of
 @(tsee include-book) or @(tsee ld) as indicated by the examples above, that
 is, by associating the indicated directory with the indicated keyword for
 purposes of the @(':dir') argument.  By the ``indicated directory'' we mean,
 in the case that the pathname is a relative pathname, the directory relative
 to the current connected book directory; see @(see cbd).  See @(see
 delete-include-book-dir) for how to undo this effect.</p>

 <p>For a keyword already associated with a directory string by a previous
 invocation of @('add-include-book-dir') or @(tsee add-include-book-dir!), it
 is illegal to associate a different directory string until removing the
 existing association; see @(see delete-include-book-dir) (and see @(see
 delete-include-book-dir!) if the existing association was made by @(tsee
 add-include-book-dir!).  If however the new directory string is identical with
 the existing one, which was already assigned by @('add-include-book-dir'),
 then the new call of @('add-include-book-dir') will be redundant (see @(see
 redundant-events)).</p>

 <p>The keyword @(':system') can never be redefined.  It will always point to
 the absolute pathname of the system books directory, which by default is
 immediately under the directory where the ACL2 executable was originally built
 (see @(see include-book), in particular the discussion there of ``books
 directory'').</p>

 <p>This macro generates a @(tsee table) event that updates the table
 @('include-book-dir!-table'), which associates keywords with absolute
 pathnames.  However, as with @(tsee add-include-book-dir), direct table
 updates are disallowed; you must use @('add-include-book-dir!') to add to the
 table and @(tsee delete-include-book-dir!) to remove from the table.</p>

 <p>It is illegal to call @('add-include-book-dir!') in a @(tsee local)
 context.  (If you are tempted to do that, consider using @(tsee
 add-include-book-dir) instead.)  To understand this restriction, imagine a
 book that contains the following sequence of @(see events).</p>

 @({
 (add-include-book-dir! :my-dir \"path/to/BAD/dir\")
 (local (delete-include-book-dir! :my-dir))
 (local (add-include-book-dir! :my-dir \"path/to/GOOD/dir\"))
 (include-book \"foo\" :dir :my-dir)
 (defthm f-def
   (equal (f x) x))
 })

 <p>During the first (proof) pass of @(tsee certify-book), the book
 @('path/to/GOOD/dir/foo.lisp') will be included.  But on the second pass, the
 book @('path/to/BAD/dir/foo.lisp') will be included.  Now imagine that the
 ``good'' version contains the event @('(defun f (x) x)') but the ``bad''
 version instead contains the event @('(defun f (x) (not x))').  Then we can
 easily prove @('nil') from the theorem @('f-def')!  Although it is likely that
 @(see book-hash) values could catch this error at @(tsee include-book) time,
 we prefer not to rely on these for soundness.</p>")

(defxdoc add-include-book-dir!
  :parents (books-reference)
  :short "Non-@(tsee local)ly link keyword for @(':dir') argument of @(tsee ld)
and @(tsee include-book)"
  :long "<p>Please see @(see add-include-book-dir), which has completely
 analogous syntax and semantics, except that @('add-include-book-dir!') is not
 @(tsee local) to the @(tsee encapsulate) or the book in which it occurs.
 Probably @(tsee add-include-book-dir) is to be preferred unless you have a
 good reason for wanting to export the effect of this event outside the
 enclosing @(tsee encapsulate) or book.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 <p>This macro is essentially a @(tsee table) event that updates the table
 @('include-book-dir!-table'), which associates keywords with absolute
 pathnames.  However, as with @(tsee add-include-book-dir), direct table
 updates are disallowed; you must use @('add-include-book-dir!') to add to the
 table and @(tsee delete-include-book-dir!) to remove from the table.</p>

 <p>It is illegal to call @('add-include-book-dir!') in a @(tsee local)
 context.  (If you are tempted to do that, consider using @(tsee
 add-include-book-dir) instead.)  To understand this restriction, imagine a
 book that contains the following sequence of @(see events).</p>

 @({
 (add-include-book-dir! :my-dir \"path/to/BAD/dir\")
 (local (delete-include-book-dir! :my-dir))
 (local (add-include-book-dir! :my-dir \"path/to/GOOD/dir\"))
 (include-book \"foo\" :dir :my-dir)
 (defthm f-def
   (equal (f x) x))
 })

 <p>During the first (proof) pass of @(tsee certify-book), the book
 @('path/to/GOOD/dir/foo.lisp') will be included.  But on the second pass, the
 book @('path/to/BAD/dir/foo.lisp') will be included.  Now imagine that the
 ``good'' version contains the event @('(defun f (x) x)') but the ``bad''
 version instead contains the event @('(defun f (x) (not x))').  Then we can
 easily prove @('nil') from the theorem @('f-def')!  Although it is likely that
 @(see book-hash) values could catch this error at @(tsee include-book) time,
 we prefer not to rely on these for soundness.</p>")

(defxdoc add-invisible-fns
  :parents (loop-stopper)
  :short "Make some unary functions invisible to the @(see loop-stopper) algorithm"
  :long "@({
  Examples:
  (add-invisible-fns binary-+ unary-- foo)
  (add-invisible-fns + unary-- foo)
 })

 <p>Each of the @(see events) above makes unary functions @(tsee unary--) and
 @('foo') ``invisible'' for the purposes of applying permutative @(':')@(tsee
 rewrite) rules to @(tsee binary-+) trees.  Thus, @('arg') and @('(unary--
 arg)') will be given the same weight and will be permuted so as to be
 adjacent.</p>

 @({
  General Form:
  (add-invisible-fns top-fn unary-fn1 ... unary-fnk)
 })

 <p>where @('top-fn') is a function symbol and the @('unary-fni') are unary
 function symbols, or more generally, these are all macro aliases for function
 symbols (see @(see macro-aliases-table)).</p>

 <p>For more information see @(see invisible-fns-table).  Also see @(see
 set-invisible-fns-table), which explains how to set the entire table in a
 single event, and see @(see remove-invisible-fns).</p>")

(defxdoc add-macro-alias
  :parents (macros)
  :short "Associate a function name with a macro name"
  :long "@({
  Example:
  (add-macro-alias append binary-append)
 })

 <p>This example associates the function symbol @(tsee binary-append) with the
 macro name @(tsee append).  As a result, the name @(tsee append) may be used
 as a runic designator (see @(see theories)) by the various theory functions.
 See @(see macro-aliases-table) for more details.  Also see @(see add-macro-fn)
 for an extension of this utility that also affects printing.</p>

 @({
  General Form:
  (add-macro-alias macro-name function-name)
 })

 <p>This is a convenient way to add an entry to @(tsee macro-aliases-table).
 See @(see macro-aliases-table) and also see @(see remove-macro-alias).</p>")

(defxdoc add-macro-fn
  :parents (macros)
  :short "Associate a function name with a macro name"
  :long "@({
  Examples:
  (add-macro-fn append binary-append)
  (add-macro-fn append binary-append t)
 })

 <p>These examples each associate the function symbol @(tsee binary-append)
 with the macro name @(tsee append).  As a result, theory functions will
 understand that @('append') refers to @('binary-append') &mdash; see @(see
 add-macro-alias) &mdash; and moreover, proof output will be printed using
 @('append') rather than @('binary-append').  In the first case, @('(append x
 (append y z))') is printed rather than @('(append x y z)').  In the second
 case, right-associated arguments are printed flat: @('(append x y z)').  Such
 right-association is considered only for binary function symbols; otherwise
 the optional third argument is ignored.</p>

 @({
  General Forms:
  (add-macro-fn macro-name function-name)
  (add-macro-fn macro-name function-name nil) ; same as above
  (add-macro-fn macro-name function-name t)
 })

 <p>This is a convenient way to add an entry to @(tsee macro-aliases-table) and
 at the same time extend the @(tsee untrans-table).  As suggested by the
 example above, calls of a function in this table will be printed as
 corresponding calls of macros, with right-associated arguments printed flat in
 the case of a binary function symbol if the optional third argument is t.  In
 that case, for a binary function symbol @('fn') associated with macro name
 @('mac'), then a call @('(fn arg1 (fn arg2 (... (fn argk arg))))') will be
 displayed to the user as though the ``term'' were @('(mac arg1 arg2 ... argk
 arg)').  For a call @('(f a1 ... ak)') of a function symbol that is not
 binary, or the optional argument is not supplied as @('t'), then the effect is
 simply to replace @('f') by the corresponding macro symbol.  See @(see
 add-macro-alias), which is invoked on the first two arguments.  Also see @(see
 remove-macro-alias), see @(see untrans-table), and see @(see
 remove-macro-fn).</p>")

(defxdoc add-match-free-override
  :parents (free-variables)
  :short "Set @(':match-free') value to @(':once') or @(':all') in existing
  rules"
  :long "@({
  Example Forms:
  (add-match-free-override :once t)
      ; Try only the first binding of free variables when relieving hypotheses
      ; of any rule of class :rewrite, :linear, or :forward-chaining.
  (add-match-free-override :all (:rewrite foo) (:rewrite bar))
      ; For rewrite rules foo and bar, try all bindings of free variables when
      ; relieving hypotheses.
  (add-match-free-override :clear)
      ; Restore :match-free to what was originally stored for each rule (either
      ; :all or :once).
 })

 <p>As described elsewhere (see @(see free-variables)), a @(see rewrite), @(see
 linear), or @(see forward-chaining) rule may have free variables in its
 hypotheses, and ACL2 can be directed either to try all bindings
 (``@(':all')'') or just the first (``@(':once')'') when relieving a
 hypothesis, as a basis for relieving subsequent hypotheses.  This direction is
 generally provided by specifying either @(':match-free :once') or
 @(':match-free :all') in the @(':')@(tsee rule-classes) of the rule, or by
 using the most recent @(tsee set-match-free-default) event.  Also see @(see
 rule-classes).</p>

 <p>However, if a proof is going slowly, you may want to modify the behavior of
 some such rules so that they use only the first match for free variables in a
 hypothesis when relieving subsequent hypotheses, rather than backtracking and
 trying additional matches as necessary.  (But note:
 @('add-match-free-override') is not relevant for @(see type-prescription)
 rules.)  The event @('(add-match-free-override :once t)') has that effect.  Or
 at the other extreme, perhaps you want to specify all rules as @(':all') rules
 except for a some specific exceptions.  Then you can execute
 @('(add-match-free-override :all t)') followed by, say,
 @('(add-match-free-override :once (:rewrite foo) (:linear bar))').</p>

 @({
  General Forms:
  (add-match-free-override :clear)
  (add-match-free-override flg t)
  (add-match-free-override flg rune1 rune2 ... runek)
 })

 <p>where @('flg') is @(':once') or @(':all') and the @('runei') are @(tsee
 rune)s.  If @(':clear') is specified then all rules will have the
 @(':all')/@(':once') behavior from when they were first stored.  The second
 general form causes all @(see rewrite) @(see linear), and @(see
 forward-chaining) rules to have the behavior specified by @('flg') (@(':all')
 or @(':once')).  Finally, the last of these, where runes are specified, is
 additive in the sense that only the indicated rules are affected; all others
 keep the behavior they had just before this event was executed (possible
 because of earlier @('add-match-free-override') events).</p>

 <p>At the conclusion of this event, ACL2 prints out the list of all
 @(':')@(tsee linear), @(':')@(tsee rewrite), and @(':')@(tsee
 forward-chaining) runes whose rules contain free variables in hypotheses that
 are to be bound @(':once'), except that if there are no overrides (value
 @(':clear') was used), then @(':clear') is printed.</p>

 <p>This event only affects rules that exist at the time it is executed.
 Future rules are not affected by the override.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.  It
 uses the @(tsee acl2-defaults-table), and hence its effect is @(tsee local) to
 the book or @(tsee encapsulate) form in which it occurs.</p>

 <p><i>Remarks</i></p>

 <p>Lists of the @(':')@(tsee rewrite), @(':')@(tsee linear), and @(':')@(tsee
 forward-chaining) @(see rune)s whose behavior was originally @(':once') or
 @(':all') are returned by the following forms, respectively.</p>

 @({
  (free-var-runes :once (w state))
  (free-var-runes :all  (w state))
 })

 <p>The form</p>

 @({
  (match-free-override (w state))
 })

 <p>evaluates to a pair, whose @(tsee car) is a number used by ACL2 to
 determine whether a @(see rune) is sufficiently old to be affected by the
 override, and whose @(tsee cdr) is the list of @(see rune)s whose behavior is
 specified as @(':once') by @('add-match-free-override'); except, if no runes
 have been overridden, then the keyword @(':clear') is returned.</p>")

(defxdoc add-nth-alias
  :parents (nth-aliases-table)
  :short "Associate one symbol with another for printing of @(tsee nth)/@(tsee update-nth) terms"
  :long "@({
  Example:
  (add-nth-alias st0 st)
 })

 <p>This example associates the symbol @('st0') with the symbol @('st') for
 purposes of printing certain terms of the form @('(nth n st0)') and
 @('(update-nth n val st0)').</p>

 @({
  General Form:
  (add-nth-alias alias-name name)
 })

 <p>This is a convenient way to add an entry to @(tsee nth-aliases-table).  See
 @(see nth-aliases-table) and also see @(see remove-nth-alias).</p>")

(defxdoc add-override-hints
  :parents (override-hints)
  :short "Add to the @(see override-hints)"
  :long "<p>See @(see override-hints) for a discussion of override-hints.  Here
 we describe how to extend the list of override-hints.  Note that the effects
 of @('add-override-hints') @(see events) are @(see local) to the @(see books)
 or @('encapsulate') @(see events) in which they reside; see @(see
 add-override-hints!) to avoid that restriction.  Also see @(see
 set-override-hints) to set a new list of override-hints to it, ignoring the
 present list rather than adding to it.</p>

 @({
  General Forms:
  (add-override-hints form)
  (add-override-hints form :at-end t)
  (add-override-hints form :at-end nil) ; default for :at-end
 })

 <p>where @('form') evaluates to a list of computed hint forms.  The effect of
 this event is to extend the current list of @(see override-hints) by appending
 the result of that evaluation.  The default is to append the evaluation result
 to the front of the current list of override-hints, but if @(':at-end t') is
 specified, then the evaluation result is appended to the end of the current
 list.</p>")

(defxdoc add-override-hints!
  :parents (override-hints)
  :short "Add non-@(see local)ly to the @(see override-hints)"
  :long "<p>@('Add-override-hints!') is the same as @(tsee add-override-hints),
 except that the former is not @(see local) to @(see books) or @(tsee
 encapsulate) @(see events) in which it occurs.  See @(see add-override-hints);
 also see @(see set-override-hints).</p>")

(defxdoc add-raw-arity
  :parents (set-raw-mode)
  :short "Add arity information for raw mode"
  :long "<p>Technical note: This macro is a no-op, and is not necessary, when
 ACL2 is built with #-acl2-mv-as-values.</p>

 <p>Users of raw mode (see @(see set-raw-mode)) can use arbitrary raw Lisp
 functions that are not known inside the usual ACL2 loop.  In such cases, ACL2
 may not know how to display a multiple value returned by ACL2's @(tsee mv)
 macro.  The following example should make this clear.</p>

 @({
  ACL2 P>(defun foo (x y) (mv y x))
  FOO
  ACL2 P>(foo 3 4)

  Note: Unable to compute number of values returned by this evaluation
  because function FOO is not known in the ACL2 logical world.  Presumably
  it was defined in raw Lisp or in raw mode.  Returning the first (perhaps
  only) value for calls of FOO.
  4
  ACL2 P>(add-raw-arity foo 2)
   RAW-ARITY-ALIST
  ACL2 P>(foo 3 4)
  (4 3)
  ACL2 P>
 })

 <p>The first argument of @('add-raw-arity') should be a symbol, representing
 the name of a function, macro, or special form, and the second argument should
 either be a non-negative integer (denoting the number of values returned by
 ACL2) or else the symbol @(':LAST'), meaning that the number of values
 returned by the call is the number of values returned by the last
 argument.</p>

 <p>The current arity assignments can be seen by evaluating @('(@
 raw-arity-alist)').  See @(see remove-raw-arity) for how to undo a call of
 @('add-raw-arity').</p>")

(defxdoc add-to-set
  :parents (lists symbols acl2-built-ins)
  :short "Add a symbol to a list"
  :long "@({
  General Forms:
  (add-to-set x lst)
  (add-to-set x lst :test 'eql)   ; same as above (eql as equality test)
  (add-to-set x lst :test 'eq)    ; same, but eq is equality test
  (add-to-set x lst :test 'equal) ; same, but equal is equality test
 })

 <p>For a symbol @('x') and an object @('lst'), @('(add-to-set-eq x lst)') is
 the result of @(tsee cons)ing @('x') on to the front of @('lst'), unless
 @('x') is already a @(tsee member) of @('lst'), in which case the result is
 @('lst'). The optional keyword, @(':TEST'), has no effect logically, but
 provides the test (default @(tsee eql)) used for comparing @('x') with
 successive elements of @('lst').</p>

 <p>The @(see guard) for a call of @('add-to-set') depends on the test.  In all
 cases, the second argument must satisfy @(tsee true-listp).  If the test is
 @(tsee eql), then either the first argument must be suitable for @(tsee eql)
 (see @(see eqlablep)) or the second argument must satisfy @(tsee
 eqlable-listp).  If the test is @(tsee eq), then either the first argument
 must be a symbol or the second argument must satisfy @(tsee symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('add-to-set') and its variants:</p>

 <blockquote><p>@('(add-to-set-eq x lst)') is equivalent to @('(add-to-set x
 lst :test 'eq)');</p>

 <p>@('(add-to-set-equal x lst)') is equivalent to @('(add-to-set x lst :test
 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('add-to-set-equal').</p>")

(defxdoc advanced-features
  :parents (acl2-tutorial)
  :short "Some advanced features of ACL2"
  :long "<p>Maybe you've been using ACL2 for awhile, and you wonder if there
 are lesser-known features that you might find useful.  Then this topic is for
 you.  We present below a ``laundry list'' of some such features, with brief
 descriptions and links to @(see documentation) topics.</p>

 <p>Although the list below is long, it is not intended to be complete, and
 indeed some topics have been deliberately excluded.  Some have fallen out of
 use, perhaps for good reason, such as @(see OBDD).  Others are already likely
 to be discovered when needed, such as @(tsee GETENV$) and perhaps @(tsee
 DOUBLE-REWRITE).  Some topics are referenced by documentation for others in
 the list, such as @(tsee MBT), which is referenced by @(tsee MBE).  Some
 utilities such as @(tsee PSTACK) and @(tsee VERBOSE-PSTACK) seem too low-level
 to be worthy of inclusion below.</p>

 <p>For an extensive introduction to using the prover, which may include some
 aspects new to you, see @(see INTRODUCTION-TO-THE-THEOREM-PROVER).  A shorter
 topic contains highlights for efficient prover usage: see @(see TIPS).  Also
 see @(see ACL2-SEDAN) for an extension of ACL2 (written by others), ACL2s,
 that includes an Eclipse-based interface, more powerful and automatic
 termination reasoning, and other features.</p>

 <p>We now move on to the list.</p>

 <h3>Top-level commands and utilities:</h3>

 <ul>
 <li>See @(see A!) and see @(see P!) to abort or pop.</li>

 <li>See @(see ACL2-CUSTOMIZATION) for initial commands to run at startup.</li>

 <li>See @(see KEYWORD-COMMANDS) for how keyword commands are processed.</li>

 <li>See @(see LD) for many ways to control the top-level loop.</li>

 <li>See @(see COMPILATION) for a discussion of @('set-compiler-enabled') and
 other compiler-related utilities.</li>

 <li>For useful reader macros `@('#!')', `@('#.')', and `@('#u')', see @(see
 SHARP-BANG-READER), see @(see SHARP-DOT-READER), and see @(see
 SHARP-U-READER).</li>

 <li>To save and use an ACL2 executable, see @(see ACL2-AS-STANDALONE-PROGRAM)
 and see @(see SAVE-EXEC).</li>

 <li>For utilities related to timing, see @(see TIME$), see @(see
 WITH-PROVER-TIME-LIMIT), see @(see WITH-PROVER-STEP-LIMIT), and see @(see
 SET-PROVER-STEP-LIMIT).</li>

 <li>To query and manage the database, see @(see HISTORY) (which discusses
 many useful utilities, such as @(':')@(tsee PBT) and @(':')@(tsee PL)), and
 see @(see DEAD-EVENTS).</li>

 <li>See @(see ADD-INCLUDE-BOOK-DIR) for linking keyword for @(':dir')
 argument of @(tsee LD) and @(tsee INCLUDE-BOOK).</li>

 <li>See @(see REBUILD) for a fast way to load a file without waiting for
 proofs.</li>

 <li>For parallel certification, see @(see BOOKS-CERTIFICATION) for use of the
 @('-j') option of `make'; also see @(see
 PROVISIONAL-CERTIFICATION).</li>

 </ul>

 <h3>Some relatively less common events</h3>

 <ul>

 <li>See @(see RESET-PREHISTORY) to reset the prehistory.</li>

 <li>See @(see ASSERT-EVENT) to assert that a given form returns a non-nil
 value.</li>

 <li>See @(see DEFATTACH) to execute constrained functions using corresponding
 attached functions.</li>

 <li>See @(see DEFUN-SK) to define a function whose body has an outermost
 quantifier.</li>

 <li>See @(see DEFCHOOSE) to define a Skolem (witnessing) function.</li>

 <li>For efficiency consider using @('defconst-fast'); see @(see
 DEFCONST).</li>

 <li>See @(see SET-VERIFY-GUARDS-EAGERNESS) to specify when @(see guard)
 verification is tried by default.</li>

 </ul>


 <h3>Output and its control (see @(see IO) for additional information)</h3>

 <ul>

 <li>See @(see WITH-OUTPUT) to suppress or turn on specified
 output for an event.</li>

 <li>See @(see EVISC-TABLE) for support for abbreviated output.</li>

 <li>See @(see NTH-ALIASES-TABLE) for a table used to associate names for
 @(tsee NTH)/@(tsee UPDATE-NTH) printing.</li>

 <li>See @(see OUTPUT-TO-FILE) to redirect output to a file.</li>

 <li>See @(see PRINT-CONTROL) to control ACL2 printing.</li>

 <li>See @(see SET-EVISC-TUPLE) to control suppression of details when
 printing.</li>

 <li>See @(see SET-INHIBIT-OUTPUT-LST) to control output by type.</li>

 <li>See @(see SET-IPRINT) to allow abbreviated output to be read back in.</li>

 <li>See @(see SET-PRINT-BASE-RADIX) (also @(see SET-PRINT-BASE) and @(see
 SET-PRINT-RADIX)) to control the radix in which numbers are printed.</li>

 <li>See @(see SET-PRINT-CASE) to control whether symbols are printed in upper
 case or in lower case.</li>

 </ul>

 <h3>On proving termination for definitions:</h3>

 <ul>

 <li>See @(see ORDINALS) for a discussion of ordinals in ACL2.</li>

 <li>See @(see RULER-EXTENDERS) for a control on ACL2's termination and
 induction analyses.</li>

 <li>See @(see SET-WELL-FOUNDED-RELATION) to set the default well-founded
 relation for termination analysis.</li>

 <li>See @(see ACL2-SEDAN) for a related tool that provides extra automation
 for termination proofs.</li>

 </ul>

 <h3>Proof debugging and output control:</h3>

 <ul>

 <li>See @(see ACCUMULATED-PERSISTENCE) to get statistics on which
 runes are being tried.</li>

 <li>See @(see ADD-MACRO-FN) and see @(see ADD-MACRO-ALIAS) to associate a
 function name with a macro name.</li>

 <li>See @(see BREAK-REWRITE) for how to monitor rewrite rules.</li>

 <li>See @(see DMR) for dynamic monitoring of rewriting and other prover
 activity.</li>

 <li>See @(see FORWARD-CHAINING-REPORTS) to see reports about the forward
 chaining process.</li>

 <li>See @(see GUARD-DEBUG) and @(see MEASURE-DEBUG) to generate markers to
 indicate sources of @(see guard) and termination proof obligations.</li>

 <li>See @(see PROOF-BUILDER) for support for low-level interaction.</li>

 <li>See @(see REDO-FLAT) for redo on failure of a @(tsee PROGN), @(tsee
 ENCAPSULATE), or @(tsee CERTIFY-BOOK).</li>

 <li>See @(see SET-GAG-MODE) and see @(see PSO) to abbreviate or restore proof
 output.</li>

 <li>See @(see SET-INHIBIT-OUTPUT-LST), see @(see SET-INHIBIT-WARNINGS), and
 see @(see SET-INHIBITED-SUMMARY-TYPES) to inhibit various types of output.</li>

 <li>See @(see SET-RAW-PROOF-FORMAT) to make proof output display lists of
 @(see rune)s.</li>

 <li>See @(see SET-RAW-WARNING-FORMAT) to make some warnings display in a
 ``raw'' s-expression format.</li>

 <li>See @(see SKIP-PROOFS) to skip proofs for a given form.</li>

 </ul>

 <h3>Program debugging:</h3>

 <ul>

 <li>See @(see BREAK$) to cause an immediate Lisp break.</li>

 <li>See @(see BREAK-ON-ERROR) to break when encountering a hard or soft error
 caused by ACL2.</li>

 <li>See @(see DISASSEMBLE$) to disassemble a function.</li>

 <li>See @(see PRINT-GV) to print a form whose evaluation caused a guard
 violation.</li>

 <li>See @(see PROFILE) to turn on profiling for one function.</li>

 <li>See @(see TRACE$) and see @(see OPEN-TRACE-FILE) to @(see trace) function
 evaluations, possibly sending trace output to a file.</li>

 <li>See @(see WET) to evaluate a form and print a subsequent error
 trace.</li>

 </ul>

 <h3>Programming and evaluation idioms, support, utilities</h3>

 <p>(also see @(see PROGRAMMING) for more utilities, e.g., @(tsee RANDOM$)).</p>

 <ul>

 <li>See @(see ARRAYS) and See @(see DEFSTOBJ) for introductions
 to ACL2 arrays and single-threaded objects (stobjs), respectively, each of
 which provides efficient destructive operations in an applicative setting.
 Also see @(see WITH-LOCAL-STOBJ) for a way to create local stobjs.</li>

 <li>See @(see ASSERT$) to cause a hard error if the given test is false.</li>

 <li>See @(see CANONICAL-PATHNAME) to obtain the true absolute filename, with
 soft links resolved.</li>

 <li>See @(see CASE-MATCH) for a utility providing pattern matching and
 destructuring.</li>

 <li>See @(see DEFPUN) to define a tail-recursive function symbol.</li>

 <li>See @(see EC-CALL) to execute a call in the ACL2 logic instead of raw
 Lisp.</li>

 <li>See @(see ER) to print an error message and ``cause an error''.</li>

 <li>See @(see FLET) to provide local binding of function symbols.</li>

 <li>See @(see GC$) to invoke the garbage collector.</li>

 <li>See @(see MBE) to attach code for execution.</li>

 <li>See @(see MV-LIST) to convert a multiple-valued result to a single-valued
 list.</li>

 <li>See @(see MV?) to return one or more values.</li>

 <li>For non-executable code, see @(see DEFUN-NX) and see @(see NON-EXEC).</li>

 <li>See @(see PROG2$) and see @(see PROGN$) to execute two or more forms and
 return the value of the last one.</li>

 <li>See @(see PROGRAMMING-WITH-STATE) for how to program using the von
 Neumannesque ACL2 @(see state) object.</li>

 <li>See @(see TOP-LEVEL) to evaluate a top-level form as a function body.</li>

 <li>See @(see WITH-GUARD-CHECKING) to suppress or enable guard-checking for a
 form.</li>

 <li>For ways to fake access to the state see @(see WORMHOLE), see @(see
 WITH-LOCAL-STATE), see @(see CW), see @(see CW!), see @(see
 PRINTING-TO-STRINGS), see @(see OBSERVATION-CW), and (dangerous!) see @(see
 WITH-LIVE-STATE).</li>

 </ul>

 <h3>Connecting with the underlying host Lisp, and doing other evil:</h3>

 <ul>

 <li>See @(see DEFTTAG) to introduce a trust tag (ttag).</li>

 <li>See @(see DEFMACRO-LAST) to define a macro that returns its last
 argument, but with side effects.</li>

 <li>See @(see PROGN!) to evaluate forms that are not necessarily @(see
 events).</li>

 <li>See @(see RETURN-LAST) to return the last argument, perhaps with side
 effects.</li>

 <li>See @(see SET-RAW-MODE) to enter or exit ``raw mode,'' a raw Lisp
 environment.</li>

 <li>See @(see SYS-CALL), @(see SYS-CALL+), and @(see SYS-CALL*) to make a
 system call to the host operating system.</li>

 </ul>

 <h3>Macros and related utilities:</h3>

 <ul>

 <li>See @(see DEFABBREV) for a convenient form of macro
 definition for simple expansions.</li>

 <li>See @(see MACRO-ARGS) for the formals list of a macro definition (see
 @(see DEFMACRO)).</li>

 <li>See @(see MAKE-EVENT) for a sort of extension of @(tsee DEFMACRO) that
 allows access to the @(see state), by evaluating (expanding) a given form and
 then evaluate the result of that expansion.</li>

 <li>See @(see TRANS), see @(see TRANS!), and see @(see TRANS1) to print the
 macroexpansion of a form.</li>

 </ul>

 <h3>Additional capabilities:</h3>

 <ul>

 <li>See @(see HONS-AND-MEMOIZATION) for a discussion of the @(see
 hons-enabled) features providing hash cons, function memoization, and
 applicative hash tables.  In particular, see @(see MEMOIZE) for efficient
 function memoization and see @(see PROFILE) for profiling.</li>

 <li>See @(see REAL) for ACL2(r), which supports the real numbers.</li>

 <li>See @(see PARALLELISM) for ACL2(p), which supports parallel evaluation
 and proof.</li>

 </ul>

 <h3>Database control and query:</h3>

 <ul>

 <li>See @(see DISABLEDP) to determine whether a given name or
 rune is disabled.</li>

 <li>For redefinition support see @(see REDEF), see @(see REDEF!), see @(see
 REDEF+), see @(see REDEF-), and see @(see REDEFINED-NAMES).</li>

 <li>See @(see TABLE) for user-managed tables.</li>

 <li>See @(see GUARD-FORMULA-UTILITIES) for how to view a guard proof
 obligation without doing the proof.</li>

 </ul>

 <h3>Prover control</h3>

 <ul>

 <li>For congruence-based reasoning see @(see DEFCONG), see @(see
 CONGRUENCE), see @(see EQUIVALENCE), see @(see DEFEQUIV), and see @(see
 DEFREFINEMENT).</li>

 <li>For meta rules and clause processors see @(see META), see @(see
 DEFEVALUATOR), see @(see CLAUSE-PROCESSOR), see @(see
 DEFINE-TRUSTED-CLAUSE-PROCESSOR) (for connecting with external tools, such as
 SAT solvers), and See @(see EXTENDED-METAFUNCTIONS) (for @(see state) and
 context-sensitive metafunctions).</li>

 <li>For theory control, see @(see THEORIES) for detailed information, but in
 particular see @(see DEFTHEORY), see @(see THEORY-FUNCTIONS), see @(see
 IN-ARITHMETIC-THEORY) (and see @(see NON-LINEAR-ARITHMETIC)), and see @(see
 THEORY-INVARIANT).</li>

 <li>See @(see HINTS) for a complete list of prover hints, including some of
 the more obscure ones such as @(':restrict'), @(':')@(tsee clause-processor),
 @(':nonlinearp'), @(':backchain-limit-rw'), @(':reorder'), and
 @(':backtrack').  Also see @(see HINTS-AND-THE-WATERFALL) for an explanation
 of how hints interact with the ACL2 proof process.  For other topics related
 to hints, see @(see OVERRIDE-HINTS), see @(see ADD-CUSTOM-KEYWORD-HINT), see
 @(see DEFAULT-HINTS), and see @(see COMPUTED-HINTS) and @(see
 USING-COMPUTED-HINTS).</li>

 <li>See @(see BIND-FREE) to bind @(see free-variables) of a @(see rewrite) or
 @(see linear) rule.</li>

 <li>See @(see CASE-SPLIT) for a utility like @(tsee FORCE) that immediately
 splits the top-level goal on the indicated hypothesis.</li>

 <li>See @(see CASE-SPLIT-LIMITATIONS) for a way to the number of cases
 produced at once</li>

 <li>See @(see DEFAULT-BACKCHAIN-LIMIT) to specify the backchain limit for a
 rule.</li>

 <li>See @(see FORCE) for an identity function used to force a hypothesis.</li>

 <li>See @(see OTF-FLG) for a way to push more than one initial subgoal for
 induction.</li>

 <li>See @(see RULE-CLASSES) to add various kinds of rules to the database,
 including more unusual sorts such as @(':')@(tsee built-in-clause) rules and
 @(':')@(tsee induction) rules.</li>

 <li>See @(see SET-BACKCHAIN-LIMIT) to set the backchain-limit used by the
 type-set and rewriting mechanisms.</li>

 <li>See @(see SET-BODY) to set an alternate definition body for @(':expand')
 @(see hints).</li>

 <li>See @(see SET-REWRITE-STACK-LIMIT) to set the @(see rewrite) stack depth
 used by the rewriter.</li>

 <li>See @(see SYNTAXP) to attach a heuristic filter on a @(':')@(tsee
 rewrite), @(':')@(tsee meta), or @(':')@(tsee linear) rule.</li>

 </ul>

 ")

(defxdoc alistp
  :parents (alists acl2-built-ins)
  :short "Recognizer for association lists"
  :long "<p>@('(alistp x)') is true if and only if @('x') is a list of @(tsee
 cons) pairs.</p>

 <p>@('(alistp x)') has a @(see guard) of @('t').</p>

 @(def alistp)")

(defxdoc alists
  :parents (programming)
  :short "Operations on association lists, which bind keys to values.")

(defxdoc allocate-fixnum-range
  :parents (numbers acl2-built-ins)
  :short "Set aside fixnums in GCL"
  :long "<p>@('(Allocate-fixnum-range fixnum-lo fixnum-hi)') causes Gnu Common
 Lisp
 (GCL) to create a persistent table for the integers between @('fixnum-lo') and
 @('fixnum-hi') (both bounds inclusive). This table is referenced first when
 any integer is boxed and the existing box in the table is used if the integer
 is in bounds.  This can speed up GCL considerably by avoiding wasteful fixnum
 boxing.  Here, @('fixnum-lo') and @('fixnum-hi') should be fixnums.  On 32-bit
 machines it would be good for them to be of type @('(signed-byte 30)'), with
 @('fixnum-lo <= fixnum-hi').</p>

 <p>When this function is executed in a Lisp implementation other than GCL, it
 has no side effect.  This function always returns @('nil').</p>")

(defxdoc alpha-char-p
  :parents (characters acl2-built-ins)
  :short "Recognizer for alphabetic characters"
  :long "<p>@('(Alpha-char-p x)') is true for a standard character @('x') if
 and only if @('x') is alphabetic, i.e., one of the @(see characters)
 @('#\\a'), @('#\\b'), ..., @('#\\z'), @('#\\A'), @('#\\B'), ...,
 @('#\\Z').</p>

 <p>The @(see guard) for @('alpha-char-p') requires its argument to be a
 standard character (see @(see standard-char-p)).</p>

 <p>@('Alpha-char-p') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def alpha-char-p)")

(defxdoc alphorder
  :parents (<< acl2-built-ins)
  :short "Total order on atoms"
  :long "<p>@('Alphorder') is a non-strict total order, a ``less than or
 equal,'' on atoms.  By ``non-strict total order'' we mean a function that
 always returns @('t') or @('nil') and satisfies the following properties.</p>

 <ul>

 <li>Antisymmetry: @('XrY & YrX -> X=Y')</li>

 <li>Transitivity: @('XrY & YrZ -> XrZ')</li>

 <li>Trichotomy: @('XrY v YrX')</li>

 </ul>

 <p>Also see @(see lexorder), which extends @('alphorder') to all objects.</p>

 <p>@('(Alphorder x y)') has a guard of @('(and (atom x) (atom y))').</p>

 <p>Within a single type: rationals are compared arithmetically, complex
 rationals are compared lexicographically, characters are compared via their
 char-codes, and strings and symbols are compared with alphabetic ordering.
 Across types, rationals come before complexes, complexes come before
 characters, characters before strings, and strings before symbols.  We also
 allow for ``bad atoms,'' i.e., atoms that are not legal Lisp objects but make
 sense in the ACL2 logic; these come at the end, after symbols.</p>

 @(def alphorder)")

(defxdoc alternative-introduction
  :parents (acl2-tutorial)
  :short "Introduction to ACL2"
  :long "<p>This section contains introductory material on ACL2 including what
 ACL2 is, how to get started using the system, how to read the output, and
 other introductory topics.  It was written almost entirely by Bill Young of
 Computational Logic, Inc.</p>

 <p>You might also find CLI Technical Report 101 helpful, especially if you are
 familiar with Nqthm.  If you would like more familiarity with Nqthm, we
 suggest CLI Technical Report 100.</p>

 <p><i>OVERVIEW</i></p>

 <p>ACL2 is an automated reasoning system developed (for the first 9 years) at
 Computational Logic, Inc. and (from January, 1997) at the University of Texas
 at Austin.  It is the successor to the Nqthm (or Boyer-Moore) logic and proof
 system and its Pc-Nqthm interactive enhancement.  The acronym ACL2 actually
 stands for ``A Computational Logic for Applicative Common Lisp''.  This title
 suggests several distinct but related aspects of ACL2.</p>

 <p>We assume that readers of the ACL2 @(see documentation) have at least a
 very slight familiarity with some Lisp-like language.  We will address the
 issue of prerequisites further, in ``ABOUT THIS TUTORIAL'' below.</p>

 <p>As a <b>logic</b>, ACL2 is a formal system with rigorously defined syntax
 and semantics.  In mathematical parlance, the ACL2 logic is a first-order
 logic of total recursive functions providing mathematical induction on the
 ordinals up to epsilon-0 and two extension principles: one for recursive
 definition and one for constrained introduction of new function symbols, here
 called encapsulation.  The syntax of ACL2 is that of Common Lisp; ACL2
 specifications are ``also'' Common Lisp programs in a way that we will make
 clear later.  In less formal language, the ACL2 logic is an integrated
 collection of rules for defining (or axiomatizing) recursive functions,
 stating properties of those functions, and rigorously establishing those
 properties.  Each of these activities is mechanically supported.</p>

 <p>As a <b>specification language</b>, ACL2 supports modeling of systems of
 various kinds.  An ACL2 function can equally be used to express purely formal
 relationships among mathematical entities, to describe algorithms, or to
 capture the intended behavior of digital systems.  For digital systems, an
 ACL2 specification is a mathematical <b>model</b> that is intended to
 formalize relevant aspects of system behavior.  Just as physics allows us to
 model the behavior of continuous physical systems, ACL2 allows us to model
 digital systems, including many with physical realizations such as computer
 hardware.  As early as the 1930's Church, Kleene, Turing and others
 established that recursive functions provide an expressive formalism for
 modeling digital computation.  Digital computation should be understood in a
 broad sense, covering a wide variety of activities including almost any
 systematic or algorithmic activity, or activity that can be reasonably
 approximated in that way.  This ranges from the behavior of a digital circuit
 to the behavior of a programming language compiler to the behavior of a
 controller for a physical system (as long as the system can be adequately
 modeled discretely).  All of these have been modeled using ACL2 or its
 predecessor Nqthm.</p>

 <p>ACL2 is a <b>computational</b> logic in at least three distinct senses.
 First, the theory of recursive functions is often considered the mathematics
 of computation.  Church conjectured that any ``effective computation'' can be
 modeled as a recursive function.  Thus, ACL2 provides an expressive language
 for modeling digital systems.  Second, many ACL2 specifications are
 executable.  In fact, recursive functions written in ACL2 <b>are</b> Common
 Lisp functions that can be submitted to any compliant Common Lisp compiler and
 executed (in an environment where suitable ACL2-specific macros and functions
 are defined).  Third, ACL2 is computational in the sense that calculation is
 heavily integrated into the reasoning process.  Thus, an expression with
 explicit constant values but no free variables can be simplified by
 calculation rather than by complex logical manipulations.</p>

 <p>ACL2 is a powerful, automated <b>theorem prover</b> or proof checker.  This
 means that a competent user can utilize the ACL2 system to discover proofs of
 theorems stated in the ACL2 logic or to check previously discovered proofs.
 The basic deductive steps in an ACL2-checked proof are often quite large, due
 to the sophisticated combination of decision procedures, conditional
 rewriting, mathematical and structural induction, propositional
 simplification, and complex heuristics to orchestrate the interactions of
 these capabilities.  Unlike some automated proof systems, ACL2 does not
 produce a formal proof.  However, we believe that if ACL2 certifies the
 ``theoremhood'' of a given conjecture, then such a formal proof exists and,
 therefore, the theorem is valid.  The ultimate result of an ACL2 proof session
 is a collection of ``@(see events),'' possibly grouped into ``@(see books),''
 that can be replayed in ACL2.  Therefore, a proof can be independently
 validated by any ACL2 user.</p>

 <p>ACL2 may be used in purely automated mode in the shallow sense that
 conjectures are submitted to the prover and the user does not interact with
 the proof attempt (except possibly to stop it) until the proof succeeds or
 fails.  However, any non-trivial proof attempt is actually interactive, since
 successful proof ``@(see events)'' influence the subsequent behavior of the
 prover.  For example, proving a lemma may introduce a rule that subsequently
 is used automatically by the prover.  Thus, any realistic proof attempt, even
 in ``automatic'' mode, is really an interactive dialogue with the prover to
 craft a sequence of @(see events) building an appropriate theory and proof
 rules leading up to the proof of the desired result.  Also, ACL2 supports
 annotating a theorem with ``@(see hints)'' designed to guide the proof
 attempt.  By supplying appropriate @(see hints), the user can suggest proof
 strategies that the prover would not discover automatically.  There is a
 ``@(see proof-tree)'' facility (see @(see proof-tree)) that allows the user to
 @(see monitor) the progress and structure of a proof attempt in real-time.
 Exploring failed proof attempts is actually where heavy-duty ACL2 users spend
 most of their time.</p>

 <p>ACL2 can also be used in a more explicitly interactive mode.  The
 interactive @(see proof-builder) subsystem of ACL2 allows exploration of a
 proof on a fairly low level including expanding calls of selected function
 symbols, invoking specific @(see rewrite) rules, and selectively navigating
 around the proof.  This facility can be used to gain sufficient insight into
 the proof to construct an automatic version, or to generate a detailed
 interactive-style proof that can be replayed in batch mode.</p>

 <p>Because ACL2 is all of these things &mdash; computational logic,
 specification language, @(see programming) system, and theorem prover &mdash;
 it is more than the sum of its parts.  The careful integration of these
 diverse aspects has produced a versatile automated reasoning system suitable
 for building highly reliable digital systems.  In the remainder of this
 tutorial, we will illustrate some simple uses of this automated reasoning
 system.</p>

 <p><i>ABOUT THIS TUTORIAL</i></p>

 <p>ACL2 is a complex system with a vast array of features, bells and whistles.
 However, it is possible to perform productive work with the system using only
 a small portion of the available functionality.  The goals of this tutorial
 are to:</p>

 <blockquote>

 <p>familiarize the new user with the most basic features of and modes of
 interaction with ACL2;</p>

 <p>familiarize her with the form of output of the system; and</p>

 <p>work through a graduated series of examples.</p></blockquote>

 <p>The more knowledge the user brings to this system, the easier it will be to
 become proficient.  On one extreme: the <b>ideal</b> user of ACL2 is an expert
 Common Lisp programmer, has deep understanding of automated reasoning, and is
 intimately familiar with the earlier Nqthm system.  Such ideal users are
 unlikely to need this tutorial.  However, without some background knowledge,
 the beginning user is likely to become extremely confused and frustrated by
 this system.  We suggest that a new user of ACL2 should:</p>

 <blockquote>

 <p>(a) have a little familiarity with Lisp, including basic Lisp programming
 and prefix notation (a Lisp reference manual such as Guy Steele's ``Common
 Lisp: The Language'' is also helpful);</p>

 <p>(b) be convinced of the utility of formal modeling; and</p>

 <p>(c) be willing to gain familiarity with basic automated theorem proving
 topics such as rewriting and algebraic simplification.</p></blockquote>

 <p>We will not assume any deep familiarity with Nqthm (the so-called
 ``Boyer-Moore Theorem Prover''), though the book ``A Computational Logic
 Handbook'' by Boyer and Moore (Academic Press, 1988) is an extremely useful
 reference for many of the topics required to become a competent ACL2 user.
 We'll refer to it as ACLH below.</p>

 <p>As we said in the introduction, ACL2 has various facets.  For example, it
 can be used as a Common Lisp @(see programming) system to construct
 application programs.  In fact, the ACL2 system itself is a large Common Lisp
 program constructed almost entirely within ACL2.  Another use of ACL2 is as a
 specification and modeling tool.  That is the aspect we will concentrate on in
 the remainder of this tutorial.</p>

 <p><i>GETTING STARTED</i></p>

 <p>This section is an abridged version of what's available elsewhere; feel
 free to see @(see startup) for more details.</p>

 <p>How you start ACL2 will be system dependent, but you'll probably type
 something like ``acl2'' at your operating system prompt.  Consult your system
 administrator for details.</p>

 <p>When you start up ACL2, you'll probably find yourself inside the ACL2 @(see
 command) loop, as indicated by the following @(see prompt).</p>

 @({
    ACL2 !>
 })

 <p>If not, you should type @('(LP)').  See @(see lp), which has a lot more
 information about the ACL2 @(see command) loop.</p>

 <p>There are two ``modes'' for using ACL2, @(':')@(tsee logic) and
 @(':')@(tsee program).  When you begin ACL2, you will ordinarily be in the
 @(':')@(tsee logic) mode.  This means that any new function defined is not
 only executable but also is axiomatically defined in the ACL2 logic.  (See
 @(see defun-mode) and see @(see default-defun-mode).)  Roughly speaking,
 @(':')@(tsee program) mode is available for using ACL2 as a @(see programming)
 language without some of the logical burdens necessary for formal reasoning.
 In this tutorial we will assume that we always remain in @(':')@(tsee logic)
 mode and that our purpose is to write formal models of digital systems and to
 reason about them.</p>

 <p>Now, within the ACL2 @(see command) loop you can carry out various kinds of
 activities, including the following.  (We'll see examples later of many of
 these.)</p>

 <blockquote>

 <p>define new functions (see @(see defun));</p>

 <p>execute functions on concrete data;</p>

 <p>pose and attempt to prove conjectures about previously defined functions
 (see @(see defthm));</p>

 <p>query the ACL2 ``@(see world)'' or database (e.g., see @(see pe)); and</p>

 <p>numerous other things.</p></blockquote>

 <p>In addition, there is extensive on-line @(see documentation), of which this
 tutorial introduction is a part.</p>

 <p><i>INTERACTING WITH ACL2</i></p>

 <p>The standard means of interacting with ACL2 is to submit a sequence of
 forms for processing by the ACL2 system.  These forms are checked for
 syntactic and semantic acceptability and appropriately processed by the
 system.  These forms can be typed directly at the ACL2 @(see prompt).
 However, most successful ACL2 users prefer to do their work using the Emacs
 text editor, maintaining an Emacs ``working'' buffer in which forms are
 edited.  Those forms are then copied to the ACL2 interaction buffer, which is
 often the @('\"*shell*\"') buffer.</p>

 <p>In some cases, processing succeeds and makes some change to the ACL2
 ``logical @(see world),'' which affects the processing of subsequent forms.
 How can this processing fail?  For example, a proposed theorem will be
 rejected unless all function symbols mentioned have been previously defined.
 Also the ability of ACL2 to discover the proof of a theorem may depend on the
 user previously having proved other theorems.  Thus, the order in which forms
 are submitted to ACL2 is quite important.  Maintaining forms in an appropriate
 order in your working buffer will be helpful for re-playing the proof
 later.</p>

 <p>One of the most common @(see events) in constructing a model is introducing
 new functions.  New functions are usually introduced using the @(tsee defun)
 form; we'll encounter some exceptions later.  Proposed function definitions
 are checked to make sure that they are syntactically and semantically
 acceptable (e.g., that all mentioned functions have been previously defined)
 and, for recursive functions, that their recursive calls <b>terminate</b>.  A
 recursive function definition is guaranteed to terminate if there is some some
 ``measure'' of the arguments and a ``well-founded'' ordering such that the
 arguments to the function get smaller in each recursive call.  See @(see
 well-founded-relation-rule).</p>

 <p>For example, suppose that we need a function that will append two lists
 together.  (We already have one in the ACL2 @(tsee append) function; but
 suppose perversely that we decide to define our own.)  Suppose we submit the
 following definition (you should do so as well and study the system
 output):</p>

 @({
    (defun my-app (x y)
      (if (atom x)
          y
        (cons (car x) (my-app x y))))
 })

 <p>The system responds with the following message:</p>

 @({
    ACL2 Error in ( DEFUN MY-APP ...):  No :MEASURE was supplied with
    the definition of MY-APP.  Our heuristics for guessing one have not
    made any suggestions.  No argument of the function is tested along
    every branch and occurs as a proper subterm at the same argument
    position in every recursive call.  You must specify a :MEASURE.  See
    :DOC defun.
 })

 <p>This means that the system could not find an expression involving the
 formal parameters @('x') and @('y') that decreases under some well-founded
 order in every recursive call (there is only one such call).  It should be
 clear that there is no such measure in this case because the only recursive
 call doesn't change the arguments at all.  The definition is obviously flawed;
 if it were accepted and executed it would loop forever.  Notice that a
 definition that is rejected is not stored in the system database; there is no
 need to take any action to have it ``thrown away.''  Let's try again with the
 correct definition.  The interaction now looks like (we're also putting in the
 ACL2 @(see prompt); you don't type that):</p>

 @({
    ACL2 !>(defun my-app (x y)
             (if (atom x)
                 y
               (cons (car x) (my-app (cdr x) y))))

    The admission of MY-APP 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 MY-APP is described by the theorem
    (OR (CONSP (MY-APP X Y)) (EQUAL (MY-APP X Y) Y)).
    We used primitive type reasoning.

    Summary
    Form:  ( DEFUN MY-APP ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
    Warnings:  None
    Time:  0.07 seconds (prove: 0.00, print: 0.00, other: 0.07)
    MY-APP
 })

 <p>Notice that this time the function definition was accepted.  We didn't have
 to supply a measure explicitly; the system inferred one from the form of the
 definition.  On complex functions it may be necessary to supply a measure
 explicitly.  (See @(see xargs).)</p>

 <p>The system output provides several pieces of information.</p>

 <blockquote>

 <p>The revised definition is acceptable.  The system realized that there is a
 particular measure (namely, @('(acl2-count x)')) and a well-founded relation
 (@('o<')) under which the arguments of @('my-app') get smaller in recursion.
 Actually, the theorem prover proved several theorems to admit @('my-app').
 The main one was that when @('(atom x)') is false the @('acl2-count') of
 @('(cdr x)') is less than (in the @('o<') sense) the @('acl2-count') of
 @('x').  @(tsee Acl2-count) is the most commonly used measure of the ``size``
 of an ACL2 object.  @(tsee o<) is the ordering relation on ordinals less than
 epsilon-0.  On the natural numbers it is just ordinary ``&lt;''.</p>

 <p>The observation printed about ``the type of MY-APP'' means that calls of
 the function @('my-app') will always return a value that is either a @(see
 cons) pair or is equal to the second parameter.</p>

 <p>The summary provides information about which previously introduced
 definitions and lemmas were used in this proof, about some notable things to
 watch out for (the Warnings), and about how long this event took to
 process.</p></blockquote>

 <p>Usually, it's not important to read this information.  However, it is a
 good habit to scan it briefly to see if the type information is surprising to
 you or if there are Warnings.  We'll see an example of them later.</p>

 <p>After a function is accepted, it is stored in the database and available
 for use in other function definitions or lemmas.  To see the definition of any
 function use the @(':')@(tsee pe) command (see @(see pe)).  For example,</p>

 @({
    ACL2 !>:pe my-app
     L       73:x(DEFUN MY-APP (X Y)
                        (IF (ATOM X)
                            Y (CONS (CAR X) (MY-APP (CDR X) Y))))
 })

 <p>This displays the definition along with some other relevant information.
 In this case, we know that this definition was processed in @(':')@(tsee
 logic) mode (the ``@('L')'') and was the 73rd @(see command) processed in the
 current session.</p>

 <p>We can also try out our newly defined function on some sample data.  To do
 that, just submit a form to be evaluated to ACL2.  For example,</p>

 @({
    ACL2 !>(my-app '(0 1 2) '(3 4 5))
    (0 1 2 3 4 5)
    ACL2 !>(my-app nil nil)
    NIL
    ACL2 !>
 })

 <p>Now suppose we want to prove something about the function just introduced.
 We conjecture, for example, that the length of the @(see append) of two lists
 is the sum of their lengths.  We can formulate this conjecture in the form of
 the following ACL2 @(tsee defthm) form.</p>

 @({
    (defthm my-app-length
      (equal (len (my-app x y))
             (+ (len x) (len y))))
 })

 <p>First of all, how did we know about the functions @('len') and @(tsee +),
 etc.?  The answer to that is somewhat unsatisfying &mdash; we know them from
 our past experience in using Common Lisp and ACL2.  It's hard to know that a
 function such as @('len') exists without first knowing some Common Lisp.  If
 we'd guessed that the appropriate function was called @(tsee length) (say,
 from our knowledge of Lisp) and tried @(':pe length'), we would have seen that
 @(tsee length) is defined in terms of @('len'), and we could have explored
 from there.  Luckily, you can write a lot of ACL2 functions without knowing
 too many of the primitive functions.</p>

 <p>Secondly, why don't we need some ``type'' hypotheses?  Does it make sense
 to append things that are not lists?  Well, yes.  ACL2 and Lisp are both quite
 weakly typed.  For example, inspection of the definition of @('my-app') shows
 that if @('x') is not a @(see cons) pair, then @('(my-app x y)') always
 returns @('y'), no matter what @('y') is.</p>

 <p>Thirdly, would it matter if we rewrote the lemma with the equality
 reversed, as follows?</p>

 @({
    (defthm my-app-length2
      (equal (+ (len x) (len y))
             (len (my-app x y)))).
 })

 <p>The two are <b>logically</b> equivalent, but...yes, it would make a big
 difference.  Recall our remark that a lemma is not only a ``fact'' to be
 proved; it also is used by the system to prove other later lemmas.  The
 current lemma would be stored as a @(see rewrite) rule.  (See @(see
 rule-classes).)  For a @(see rewrite) rule, a conclusion of the form @('(EQUAL
 LHS RHS)') means to replace instances of the @('LHS') by the appropriate
 instance of the @('RHS').  Presumably, it's better to @(see rewrite) @('(len
 (my-app x y))') to @('(+ (len x) (len y))') than the other way around.  The
 reason is that the system ``knows'' more about @(tsee +) than it does about
 the new function symbol @('my-app').</p>

 <p>So let's see if we can prove this lemma.  Submitting our preferred @(tsee
 defthm) to ACL2 (do it!), we get the following interaction:</p>

 @({
            --------------------------------------------------
  ACL2 !>(defthm my-app-length
    (equal (len (my-app x y))
           (+ (len x) (len y))))

  Name the formula above *1.

  Perhaps we can prove *1 by induction.  Three induction schemes are
  suggested by this conjecture.  These merge into two derived
  induction schemes.  However, one of these is flawed and so we are
  left with one viable candidate.

  We will induct according to a scheme suggested by (LEN X), but
  modified to accommodate (MY-APP X Y).  If we let (:P X Y) denote *1
  above then the induction scheme we'll use is
  (AND (IMPLIES (NOT (CONSP X)) (:P X Y))
       (IMPLIES (AND (CONSP X) (:P (CDR X) Y))
                (:P X Y))).
  This induction is justified by the same argument used to admit LEN,
  namely, the measure (ACL2-COUNT X) is decreasing according to the
  relation O< (which is known to be well-founded on the domain
  recognized by O-P).  When applied to the goal at hand the
  above induction scheme produces the following two nontautological
  subgoals.

  Subgoal *1/2
  (IMPLIES (NOT (CONSP X))
           (EQUAL (LEN (MY-APP X Y))
                  (+ (LEN X) (LEN Y)))).

  But simplification reduces this to T, using the :definitions of FIX,
  LEN and MY-APP, the :type-prescription rule LEN, the :rewrite rule
  UNICITY-OF-0 and primitive type reasoning.

  Subgoal *1/1
  (IMPLIES (AND (CONSP X)
                (EQUAL (LEN (MY-APP (CDR X) Y))
                       (+ (LEN (CDR X)) (LEN Y))))
           (EQUAL (LEN (MY-APP X Y))
                  (+ (LEN X) (LEN Y)))).

  This simplifies, using the :definitions of LEN and MY-APP, primitive
  type reasoning and the :rewrite rules COMMUTATIVITY-OF-+ and
  CDR-CONS, to

  Subgoal *1/1'
  (IMPLIES (AND (CONSP X)
                (EQUAL (LEN (MY-APP (CDR X) Y))
                       (+ (LEN Y) (LEN (CDR X)))))
           (EQUAL (+ 1 (LEN (MY-APP (CDR X) Y)))
                  (+ (LEN Y) 1 (LEN (CDR X))))).

  But simplification reduces this to T, using linear arithmetic,
  primitive type reasoning and the :type-prescription rule LEN.

  That completes the proof of *1.

  Q.E.D.

  Summary
  Form:  ( DEFTHM MY-APP-LENGTH ...)
  Rules: ((:REWRITE UNICITY-OF-0)
          (:DEFINITION FIX)
          (:REWRITE COMMUTATIVITY-OF-+)
          (:DEFINITION LEN)
          (:REWRITE CDR-CONS)
          (:DEFINITION MY-APP)
          (:TYPE-PRESCRIPTION LEN)
          (:FAKE-RUNE-FOR-TYPE-SET NIL)
          (:FAKE-RUNE-FOR-LINEAR NIL))
  Warnings:  None
  Time:  0.30 seconds (prove: 0.13, print: 0.05, other: 0.12)
   MY-APP-LENGTH
            --------------------------------------------------
 })

 <p>Wow, it worked!  In brief, the system first tried to @(see rewrite) and
 simplify as much as possible.  Nothing changed; we know that because it said
 ``Name the formula above *1.''  Whenever the system decides to name a formula
 in this way, we know that it has run out of techniques to use other than proof
 by induction.</p>

 <p>The induction performed by ACL2 is structural or ``Noetherian'' induction.
 You don't need to know much about that except that it is induction based on
 the structure of some object.  The heuristics infer the structure of the
 object from the way the object is recursively decomposed by the functions used
 in the conjecture.  The heuristics of ACL2 are reasonably good at selecting an
 induction scheme in simple cases.  It is possible to override the heuristic
 choice by providing an @(':induction') hint (see @(see hints)).  In the case
 of the theorem above, the system inducts on the structure of @('x') as
 suggested by the decomposition of @('x') in both @('(my-app x y)') and @('(len
 x)').  In the base case, we assume that @('x') is not a @(tsee consp).  In the
 inductive case, we assume that it is a @(tsee consp) and assume that the
 conjecture holds for @('(cdr x)').</p>

 <p>There is a close connection between the analysis that goes on when a
 function like @('my-app') is accepted and when we try to prove something
 inductively about it.  That connection is spelled out well in Boyer and
 Moore's book ``A Computational Logic,'' if you'd like to look it up.  But it's
 pretty intuitive.  We accepted @('my-app') because the ``size'' of the first
 argument @('x') decreases in the recursive call.  That tells us that when we
 need to prove something inductively about @('my-app'), it's a good idea to try
 an induction on the size of the first argument.  Of course, when you have a
 theorem involving several functions, it may be necessary to concoct a more
 complicated @(see induction) schema, taking several of them into account.
 That's what's meant by ``merging'' the induction schemas.</p>

 <p>The proof involves two cases: the base case, and the inductive case.
 You'll notice that the subgoal numbers go <b>down</b> rather than up, so you
 always know how many subgoals are left to process.  The base case (@('Subgoal
 *1/2')) is handled by opening up the function definitions, simplifying, doing
 a little rewriting, and performing some reasoning based on the types of the
 arguments.  You'll often encounter references to system defined lemmas (like
 @('unicity-of-0')).  You can always look at those with @(':')@(tsee pe); but,
 in general, assume that there's a lot of simplification power under the hood
 that's not too important to understand fully.</p>

 <p>The inductive case (@('Subgoal *1/1')) is also dispatched pretty easily.
 Here we assume the conjecture true for the @(tsee cdr) of the list and try to
 prove it for the entire list.  Notice that the prover does some simplification
 and then prints out an updated version of the goal (@('Subgoal *1/1'')).
 Examining these gives you a pretty good idea of what's going on in the
 proof.</p>

 <p>Sometimes one goal is split into a number of subgoals, as happened with the
 induction above.  Sometimes after some initial processing the prover decides
 it needs to prove a subgoal by induction; this subgoal is given a name and
 pushed onto a stack of goals.  Some steps, like generalization (see ACLH), are
 not necessarily validity preserving; that is, the system may adopt a false
 subgoal while trying to prove a true one.  (Note that this is ok in the sense
 that it is not ``unsound.''  The system will fail in its attempt to establish
 the false subgoal and the main proof attempt will fail.)  As you gain facility
 with using the prover, you'll get pretty good at recognizing what to look for
 when reading a proof script.  The prover's @(see proof-tree) utility helps
 with monitoring an ongoing proof and jumping to designated locations in the
 proof (see @(see proof-tree)).  See @(see tips) for a number of useful
 pointers on using the theorem prover effectively.</p>

 <p>When the prover has successfully proved all subgoals, the proof is
 finished.  As with a @(tsee defun), a summary of the proof is printed.  This
 was an extremely simple proof, needing no additional guidance.  More realistic
 examples typically require the user to look carefully at the failed proof log
 to find ways to influence the prover to do better on its next attempt.  This
 means either: proving some rules that will then be available to the prover,
 changing the global state in ways that will affect the proof, or providing
 some @(see hints) locally that will influence the prover's behavior.  Proving
 this lemma (@('my-app-length')) is an example of the first.  Since this is a
 @(see rewrite) rule, whenever in a later proof an instance of the form @('(LEN
 (MY-APP X Y))') is encountered, it will be rewritten to the corresponding
 instance of @('(+ (LEN X) (LEN Y))').  Disabling the rule by executing the
 @(see command)</p>

 @({
    (in-theory (disable my-app-length)),
 })

 <p>is an example of a global change to the behavior of the prover since this
 @(see rewrite) will not be performed subsequently (unless the rule is again
 @(see enable)d).  Finally, we can add a (local) @(see disable) ``hint'' to a
 @(tsee defthm), meaning to @(see disable) the lemma only in the proof of one
 or more subgoals.  For example:</p>

 @({
    (defthm my-app-length-commutativity
      (equal (len (my-app x y))
             (len (my-app y x)))
      :hints ((\"Goal\" :in-theory (disable my-app-length))))
 })

 <p>In this case, the hint supplied is a bad idea since the proof is much
 harder with the hint than without it.  Try it both ways.</p>

 <p>By the way, to undo the previous event use @(':u') (see @(see u)).  To undo
 back to some earlier event use @(':ubt') (see @(see ubt)).  To view the
 current event use @(':pe :here').  To list several @(see events) use @(':pbt')
 (see @(see pbt)).</p>

 <p>Notice the form of the hint in the previous example (see @(see hints)).  It
 specifies a goal to which the hint applies.  @('\"Goal\"') refers to the
 top-level goal of the theorem.  Subgoals are given unique names as they are
 generated.  It may be useful to suggest that a function symbol be @(see
 disable)d only for Subgoal 1.3.9, say, and a different function @(see enable)d
 only on Subgoal 5.2.8.  Overuse of such @(see hints) often suggests a poor
 global proof strategy.</p>

 <p>We now recommend that you visit @(see documentation) on additional
 examples.  See @(see annotated-acl2-scripts).</p>")

(defxdoc and
  :parents (basics acl2-built-ins)
  :short "Conjunction"
  :long "<p>@('And') is the macro for conjunctions.  @('And') takes any number
 of arguments.  @('And') returns @('nil') if one of the arguments is @('nil'),
 but otherwise returns the last argument.  If there are no arguments, @('and')
 returns @('t').</p>

 <p>@('And') is a Common Lisp macro.  See any Common Lisp documentation for
 more information.</p>

 @(def and)
 @(def and-macro)")

(defxdoc annotated-acl2-scripts
  :parents (acl2-tutorial)
  :short "Examples of ACL2 scripts"
  :long "<p>Beginning users may find these annotated scripts useful.  We
 suggest that you read these in the following order:</p>

 <code>
 @(see Tutorial1-Towers-of-Hanoi)
 @(see Tutorial2-Eights-Problem)
 @(see Tutorial3-Phonebook-Example)
 @(see Tutorial4-Defun-Sk-Example)
 @(see Tutorial5-Miscellaneous-Examples)
 </code>

 <p>You can also find useful demos in the @(see community-books) directory,
 @('books/demos/'), and its subdirectories.</p>

 <p>The web page <a
 href='http://www.cs.utexas.edu/users/moore/publications/tutorial/rev3.html'>Brief
 ACL2 Tutorial</a> contains a script that illustrates how it feels to use The
 Method to prove an unusual list reverse function correct.  The screen shots of
 ACL2's proof output are outdated &mdash; in the version shown, ACL2 does not
 print Key Checkpoints, but the concept of key checkpoint is clear in the
 discussion and the behavior of the user.</p>

 <p>See <a
 href='http://www.cs.utexas.edu/users/moore/acl2/contrib/POLISHING-PROOFS-TUTORIAL.html'>Polishing
 Proofs Tutorial</a> for a tutorial on becoming successful at approaching a
 formalization and proof problem in ACL2.  That tutorial, written by Shilpi
 Goel and Sandip Ray, has two parts: it illustrates how to guide the theorem
 prover to a successful proof, and it shows how to clean up the proof in order
 to facilitate maintenance and extension of the resulting book (see @(see
 books)).</p>

 <p>The <a
 href='http://www.cs.utexas.edu/users/moore/publications/tutorial/kaufmann-TPHOLs08/index.html'>ACL2
 Demo Given at TPHOLs 2008</a> by Matt Kaufmann includes scripts and a gzipped
 tar file containing the entire contents of the demos.</p>

 <p>The <a
 href='http://www.cs.utexas.edu/users/moore/publications/tutorial/sort-equivalence'>sort
 equivalence demo</a> is a collection of scripts illustrating both high-level
 strategy and lower-level tactics dealing with the functional equivalence of
 various list sorting algorithms.  Start with the @('README') on that
 directory.  There is also a <a
 href='http://www.cs.utexas.edu/users/moore/publications/tutorial/sort-equivalence.tgz'>gzipped
 tar file</a> with all of these scripts.</p>

 <p>When you feel you have read enough examples, you might want to try the
 following very simple example on your own. (See @(see
 solution-to-simple-example) for a solution, after you work on this example.)
 First define the notion of the ``fringe'' of a tree, where we identify trees
 simply as @(see cons) structures, with @(see atom)s at the leaves.  For
 example:</p>

 @({
    ACL2 !>(fringe '((a . b) c . d))
    (A B C D)
 })

 <p>Next, define the notion of a ``leaf'' of a tree, i.e., a predicate
 @('leaf-p') that is true of an atom if and only if that atom appears at the
 tip of the tree.  Define this notion without referencing the function
 @('fringe').  Finally, prove the following theorem, whose proof may well be
 automatic (i.e., not require any lemmas).</p>

 @({
    (defthm leaf-p-iff-member-fringe
      (iff (leaf-p atm x)
           (member-equal atm (fringe x))))
 })")

(defxdoc append
  :parents (lists acl2-built-ins)
  :short "@(see concatenate) zero or more lists"
  :long "<p>@('Append'), which takes zero or more arguments, expects all the
 arguments except perhaps the last to be true (null-terminated) lists.  It
 returns the result of concatenating all the elements of all the given lists
 into a single list.  Actually, in ACL2 @('append') is a macro that expands
 into calls of the binary function @(tsee binary-append) if there are at least
 two arguments; if there is just one argument then the expansion is that
 argument; and finally, @('(append)') expands to @('nil').</p>

 <p>@('Append') is a Common Lisp function.  See any Common Lisp documentation
 for more information.  See @(see append-without-guard) for a version of
 @('append') that has a guard of @('t').</p>

 @(def append)
 @(def binary-append)")

(defxdoc apply$
  :parents (acl2-built-ins)
  :short "Apply a function to arguments"
  :long "<p>This documentation topic is currently little more than a stub, but
 with pointers to helpful information about @('apply$') and related functions
 @('ev$') and @('ev$-list').  Here is a little edited log, produced immediately
 after starting ACL2, that shows @('apply$') at work.</p>

 @({
 ACL2 !>(defun$ foo (x y) (+ x y))
 [[.. elided output ..]]
  :WARRANTED
 ACL2 !>(apply$ 'foo (list 3 (- 10 2)))
 11
 ACL2 !>(thm (implies (warrant foo)
                      (equal (apply$ 'foo (list x y))
                             (foo x y))))
 [[.. elided output ..]]
 Proof succeeded.
 ACL2 !>
 })

 <p>The paper <a
 href='http://www.cs.utexas.edu/users/kaufmann/papers/apply/index.html'>``Limited
 Second-Order Functionality in a First-Order Setting''</a> by Matt Kaufmann and
 J Strother Moore is the definitive reference on @('apply$').  That paper
 serves not only as a manual, but it also provides logical foundations, which
 are illustrated in @(see community-books) directory
 @('books/projects/apply-model/').</p>

 <p>A quick way to start using @('apply$') is to start with</p>

 @({
 (include-book \"projects/apply/apply-lemmas\" :dir :system)
 })

 <p>to load useful lemmas for reasoning about @('apply$').</p>

 <p>Then run some examples in the community book,
 @('books/projects/apply/report.lisp'), to learn how to do proofs about
 apply$.</p>")

(defxdoc architecture-of-the-prover
  :parents (introduction-to-the-theorem-prover)
  :short "A simple overview of how the prover works"
  :long "<p>Six built-in proof techniques are used by ACL2 to decompose the
 goal formula into subgoals.</p>

 <ul>

 <li><i>simplification</i> &mdash; decision procedures and rewriting with
 previously proved rules, but actually including a host of other techniques
 under your control.  Simplification is the only proof technique that can
 reduce a formula to 0 subgoals (i.e., prove it) rather than just transform it
 to other formulas.  The predominant activity in most proofs is simplification.
 There are many ways you can affect what the simplifier does to your formulas.
 Good users spend most of their time thinking about how to control the
 simplifier.</li>

 <li><i>destructor elimination</i> &mdash; getting rid of ``destructor terms''
 like @('(CAR X)') and @('(CDR X)') by replacing a variable, e.g., @('X'), by a
 ``constructor'' term, e.g., @('(CONS A B)').  But you can tell ACL2 about new
 destructor/constructor combinations.</li>

 <li><i>fertilization</i> &mdash; using an equivalence hypothesis by
  substituting one side for the other in the goal.  When under induction, ACL2
  may decide to restrict the substitution as follows, using its so-called
  <i>cross-fertilization</i> heuristic: substitute only into one side of the
  conclusion, thus using an inductive hypothesis in preparation for possible
  generalization in advance of another induction.  Note that
  cross-fertilization is used only when generalization is enabled: with the
  hint @(':do-not '(generalize)'), only full fertilization is applied.</li>

 <li><i>generalization</i> &mdash; replacing a term by a new variable and
 restricting the new variable to have some of the properties of the term.  You
 can control the restrictions imposed on the new variable.  This is a heuristic
 that prepares the goal for another induction.</li>

 <li><i>elimination of irrelevance</i> &mdash; throwing away unnecessary
 hypotheses.  This is a heuristic that prepares the goal for another
 induction.</li>

 <li><i>induction</i> &mdash; selecting an induction scheme to prove a formula.
 Inductions are ``suggested'' by the recursive functions appearing in the
 formula.  But you can control what inductions are suggested by terms.</li>

 </ul>

 <p>But you can add additional techniques, called <i>clause processors</i>.</p>

 <p>The various techniques are tried in turn, with simplification first and
 induction last.  Each technique reports one of three outcomes: it found
 nothing to change (i.e., the technique doesn't <i>apply</i> to that subgoal),
 it decided to abort the proof attempt (typically because there is reason to
 believe the proof is failing), or it decomposed the goal into <i>k</i>
 subgoals.</p>

 <p>The last outcome has a special case: if <i>k</i> is 0 then the technique
 proved the goal.  Whenever <i>k</i> is non-0, the process starts over again
 with simplification on each of the <i>k</i> subgoals.  However, it saves up
 all the subgoals for which induction is the only proof technique left to
 try. That way you see how it performs on every base case and induction step of
 one induction before it launches into another induction.</p>

 <p>It runs until you or one of the proof techniques aborts the proof attempt
 or until all subgoals have been proved.</p>

 <p>Note that if simplification produces a subgoal, that subgoal is
 re-simplified.  This process continues until the subgoal cannot be simplified
 further.  Only then is the next proof technique is tried.  Such subgoals are
 said to be <i>stable under simplification</i>.</p>

 <p>While this is happening, the prover prints an English narrative describing
 the process.  Basically, after each goal is printed, the system prints an
 English paragraph that names the next applicable proof technique, gives a
 brief description of what that technique does to the subgoal, and says how
 many new subgoals are produced.  Then each subgoal is dealt with in turn.</p>

 <p>If the proof is successful, you could read this log as a proof of the
 conjecture.  But output from successful proofs is generally never read because
 it is not important to The Method described in @(see
 introduction-to-the-theorem-prover).</p>

 <p>The output of an unsuccessful proof attempt concludes with some <i>key</i>
 <i>checkpoints</i> which usually bear looking at.</p>

 <p>For more information about how ACL2 orchestrates its proof techniques, see
 @(see hints-and-the-waterfall).</p>")

(defxdoc aref1
  :parents (arrays acl2-built-ins)
  :short "Access the elements of a 1-dimensional array"
  :long "@({
  Example Form:
  (aref1 'delta1 a (+ i k))

  General Form:
  (aref1 name alist index)
 })

 <p>where @('name') is a symbol, @('alist') is a 1-dimensional array and
 @('index') is a legal index into @('alist').  This function returns the value
 associated with @('index') in @('alist'), or else the default value of the
 array.  See @(see arrays) for details.</p>

 <p>This function executes in virtually constant time if @('alist') is in fact
 the ``semantic value'' associated with @('name') (see @(see arrays)).  When it
 is not, @('aref1') must do a linear search through @('alist').  In that case
 the correct answer is returned but a <b>slow array</b> comment is printed to
 the comment window.  See @(see slow-array-warning).</p>

 @(def aref1)")

(defxdoc aref2
  :parents (arrays acl2-built-ins)
  :short "Access the elements of a 2-dimensional array"
  :long "@({
  Example Form:
  (aref2 'delta1 a i j)

  General Form:
  (aref2 name alist i j)
 })

 <p>where @('name') is a symbol, @('alist') is a 2-dimensional array and @('i')
 and @('j') are legal indices into @('alist').  This function returns the value
 associated with @('(i . j)') in @('alist'), or else the default value of the
 array.  See @(see arrays) for details.</p>

 <p>This function executes in virtually constant time if @('alist') is in fact
 the ``semantic value'' associated with @('name') (see @(see arrays)).  When it
 is not, @('aref2') must do a linear search through @('alist').  In that case
 the correct answer is returned but a <b>slow array</b> comment is printed to
 the comment window.  See @(see slow-array-warning).</p>

 @(def aref2)")

(defxdoc args
  :parents (documentation)
  :short "@('args'), @(tsee guard), @('type'), @(tsee constraint), etc., of a
  function symbol"
  :long "@({
  Example:
  :args assoc-eq
 })

 <p>@('Args') takes one argument, a symbol which must be the name of a function
 or macro, and prints out the formal parameters, the @(see guard) expression,
 the output @(see signature), the deduced type, the @(see constraint) (if any),
 and whether @(see documentation) about the symbol is available via
 @(':')@(tsee doc).</p>")

(defxdoc arities-okp
  :parents (acl2-built-ins)
  :short "check the arities of given function symbols"
  :long "@({
  Example:
  (arities-okp '((IF . 3) (CAR . 1) (CONS . 2)) (w state))

  General Form:
  (arities-okp alist w)
 })

 <p>where @('alist') is a @(tsee symbol-alistp) and @('w') is an ACL2 logical
 @(see world).  The alist is presumed to pair @(':')@(tsee logic)-mode function
 symbols with arities.  The result is @('t') or @('nil') according to whether
 each symbol in the alist is a @(':logic')-mode function symbol with the
 associated arity as its @(tsee arity) in @('w').  See @(see
 well-formedness-guarantee).</p>

 @(def arities-okp)")

(defxdoc arity
  :parents (acl2-built-ins)
  :short "number of arguments of a function symbol"
  :long "@({
  Examples:
  (arity 'IF (w state))
  (arity '(LAMBDA (X) (CONS X X)) (w state))

  General Form:
  (arity fn w)
 })

 <p>where @('fn') is a function symbol or a lambda expression and @('w') is an
 ACL2 logical @(see world).  The result is the number of arguments the function
 or lambda expression takes, or @('nil') if the function symbol is not defined
 in @('w').</p>

 See @(see arity+) for a variant of @('arity') with a stronger @(see guard).")

(defxdoc array1p
  :parents (arrays acl2-built-ins)
  :short "Recognize a 1-dimensional array"
  :long "@({
  Example Form:
  (array1p 'delta1 a)

  General Form:
  (array1p name alist)
 })

 <p>where @('name') and @('alist') are arbitrary objects.  This function
 returns @('t') if @('alist') is a 1-dimensional ACL2 array.  Otherwise it
 returns @('nil').  The function operates in constant time if @('alist') is the
 semantic value of @('name').  See @(see arrays).</p>

 @(def array1p)")

(defxdoc array2p
  :parents (arrays acl2-built-ins)
  :short "Recognize a 2-dimensional array"
  :long "@({
  Example Form:
  (array2p 'delta1 a)

  General Form:
  (array2p name alist)
 })

 <p>where @('name') and @('alist') are arbitrary objects.  This function
 returns @('t') if @('alist') is a 2-dimensional ACL2 array.  Otherwise it
 returns @('nil').  The function operates in constant time if @('alist') is the
 semantic value of @('name').  See @(see arrays).</p>

 @(def array2p)")

(defxdoc arrays
  :parents (programming)
  :short "ACL2 arrays and operations on them"
  :long "<p>Below we begin a detailed presentation of ACL2 arrays.  ACL2's
 single-threaded objects (see @(see stobj)) provide a similar functionality
 that is generally more efficient when there are updates (writes), but is also
 more restrictive.</p>

 <p>See @(see arrays-example) for a brief introduction illustrating the use of
 ACL2 arrays.</p>

 <p>ACL2 provides relatively efficient 1- and 2-dimensional arrays.  Arrays are
 awkward to provide efficiently in an applicative language because the
 programmer rightly expects to be able to ``modify'' an array object with the
 effect of changing the behavior of the element accessing function on that
 object.  This, of course, does not make any sense in an applicative setting.
 The element accessing function is, after all, a function, and its behavior on
 a given object is immutable.  To ``modify'' an array object in an applicative
 setting we must actually produce a new array object.  Arranging for this to be
 done efficiently is a challenge to the implementors of the language.  In
 addition, the programmer accustomed to the von Neumann view of arrays must
 learn how to use immutable applicative arrays efficiently.</p>

 <p>In this note we explain 1-dimensional arrays.  In particular, we explain
 briefly how to create, access, and ``modify'' them, how they are implemented,
 and how to program with them.  2-dimensional arrays are dealt with by
 analogy.</p>

 <p><i>The Logical Description of ACL2 Arrays</i></p>

 <p>An ACL2 1-dimensional array is an object that associates arbitrary objects
 with certain integers, called ``indices.'' Every array has a dimension,
 @('dim'), which is a positive integer.  The indices of an array are the
 consecutive integers from @('0') through @('dim-1').  To obtain the object
 associated with the index @('i') in an array @('a'), one uses @('(aref1 name a
 i)').  @('Name') is a symbol that is irrelevant to the semantics of @(tsee
 aref1) but affects the speed with which it computes.  We will talk more about
 array ``names'' later.  To produce a new array object that is like @('a') but
 which associates @('val') with index @('i'), one uses @('(aset1 name a i
 val)').</p>

 <p>An ACL2 1-dimensional array is actually an alist.  There is no special ACL2
 function for creating arrays; they are generally built with the standard list
 processing functions @(tsee list) and @(tsee cons).  However, there is a
 special ACL2 function, called @(tsee compress1), for speeding up access to the
 elements of such an alist.  We discuss @(tsee compress1) later.</p>

 <p>One element of the alist must be the ``header'' of the array.  The @(see
 header) of a 1-dimensional array with dimension @('dim') is of the form:</p>

 @({
  (:HEADER :DIMENSIONS (dim)
           :MAXIMUM-LENGTH max
           :DEFAULT obj ; optional
           :NAME name   ; optional
           :ORDER order ; optional values are < (the default), >, or :none/nil
           ).
 })

 <p>@('Obj') may be any object and is called the ``default value'' of the
 array.  @(tsee Max) must be an integer greater than @('dim').  @('Name') must
 be a symbol.  The @(':')@(tsee default) and @(':name') entries are optional;
 if @(':')@(tsee default) is omitted, the default value is @('nil').  The
 function @(tsee header), when given a name and a 1- or 2-dimensional array,
 returns the @(see header) of the array.  The functions @(tsee dimensions),
 @(tsee maximum-length), and @(tsee default) are similar and return the
 corresponding fields of the @(see header) of the array.  The role of the
 @(':')@(tsee dimensions) field is obvious: it specifies the legal indices into
 the array.  The roles played by the @(':')@(tsee maximum-length) and
 @(':')@(tsee default) fields are described below.</p>

 <p>Aside from the @(see header), the other elements of the alist must each be
 of the form @('(i . val)'), where @('i') is an integer and @('0 <= i < dim'),
 and @('val') is an arbitrary object.</p>

 <p>The @(':order') field of the header is ignored for 2-dimensional arrays.
 For 1-dimensional arrays, it specifies the order of keys (@('i'), above) when
 the array is compressed as with @(tsee compress1), as described below.  An
 @(':order') of @(':none') or @('nil') specifies no reordering of the alist by
 @(tsee compress1), and an order of @('>') specifies reordering by @(tsee
 compress1) so that keys are in descending order.  Otherwise, the alist is
 reordered by @(tsee compress1) so that keys are in ascending order.</p>

 <p>@('(Aref1 name a i)') is @(see guard)ed so that @('name') must be a symbol,
 @('a') must be an array and @('i') must be an index into @('a').  The value of
 @('(aref1 name a i)') is either @('(cdr (assoc i a))') or else is the default
 value of @('a'), depending on whether there is a pair in @('a') whose @(tsee
 car) is @('i').  Note that @('name') is irrelevant to the value of an @(tsee
 aref1) expression.  You might @(':pe aref1') to see how simple the definition
 is.</p>

 <p>@('(Aset1 name a i val)') is @(see guard)ed analogously to the @(tsee
 aref1) expression.  The value of the @(tsee aset1) expression is essentially
 @('(cons (cons i val) a)').  Again, @('name') is irrelevant.  Note @('(aset1
 name a i val)') is an array, @('a''), with the property that @('(aref1 name a'
 i)') is @('val') and, except for index @('i'), all other indices into @('a'')
 produce the same value as in @('a').  Note also that if @('a') is viewed as an
 alist (which it is) the pair ``binding'' @('i') to its old value is in @('a'')
 but ``covered up'' by the new pair.  Thus, the length of an array grows by one
 when @(tsee aset1) is done.</p>

 <p>Because @(tsee aset1) covers old values with new ones, an array produced by
 a sequence of @(tsee aset1) calls may have many irrelevant pairs in it.  The
 function @(tsee compress1) can remove these irrelevant pairs.  Thus,
 @('(compress1 name a)') returns an array that is equivalent (vis-a-vis @(tsee
 aref1)) to @('a') but which may be shorter.  For technical reasons, the alist
 returned by @(tsee compress1) may also list the pairs in a different order
 than listed in @('a').</p>

 <p>To prevent arrays from growing excessively long due to repeated @(tsee
 aset1) operations, @(tsee aset1) actually calls @(tsee compress1) on the new
 alist whenever the length of the new alist exceeds the @(':')@(tsee
 maximum-length) entry, @(tsee max), in the @(see header) of the array.  See
 the definition of @(tsee aset1) (for example by using @(':')@(tsee pe)).  This
 is primarily just a mechanism for freeing up @(tsee cons) space consumed while
 doing @(tsee aset1) operations.  Note however that this @(tsee compress1) call
 is replaced by a hard error if the header specifies an @(':order') of
 @(':none') or @('nil').</p>

 <p>This completes the logical description of 1-dimensional arrays.
 2-dimensional arrays are analogous.  The @(':')@(tsee dimensions) entry of the
 @(see header) of a 2-dimensional array should be @('(dim1 dim2)').  A pair of
 indices, @('i') and @('j'), is legal iff @('0 <= i < dim1') and @('0 <= j <
 dim2').  The @(':')@(tsee maximum-length) must be greater than @('dim1*dim2').
 @(tsee Aref2), @(tsee aset2), and @(tsee compress2) are like their
 counterparts but take an additional @('index') argument.  Finally, the pairs
 in a 2-dimensional array are of the form @('((i . j) . val)').</p>

 <p><i>The Implementation of ACL2 Arrays</i></p>

 <p>Very informally speaking, the function @(tsee compress1) ``creates'' an
 ACL2 array that provides fast access, while the function @(tsee aref1)
 ``maintains'' fast access.  We now describe this informal idea more
 carefully.</p>

 <p>@(tsee Aref1) is essentially @(tsee assoc).  If @(tsee aref1) were
 implemented naively the time taken to access an array element would be linear
 in the dimension of the array and the number of ``assignments'' to it (the
 number of @(tsee aset1) calls done to create the array from the initial
 alist).  This is intolerable; arrays are ``supposed'' to provide constant-time
 access and change.</p>

 <p>The apparently irrelevant names associated with ACL2 arrays allow us to
 provide constant-time access and change when arrays are used in
 ``conventional'' ways.  The implementation of arrays makes it clear what we
 mean by ``conventional.''</p>

 <p>Recall that array names are symbols.  Behind the scenes, ACL2 associates
 two objects with each ACL2 array name.  The first object is called the
 ``semantic value'' of the name and is an alist.  The second object is called
 the ``raw lisp array'' and is a Common Lisp array.</p>

 <p>When @('(compress1 name alist)') builds a new alist, @('a''), it sets the
 semantic value of @('name') to that new alist.  Furthermore, it creates a
 Common Lisp array and writes into it all of the index/value pairs of @('a''),
 initializing unassigned indices with the default value.  This array becomes
 the raw lisp array of @('name').  @(tsee Compress1) then returns @('a''), the
 semantic value, as its result, as required by the definition of @(tsee
 compress1).</p>

 <p>When @('(aref1 name a i)') is invoked, @(tsee aref1) first determines
 whether the semantic value of @('name') is @('a') (i.e., is @(tsee eq) to the
 alist @('a')).  If so, @(tsee aref1) can determine the @('i')th element of
 @('a') by invoking Common Lisp's @('aref') function on the raw lisp array
 associated with name.  Note that no linear search of the alist @('a') is
 required; the operation is done in constant time and involves retrieval of two
 global variables, an @(tsee eq) test and @('jump'), and a raw lisp array
 access.  In fact, an ACL2 array access of this sort is about 5 times slower
 than a C array access.  On the other hand, if @('name') has no semantic value
 or if it is different from @('a'), then @(tsee aref1) determines the answer by
 linear search of @('a') as suggested by the @('assoc-like') definition of
 @(tsee aref1).  Thus, @(tsee aref1) always returns the axiomatically specified
 result.  It returns in constant time if the array being accessed is the
 current semantic value of the name used.  The ramifications of this are
 discussed after we deal with @(tsee aset1).</p>

 <p>When @('(aset1 name a i val)') is invoked, @(tsee aset1) does two @(tsee
 cons)es to create the new array.  Call that array @('a'').  It will be
 returned as the answer.  (In this discussion we ignore the case in which
 @(tsee aset1) does a @(tsee compress1).)  However, before returning, @(tsee
 aset1) determines if @('name')'s semantic value is @('a').  If so, it makes
 the new semantic value of @('name') be @('a'') and it smashes the raw lisp
 array of @('name') with @('val') at index @('i'), before returning @('a'') as
 the result.  Thus, after doing an @(tsee aset1) and obtaining a new semantic
 value @('a''), all @(tsee aref1)s on that new array will be fast.  Any @(tsee
 aref1)s on the old semantic value, @('a'), will be slow.</p>

 <p>To understand the performance implications of this design, consider the
 chronological sequence in which ACL2 (Common Lisp) evaluates expressions:
 basically inner-most first, left-to-right, call-by-value.  An array use, such
 as @('(aref1 name a i)'), is ``fast'' (constant-time) if the alist supplied,
 @('a'), is the value returned by the most recently executed @(tsee compress1)
 or @(tsee aset1) on the name supplied.  In the functional expression of
 ``conventional'' array processing, all uses of an array are fast.</p>

 <p>The @(':name') field of the @(see header) of an array is completely
 irrelevant.  Our convention is to store in that field the symbol we mean to
 use as the name of the raw lisp array.  But no ACL2 function inspects
 @(':name') and its primary value is that it allows the user, by inspecting the
 semantic value of the array &mdash; the alist &mdash; to recall the name of
 the raw array that probably holds that value.  We say ``probably'' since there
 is no enforcement that the alist was compressed under the name in the @(see
 header) or that all @('aset')s used that name.  Such enforcement would be
 inefficient.</p>

 <p><i>Some Programming Examples</i></p>

 <p>In the following examples we will use ACL2 ``global variables'' to hold
 several arrays.  See @(see @), and see @(see assign).</p>

 <p>Let the @(tsee state) global variable @('a') be the 1-dimensional
 compressed array of dimension @('5') constructed below.</p>

 @({
  ACL2 !>(assign a (compress1 'demo
                              '((:header :dimensions (5)
                                         :maximum-length 15
                                         :default uninitialized
                                         :name demo)
                                (0 . zero))))
 })

 <p>Then @('(aref1 'demo (@ a) 0)') is @('zero') and @('(aref1 'demo (@ a) 1)')
 is @('uninitialized').</p>

 <p>Now execute</p>

 @({
  ACL2 !>(assign b (aset1 'demo (@ a) 1 'one))
 })

 <p>Then @('(aref1 'demo (@ b) 0)') is @('zero') and @('(aref1 'demo (@ b) 1)')
 is @('one').</p>

 <p>All of the @(tsee aref1)s done so far have been ``fast.''</p>

 <p>Note that we now have two array objects, one in the global variable @('a')
 and one in the global variable @('b').  @('B') was obtained by assigning to
 @('a').  That assignment does not affect the alist @('a') because this is an
 applicative language.  Thus, @('(aref1 'demo (@ a) 1)') must <b>still</b> be
 @('uninitialized').  And if you execute that expression in ACL2 you will see
 that indeed it is.  However, a rather ugly comment is printed, namely that
 this array access is ``slow.''  The reason it is slow is that the raw lisp
 array associated with the name @('demo') is the array we are calling @('b').
 To access the elements of @('a'), @(tsee aref1) must now do a linear search.
 Any reference to @('a') as an array is now ``unconventional;'' in a
 conventional language like Ada or Common Lisp it would simply be impossible to
 refer to the value of the array before the assignment that produced our
 @('b').</p>

 <p>Now let us define a function that counts how many times a given object,
 @('x'), occurs in an array.  For simplicity, we will pass in the name and
 highest index of the array:</p>

 @({
  ACL2 !>(defun cnt (name a i x)
           (declare (xargs :guard
                           (and (array1p name a)
                                (integerp i)
                                (>= i -1)
                                (< i (car (dimensions name a))))
                           :mode :logic
                           :measure (nfix (+ 1 i))))
           (cond ((zp (1+ i)) 0) ; return 0 if i is at most -1
                 ((equal x (aref1 name a i))
                  (1+ (cnt name a (1- i) x)))
                 (t (cnt name a (1- i) x))))
 })

 <p>To determine how many times @('zero') appears in @('(@ b)') we can
 execute:</p>

 @({
  ACL2 !>(cnt 'demo (@ b) 4 'zero)
 })

 <p>The answer is @('1').  How many times does @('uninitialized') appear in
 @('(@ b)')?</p>

 @({
  ACL2 !>(cnt 'demo (@ b) 4 'uninitialized)
 })

 <p>The answer is @('3'), because positions @('2'), @('3') and @('4') of the
 array contain that default value.</p>

 <p>Now imagine that we want to assign @(''two') to index @('2') and then count
 how many times the 2nd element of the array occurs in the array.  This
 specification is actually ambiguous.  In assigning to @('b') we produce a new
 array, which we might call @('c').  Do we mean to count the occurrences in
 @('c') of the 2nd element of @('b') or the 2nd element of @('c')?  That is, do
 we count the occurrences of @('uninitialized') or the occurrences of @('two')?
 If we mean the former the correct answer is @('2') (positions @('3') and
 @('4') are @('uninitialized') in @('c')); if we mean the latter, the correct
 answer is @('1') (there is only one occurrence of @('two') in @('c')).</p>

 <p>Below are ACL2 renderings of the two meanings, which we call @('[former]')
 and @('[latter]').  (Warning: Our description of these examples, and of an
 example @('[fast former]') that follows, assumes that only one of these three
 examples is actually executed; for example, they are not executed in sequence.
 See ``A Word of Warning'' below for more about this issue.)</p>

 @({
  (cnt 'demo (aset1 'demo (@ b) 2 'two) 4 (aref1 'demo (@ b) 2))  ; [former]

  (let ((c (aset1 'demo (@ b) 2 'two)))                           ; [latter]
    (cnt 'demo c 4 (aref1 'demo c 2)))
 })

 <p>Note that in @('[former]') we create @('c') in the second argument of the
 call to @('cnt') (although we do not give it a name) and then refer to @('b')
 in the fourth argument.  This is unconventional because the second reference
 to @('b') in @('[former]') is no longer the semantic value of @('demo').
 While ACL2 computes the correct answer, namely @('2'), the execution of the
 @(tsee aref1) expression in @('[former]') is done slowly.</p>

 <p>A conventional rendering with the same meaning is</p>

 @({
  (let ((x (aref1 'demo (@ b) 2)))                           ; [fast former]
    (cnt 'demo (aset1 'demo (@ b) 2 'two) 4 x))
 })

 <p>which fetches the 2nd element of @('b') before creating @('c') by
 assignment.  It is important to understand that @('[former]') and @('[fast
 former]') mean exactly the same thing: both count the number of occurrences of
 @('uninitialized') in @('c').  Both are legal ACL2 and both compute the same
 answer, @('2').  Indeed, we can symbolically transform @('[fast former]') into
 @('[former]') merely by substituting the binding of @('x') for @('x') in the
 body of the @(tsee let).  But @('[fast former]') can be evaluated faster than
 @('[former]') because all of the references to @('demo') use the then-current
 semantic value of @('demo'), which is @('b') in the first line and @('c')
 throughout the execution of the @('cnt') in the second line.  @('[Fast
 former]') is the preferred form, both because of its execution speed and its
 clarity.  If you were writing in a conventional language you would have to
 write something like @('[fast former]') because there is no way to refer to
 the 2nd element of the old value of @('b') after smashing @('b') unless it had
 been saved first.</p>

 <p>We turn now to @('[latter]').  It is both clear and efficient.  It creates
 @('c') by assignment to @('b') and then it fetches the 2nd element of @('c'),
 @('two'), and proceeds to count the number of occurrences in @('c').  The
 answer is @('1').  @('[Latter]') is a good example of typical ACL2 array
 manipulation: after the assignment to @('b') that creates @('c'), @('c') is
 used throughout.</p>

 <p>It takes a while to get used to this because most of us have grown
 accustomed to the peculiar semantics of arrays in conventional languages.  For
 example, in raw lisp we might have written something like the following,
 treating @('b') as a ``global variable'':</p>

 @({
  (cnt 'demo (aset 'demo b 2 'two) 4 (aref 'demo b 2))
 })

 <p>which sort of resembles @('[former]') but actually has the semantics of
 @('[latter]') because the @('b') from which @('aref') fetches the 2nd element
 is not the same @('b') used in the @('aset')!  The array @('b') is destroyed
 by the @('aset') and @('b') henceforth refers to the array produced by the
 @('aset'), as written more clearly in @('[latter]').</p>

 <p>A Word of Warning: Users must exercise care when experimenting with
 @('[former]'), @('[latter]') and @('[fast former]').  Suppose you have just
 created @('b') with the assignment shown above,</p>

 @({
  ACL2 !>(assign b (aset1 'demo (@ a) 1 'one))
 })

 <p>If you then evaluate @('[former]') in ACL2 it will complain that the @(tsee
 aref1) is slow and compute the answer, as discussed.  Then suppose you
 evaluate @('[latter]') in ACL2.  From our discussion you might expect it to
 execute fast &mdash; i.e., issue no complaint.  But in fact you will find that
 it complains repeatedly.  The problem is that the evaluation of @('[former]')
 changed the semantic value of @('demo') so that it is no longer @('b').  To
 try the experiment correctly you must make @('b') be the semantic value of
 @('demo') again before the next example is evaluated.  One way to do that is
 to execute</p>

 @({
  ACL2 !>(assign b (compress1 'demo (@ b)))
 })

 <p>before each expression.  Because of issues like this it is often hard to
 experiment with ACL2 arrays at the top-level.  We find it easier to write
 functions that use arrays correctly and efficiently than to so use them
 interactively.</p>

 <p>This last assignment also illustrates a very common use of @(tsee
 compress1).  While it was introduced as a means of removing irrelevant pairs
 from an array built up by repeated assignments, it is actually most useful as
 a way of insuring fast access to the elements of an array.</p>

 <p>Many array processing tasks can be divided into two parts.  During the
 first part the array is built.  During the second part the array is used
 extensively but not modified.  If your @(see programming) task can be so
 divided, it might be appropriate to construct the array entirely with list
 processing, thereby saving the cost of maintaining the semantic value of the
 name while few references are being made.  Once the alist has stabilized, it
 might be worthwhile to treat it as an array by calling @(tsee compress1),
 thereby gaining constant time access to it.</p>

 <p>ACL2's theorem prover uses this technique in connection with its
 implementation of the notion of whether a @(see rune) is @(see disable)d or
 not.  Associated with every @(see rune) is a unique integer @('index'), called
 its ``nume.''  When each rule is stored, the corresponding nume is stored as a
 component of the rule.  @(see Theories) are lists of @(see rune)s and
 membership in the ``current theory'' indicates that the corresponding rule is
 @(see enable)d.  But these lists are very long and membership is a linear-time
 operation.  So just before a proof begins we map the list of @(see rune)s in
 the current theory into an alist that pairs the corresponding numes with
 @('t').  Then we compress this alist into an array.  Thus, given a rule we can
 obtain its nume (because it is a component) and then determine in constant
 time whether it is @(see enable)d.  The array is never modified during the
 proof, i.e., @(tsee aset1) is never used in this example.  From the logical
 perspective this code looks quite odd: we have replaced a linear-time
 membership test with an apparently linear-time @(tsee assoc) after going to
 the trouble of mapping from a list of @(see rune)s to an alist of numes.  But
 because the alist of numes is an array, the ``apparently linear-time @(tsee
 assoc)'' is more apparent than real; the operation is constant-time.</p>")

(defxdoc arrays-example

; The transcript below was generated essentially after executing the following
; two forms:
; (set-fmt-soft-right-margin 55 state)
; (set-fmt-hard-right-margin 68 state)

  :parents (arrays)
  :short "An example illustrating ACL2 arrays"
  :long "<p>The example below illustrates the use of ACL2 arrays.  It is not,
 of course, a substitute for the detailed explanations provided elsewhere (see
 @(see arrays), including subtopics).</p>

 @({
  ACL2 !>(defun defarray (name size initial-element)
           (compress1 name
                      (cons (list :HEADER
                                  :DIMENSIONS (list size)
                                  :MAXIMUM-LENGTH (1+ size)
                                  :DEFAULT initial-element
                                  :NAME name)
                            nil)))

  Since DEFARRAY is non-recursive, its admission is trivial.  We observe
  that the type of DEFARRAY is described by the theorem
  (AND (CONSP (DEFARRAY NAME SIZE INITIAL-ELEMENT))
       (TRUE-LISTP (DEFARRAY NAME SIZE INITIAL-ELEMENT))).
  We used the :type-prescription rule COMPRESS1.

  Summary
  Form:  ( DEFUN DEFARRAY ...)
  Rules: ((:TYPE-PRESCRIPTION COMPRESS1))
  Warnings:  None
  Time:  0.02 seconds (prove: 0.00, print: 0.02, other: 0.00)
   DEFARRAY
  ACL2 !>(assign my-ar (defarray 'a1 5 17))
   ((:HEADER :DIMENSIONS (5)
             :MAXIMUM-LENGTH 6 :DEFAULT 17 :NAME A1))
  ACL2 !>(aref1 'a1 (@ my-ar) 3)
  17
  ACL2 !>(aref1 'a1 (@ my-ar) 8)

  ACL2 Error in TOP-LEVEL:  The guard for the function symbol AREF1,
  which is
  (AND (ARRAY1P NAME L) (INTEGERP N) (>= N 0) (< N (CAR (DIMENSIONS NAME L)))),
  is violated by the arguments in the call (AREF1 'A1 '(#) 8).

  ACL2 !>(assign my-ar (aset1 'a1 (@ my-ar) 3 'xxx))
   ((3 . XXX)
    (:HEADER :DIMENSIONS (5)
             :MAXIMUM-LENGTH 6 :DEFAULT 17 :NAME A1))
  ACL2 !>(aref1 'a1 (@ my-ar) 3)
  XXX
  ACL2 !>(aset1 'a1 (@ my-ar) 3 'yyy) ; BAD: (@ my-ar) now points to
                                      ;      an old copy of the array!
  ((3 . YYY)
   (3 . XXX)
   (:HEADER :DIMENSIONS (5)
            :MAXIMUM-LENGTH 6 :DEFAULT 17 :NAME A1))
  ACL2 !>(aref1 'a1 (@ my-ar) 3) ; Because of \"BAD\" above, the array
                                 ; access is done using assoc rather
                                 ; than Lisp aref, hence is slower;
                                 ; but the answer is still correct,
                                 ; reflecting the value in (@ my-ar),
                                 ; which was not changed above.

  **********************************************************
  Slow Array Access!  A call of AREF1 on an array named
  A1 is being executed slowly.  See :DOC slow-array-warning
  **********************************************************

  XXX
  ACL2 !>
 })")

(defxdoc aset1
  :parents (arrays acl2-built-ins)
  :short "Set the elements of a 1-dimensional array"
  :long "@({
  Example Form:
  (aset1 'delta1 a (+ i k) 27)

  General Form:
  (aset1 name alist index val)
 })

 <p>where @('name') is a symbol, @('alist') is a 1-dimensional array named
 @('name'), @('index') is a legal index into @('alist'), and @('val') is an
 arbitrary object.  See @(see arrays) for details.  Roughly speaking this
 function ``modifies'' @('alist') so that the value associated with @('index')
 is @('val').  More precisely, it returns a new array, @('alist''), of the same
 name and dimension as @('alist') that, under @(tsee aref1), is everywhere
 equal to @('alist') except at @('index') where the result is @('val').  That
 is, @('(aref1 name alist' i)') is @('(aref1 name alist i)') for all legal
 indices @('i') except @('index'), where @('(aref1 name alist' i)') is
 @('val').</p>

 <p>In order to ``modify'' @('alist'), @('aset1') @(tsee cons)es a new pair
 onto the front.  If the length of the resulting alist exceeds the @(':')@(tsee
 maximum-length) entry in the array @(see header), @('aset1') compresses the
 array as with @(tsee compress1).</p>

 <p>It is generally expected that the ``semantic value'' of @('name') will be
 @('alist') (see @(see arrays)).  This function operates in virtually constant
 time whether this condition is true or not (unless the @(tsee compress1)
 operation is required).  But the value returned by this function cannot be
 used efficiently by subsequent @('aset1') operations unless @('alist') is the
 semantic value of @('name') when @('aset1') is executed.  Thus, if the
 condition is not true, @('aset1') prints a <b>slow array</b> warning to the
 comment window.  See @(see slow-array-warning).</p>

 @(def aset1)")

(defxdoc aset2
  :parents (arrays acl2-built-ins)
  :short "Set the elements of a 2-dimensional array"
  :long "@({
  Example Form:
  (aset2 'delta1 a i j 27)

  General Form:
  (aset2 name alist i j val)
 })

 <p>where @('name') is a symbol, @('alist') is a 2-dimensional array named
 @('name'), @('i') and @('j') are legal indices into @('alist'), and @('val')
 is an arbitrary object.  See @(see arrays) for details.  Roughly speaking this
 function ``modifies'' @('alist') so that the value associated with @('(i
 . j)') is @('val').  More precisely, it returns a new array, @('alist''), of
 the same name and dimension as @('alist') that, under @(tsee aref2), is
 everywhere equal to @('alist') except at @('(i . j)') where the result is
 @('val').  That is, @('(aref2 name alist' x y)') is @('(aref2 name alist x
 y)') for all legal indices @('x') @('y') except @('i') and @('j') where
 @('(aref2 name alist' i j)') is @('val').</p>

 <p>In order to ``modify'' @('alist'), @('aset2') @(tsee cons)es a new pair
 onto the front.  If the length of the resulting @('alist') exceeds the
 @(':')@(tsee maximum-length) entry in the array @(see header), @('aset2')
 compresses the array as with @(tsee compress2).</p>

 <p>It is generally expected that the ``semantic value'' of @('name') will be
 @('alist') (see @(see arrays)).  This function operates in virtually constant
 time whether this condition is true or not (unless the @(tsee compress2)
 operation is required).  But the value returned by this function cannot be
 used efficiently by subsequent @('aset2') operations unless @('alist') is the
 semantic value of @('name') when @('aset2') is executed.  Thus, if the
 condition is not true, @('aset2') prints a <b>slow array</b> warning to the
 comment window.  See @(see slow-array-warning).</p>

 @(def aset2)")

(defxdoc ash
  :parents (numbers acl2-built-ins)
  :short "Arithmetic shift operation"
  :long "<p>@('(ash i c)') is the result of taking the two's complement
 representation of the integer @('i') and shifting it by @('c') bits: shifting
 left and padding with @('c') @('0') bits if @('c') is positive, shifting right
 and dropping @('(abs c)') bits if @('c') is negative, and simply returning
 @('i') if @('c') is @('0').</p>

 <p>The @(see guard) for @('ash') requires that its arguments are integers.</p>

 <p>@('Ash') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def ash)")

(defxdoc assert$
  :parents (errors acl2-built-ins)
  :short "Cause a hard error if the given test is false"
  :long "@({
  General Form:
  (assert$ test form)
 })

 <p>where @('test') returns a single value and @('form') is arbitrary.
 Semantically, this call of @('assert$') is equivalent to @('form').  However,
 it causes a hard error if the value of @('test') is @('nil').  That hard error
 invokes the function @(tsee illegal), which has a @(see guard) that is equal
 to @('nil'); so if you use @('assert$') in code for which you verify guards,
 then a proof obligation will be that the occurrence of @('test') is never
 @('nil').</p>

 <p>For a related utility, see @(see assert*).  Both @('assert$') and
 @('assert*') create a @(see guard) proof obligation (when used in a definition
 made in @(tsee logic)-mode).  However, @('assert$') checks the assertion at
 runtime, while @('assert*') does not.</p>")

(defxdoc assert*
  :parents (errors acl2-built-ins)
  :short "Create a @(see guard) proof obligation that given test holds"
  :long "@({
  General Form:
  (assert* test form)
 })

 <p>where @('test') returns a single value and @('form') is arbitrary.
 Semantically, this call of @('assert*') is equivalent to @('form').  However,
 a @(see guard) proof obligation is created that @('test') holds, when used in
 a definition made in @(tsee logic)-mode).</p>

 <p>For a related utility, see @(see assert$).  Both @('assert$') and
 @('assert*') create a @(see guard) proof obligation (when used in a definition
 made in @(tsee logic)-mode).  However, @('assert$') checks the assertion at
 runtime, while @('assert*') does not.</p>

 @(def assert*)")

(defxdoc assert-event
  :parents (events errors)
  :short "Assert that a given form returns a non-@('nil') value"
  :long "<p>@('Assert-event') provides a way to check that the value of an
 expression is not @('nil'), causing an error otherwise.  For a similar utility
 see the macro @(tsee assert!) defined in @(see community-books) file
 @('books/misc/assert.lisp').  Here we compare the two, highlighting some key
 differences.</p>

 <ul>

 <li>Both @('assert!') and @('assert-event') evaluate using the current @(see
 guard)-checking status (e.g., see @(see with-guard-checking)).  However,
 @('Assert-event') evaluates using the same ``safe-mode'' that is used during
 macroexpansion, which essentially enforces guard checking for @(see
 primitive)s.  For example, @('(assert! (equal (car 3) nil))') causes an error
 by default but succeeds after @('(set-guard-checking nil)'), but
 @('(assert-event (equal (car 3) nil))') always causes an error.</li>

 <li>@('Assert!') is implemented using @(tsee make-event), so in unusual cases
 it could cause @(see certificate) files to be large.</li>

 <li>@('Assert-event') provides two keyword arguments not directly available in
 @('assert!'): @(':msg'), for custom error messages; and @(':on-skip-proofs'),
 to control whether or not the check is done when skipping proofs, as is the
 case during @(tsee include-book).  Of course, one could modify @('assert!'),
 or wrap its calls inside other code, to do these sorts of things.</li>

 <li>@('Assert!') allows one to specify an event when the check passes.  Of
 course, this could easily be accomplished by combining the use of @(tsee
 progn) and @(tsee assert-event).</li>

 <li>@('Assert-event') is built into ACL2, so it can be used without including
 a book.  On the other hand, since @('assert!') is in a book, the ACL2
 community is welcome to modify it to improve it.</li>

 </ul>

 @({
 Examples:
 (assert-event (equal (+ 3 4) 7))
 (assert-event (equal (+ 3 4) 7) :msg (msg \"Error: ~x0\" 'equal-check))
 (assert-event (equal (+ 3 4) 7) :on-skip-proofs t)

 General Form:
 (assert-event form ; keyword arguments are optional
               :on-skip-proofs t :msg msg)
 })

 <p>@('Assert-event') takes a ground form, i.e., one with no free variables;
 @(tsee stobj)s are allowed but only a single non-@(tsee stobj) value can be
 returned.  The form is then evaluated and if the result is @('nil'), then a
 so-called hard error (see @(see er)) results.  This evaluation is however not
 done if proofs are being skipped, as during @(tsee include-book) (also see
 @(see skip-proofs) and see @(see ld-skip-proofsp)), unless @(':on-skip-proofs
 t') is supplied.</p>

 <p>Normally, if an @('assert-event') call fails then a generic failure message
 is printed, showing the offending form.  However, if keyword argument
 @(':msg') is supplied, then the failure message is printed as with @(tsee fmt)
 argument @('~@0'); see @(see fmt).  In particular, @(':msg') is typically a
 string or a call @('(msg str arg-0 arg-1 ... arg-k)'), where @('str') is a
 string and each @('arg-i') is the value to be associated with @('#\\i') upon
 formatted printing (as with @(tsee fmt)) of the string @('str').</p>

 <p>This form may be put into a book to be certified (see @(see books)),
 because @('assert-event') is a macro whose calls expand to calls of
 @('value-triple') (see @(see embedded-event-form)).  When certifying a book,
 guard-checking is off, as though @('(set-guard-checking nil)') has been
 evaluated; see @(see set-guard-checking).  That, together with a ``safe
 mode,'' guarantees that @('assert-event') forms are evaluated in the logic
 without ill-guarded calls of @(':')@(tsee program)-mode functions while
 certifying a book.</p>")

(defxdoc assign
  :parents (programming-with-state acl2-built-ins)
  :short "Assign to a global variable in @(tsee state)"
  :long "@({
  Examples:
  (assign x (expt 2 10))
  (assign a (aset1 'ascii-map-array (@ a) 66 'Upper-case-B))

  General Form:
  (assign symbol term)
 })

 <p>where @('symbol') is any symbol (with certain enforced exclusions to avoid
 overwriting ACL2 system ``globals'') and @('term') is any ACL2 term that could
 be evaluated at the top-level.  @('Assign') evaluates the term, stores the
 result as the value of the given symbol in the @('global-table') of @(tsee
 state), and returns the result.  (Note: the actual implementation of the
 storage of this value is much more efficient than this discussion of the logic
 might suggest.)  @('Assign') is a macro that effectively expands to the more
 complicated but understandable:</p>

 @({
  (pprogn (f-put-global 'symbol term state)
          (mv nil (f-get-global 'symbol state) state)).
 })

 <p>The macro @('f-put-global') is closely related to @(tsee assign):
 @('(assign var val)') macroexpands to @('(f-put-global 'var val state)').</p>

 <p>The macro @(tsee @) gives convenient access to the value of such globals.
 The @(':')@(tsee ubt) operation has no effect on the @('global-table') of
 @(tsee state).  Thus, you may use these globals to hang onto useful data
 structures even though you may undo back past where you computed and saved
 them.</p>")

(defxdoc assoc
  :parents (alists acl2-built-ins)
  :short "Look up key in association list"
  :long "@({
  General Forms:
  (assoc x alist)
  (assoc x alist :test 'eql)   ; same as above (eql as equality test)
  (assoc x alist :test 'eq)    ; same, but eq is equality test
  (assoc x alist :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Assoc x alist)') is the first member of @('alist') whose @(tsee car) is
 @('x'), or @('nil') if no such member exists.  The optional keyword,
 @(':TEST'), has no effect logically, but provides the test (default @(tsee
 eql)) used for comparing @('x') with the @(tsee car)s of successive elements
 of @('alist').</p>

 <p>The @(see guard) for a call of @('assoc') depends on the test.  In all
 cases, the second argument must satisfy @(tsee alistp).  If the test is @(tsee
 eql), then either the first argument must be suitable for @(tsee eql) (see
 @(see eqlablep)) or the second argument must satisfy @(tsee eqlable-alistp).
 If the test is @(tsee eq), then either the first argument must be a symbol or
 the second argument must satisfy @(tsee symbol-alistp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('assoc') and its variants:</p>

 <blockquote><p>@('(assoc-eq x alist)') is equivalent to @('(assoc x alist
 :test 'eq)');</p>

 <p>@('(assoc-equal x alist)') is equivalent to @('(assoc x alist :test
 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('assoc-equal').</p>

 <p>@('Assoc') is defined by Common Lisp.  See any Common Lisp documentation
 for more information.</p>

 @(def assoc-equal)")

(defxdoc assoc-keyword
  :parents (keyword-value-listp acl2-built-ins)
  :short "Look up key in a @(tsee keyword-value-listp)"
  :long "<p>If @('l') is a list of even length of the form @('(k1 a1 k2 a2
 ... kn an)'), where each @('ki') is a keyword, then @('(assoc-keyword key l)')
 is the first tail of @('l') starting with @('key') if key is some @('ki'), and
 is @('nil') otherwise.</p>

 <p>The @(see guard) for @('(assoc-keyword key l)') is @('(keyword-value-listp
 l)').</p>

 @(def assoc-keyword)")

(defxdoc assoc-string-equal
  :parents (alists acl2-built-ins)
  :short "Look up key, a string, in association list"
  :long "<p>@('(Assoc-string-equal x alist)') is similar to @(tsee
 assoc-equal).  However, for string @('x') and alist @('alist'), the comparison
 of @('x') with successive keys in @('alist') is done using @(tsee
 string-equal) rather than @(tsee equal).</p>

 <p>The @(see guard) for @('assoc-string-equal') requires that @('x') is a
 string and @('alist') is an alist.</p>

 @(def assoc-string-equal)")

(defxdoc atom
  :parents (conses acl2-built-ins)
  :short "Recognizer for atoms"
  :long "<p>@('(atom x)') is true if and only if @('x') is an atom, i.e., not a
 @(tsee cons) pair.</p>

 <p>@('Atom') has a @(see guard) of @('t'), and is a Common Lisp function.  See
 any Common Lisp documentation for more information.</p>

 @(def atom)")

(defxdoc atom-listp
  :parents (atom lists acl2-built-ins)
  :short "Recognizer for a true list of @(see atom)s"
  :long "<p>The predicate @('atom-listp') tests whether its argument is a
 @(tsee true-listp) of @(see atom)s, i.e., of non-conses.</p>

 <p>Also see @(see good-atom-listp).</p>

 @(def atom-listp)")

(defxdoc |About Models|
  :parents (|Pages Written Especially for the Tours|)
  :short "About Models"
  :long "<p><see topic='@(url |Models of Computer Hardware and Software|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>ACL2 is used to construct mathematical models of computer hardware and
 software (i.e., ``digital systems'').</p>

 <p><img src='res/tours/computing-machine.gif'></img></p>

 <p>A <b>mathematical model</b> is a set of mathematical formulas used to
 predict the behavior of some artifact.</p>

 <p>The use of mathematical models allows <b>faster</b> and <b>cheaper</b>
 delivery of <b>better</b> systems.</p>

 <p>Models need not be <b>complete</b> or <b>perfectly accurate</b> to be
 useful to the trained engineer.</p>

 <p>Click <see topic='@(url |Models in Engineering|)'>here</see> for more
 discussion of these assertions in an engineering context.</p>

 <p><see topic='@(url |Models of Computer Hardware and Software|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |About Types|
  :parents (|Pages Written Especially for the Tours|)
  :short "About Types"
  :long "<p>The universe of ACL2 objects includes objects of many different
 types.  For example, @('t') is a ``symbol'' and 3 is an ``integer.''  Roughly
 speaking the objects of ACL2 can be partitioned into the following types:</p>

 <ul>

 <li><see topic='@(url |Numbers in ACL2|)'>Numbers</see> such as @('3, -22/7,
 #c(3 5/2)').</li>

 <li><see topic='@(url |ACL2 Characters|)'>Characters</see> such as @('#\\A,
 #\\a, #\\Space').</li>

 <li><see topic='@(url |ACL2 Strings|)'>Strings</see> such as @('\"This is a
 string.\"').</li>

 <li><see topic='@(url |ACL2 Symbols|)'>Symbols</see> such as @(''abc,
 'smith::abc').</li>

 <li><see topic='@(url |ACL2 Conses or Ordered Pairs|)'>Conses (or
 Ordered Pairs)</see> such as @(''((a . 1) (b . 2))').</li>

 </ul>

 <p>When proving theorems it is important to know the types of object returned
 by a term.  ACL2 uses a complicated heuristic algorithm, called @(tsee
 type-set) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>, to determine what types of objects a term may
 produce.  The user can more or less program the @('type-set') algorithm by
 proving @(tsee type-prescription) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 rules.</p>

 <p>ACL2 is an ``untyped'' logic in the sense that the syntax is not typed: It
 is legal to apply a function symbol of n arguments to any n terms, regardless
 of the types of the argument terms.  Thus, it is permitted to write such odd
 expressions as @('(+ t 3)') which sums the symbol @('t') and the integer 3.
 Common Lisp does not prohibit such expressions.  We like untyped languages
 because they are simple to describe, though proving theorems about them can be
 awkward because, unless one is careful in the way one defines or states
 things, unusual cases (like @('(+ t 3)')) can arise.</p>

 <p>To make theorem proving easier in ACL2, the axioms actually define a value
 for such terms.  The value of @('(+ t 3)') is 3; under the ACL2 axioms,
 non-numeric arguments to @('+') are treated as though they were 0.</p>

 <p>You might immediately wonder about our claim that ACL2 is Common Lisp,
 since @('(+ t 3)') is ``an error'' (and will sometimes even ``signal an
 error'') in Common Lisp.  It is to handle this problem that ACL2 has
 <b>guards</b>.  We will discuss guards later in the Walking Tour.  However,
 many new users simply ignore the issue of guards entirely and that is what we
 recommend for now.</p>

 <p>You should now return to <see topic='@(url
 |Revisiting the Admission of App|)'>the Walking Tour</see>.</p>")

(defxdoc |About the ACL2 Home Page|
  :parents (|Pages Written Especially for the Tours|)
  :short "About the ACL2 Home Page"
  :long "<p><see topic='@(url |What Is ACL2(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>The ACL2 Home Page is integrated into the ACL2 online documentation.  Over
 4 megabytes of hypertext is available here.</p>

 <p>The vast majority of the text is user-level documentation.  For example, to
 find out about @(see rewrite) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 rules you could click on the link.  (If you do that, remember to use your
 browser's <b>Back Button</b> to come back here.)</p>

 <p>The tiny warning signs <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> mark links that lead out of the introductory-level
 material and into the user documentation.  We advise against following such
 links upon your first reading of the documentation.</p>

 <p>At the end of the tours you will have a chance to revisit them quickly to
 explore alternative paths more fully.</p>

 <p>Finally, every page contains two icons at the bottom.  The ACL2 icon leads
 you back to the ACL2 Home Page.  The Index icon allows you to browse an
 alphabetical listing of all the topics in ACL2's online documentation.  But
 both icons take you off the main route of the tour.</p>

 <p><see topic='@(url |What Is ACL2(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |About the Admission of Recursive Definitions|
  :parents (|Pages Written Especially for the Tours|)
  :short "About the Admission of Recursive Definitions"
  :long "<p>You can't just add any formula as an axiom or definition and expect
 the logic to stay sound!  For example, if we were permitted to define @('(APP
 X Y)') so that it was equal to @('(NOT (APP X Y))') then we could prove
 anything.  The purported ``definition'' of @('APP') must have several
 properties to be admitted to the logic as a new axiom.</p>

 <p>The key property a recursive definition must have is that the recursion
 terminate.  This, along with some syntactic criteria, ensures us that there
 exists a function satisfying the definition.</p>

 <p>Termination must be proved before the definition is admitted.  This is done
 in general by finding a measure of the arguments of the function and a
 well-founded relation such that the arguments ``get smaller'' every time a
 recursive branch is taken.</p>

 <p>For @('app') the measure is the ``size'' of the first argument, @('x'), as
 determined by the primitive function @(tsee acl2-count) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>.
 The well-founded relation used in this example is @(tsee o-p) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>,
 which is the standard ordering on the ordinals less than ``epsilon naught.''
 These particular choices for @('app') were made ``automatically'' by ACL2.
 But they are in fact determined by various ``default'' settings.  The user of
 ACL2 can change the defaults or specify a ``hint'' to the @(tsee defun) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 command to specify the measure and relation.</p>

 <p>You should now return to <see topic='@(url
 |Revisiting the Admission of App|)'>the Walking Tour</see>.</p>")

(defxdoc |About the Prompt|
  :parents (|Pages Written Especially for the Tours|)
  :short "About the Prompt"
  :long "<p>The string ``@('ACL2 !>')'' is the ACL2 prompt.</p>

 <p>The prompt tells the user that an ACL2 @(see command) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> is expected.  In addition, the prompt
 tells us a little about the current state of the ACL2 command interpreter.  We
 explain the prompt briefly below.  But first we talk about the command
 interpreter.</p>

 <p>An ACL2 command is generally a Lisp expression to be evaluated.  There are
 some unusual commands (such as :@(see q) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> for
 <b>quitting</b> ACL2) which cause other behavior.  But most commands are read,
 evaluated, and then have their results printed.  Thus, we call the command
 interpreter a ``read-eval-print loop.''  The ACL2 command interpreter is named
 @(tsee LD) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> (after Lisp's ``load'').</p>

 <p>When a command is read, all the symbols in it are converted to uppercase.
 Thus, typing @('(defun app ...)') is the same as typing @('(DEFUN APP ...)')
 or @('(defun App ...)').  There are ways to force lowercase case characters
 into symbols but we won't discuss them here.  A consequence of Common Lisp's
 default uppercasing is that you'll see a general lack of concern over the case
 used when symbols are displayed in this documentation.</p>

 <p>In addition, symbols ``belong'' to ``packages'' which give the user a way
 to control namespaces.  The prompt tells us which package is the default one,
 namely @('\"ACL2\"').  That means when we call @('car'), for example, we are
 invoking the standard definition of that symbol.  If the packager were
 @('\"JONES\"') then @('car') would refer to the definition of that symbol in
 that package (which may or may not be different depending on what symbols were
 imported into that package.</p>

 <p>A command like <b>(defun app (x y) ...)</b> causes ACL2 to evaluate the
 @(see defun) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> function on <b>app</b>, <b>(x y)</b> and
 <b>...</b>.  When that command is evaluated it prints some information to the
 terminal explaining the processing of the proposed definition.  It returns the
 symbol @('APP') as its value, which is printed by the command interpreter.
 (Actually, @('defun') is not a function but a <see topic='@(url
 DEFMACRO)'>macro</see> <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> which expands to a form that involves @(tsee state)
 <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>, a necessary precondition to printing output to the
 terminal and to ``changing'' the set of axioms.  But we do not discuss this
 further here.)</p>

 <p>The @('defun') command is an example of a special kind of command called an
 ``event.''  @(see Events) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> are those commands that change the ``logical
 world'' by adding such things as axioms or theorems to ACL2's database.  See
 @(see world) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.  But not every command is an event command.</p>

 <p>A command like <b>(app '(1 2 3) '(4 5 6 7))</b> is an example of a
 non-event.  It is processed the same general way: the function <b>app</b> is
 applied to the indicated arguments and the result is printed.  The function
 <b>app</b> does not print anything and does not change the ``world.''</p>

 <p>A third kind of command is one that display information about the current
 logical world or that ``roll back'' to previous versions of the world.  Such
 commands are called ``@(see history)'' <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 commands.</p>

 <p>What does the ACL2 prompt tell us about the read-eval-print loop?  The
 prompt ``@('ACL2 !>')'' tells us that the command will be read with @(tsee
 current-package) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> set to @('\"ACL2\"'), that guard checking (see
 @(see set-guard-checking) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>) is on (``@('!')''), and that we are at the
 top-level (there is only one ``@('>')'').  For more about the prompt, see
 @(see default-print-prompt) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p>You should now return to <see topic='@(url
 |Revisiting the Admission of App|)'>the Walking Tour</see>.</p>")

(defxdoc |An Example Common Lisp Function Definition|
  :parents (|Pages Written Especially for the Tours|)
  :short "An Example Common Lisp Function Definition"
  :long "<p><see topic='@(url |An Example of ACL2 in Use|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>Consider the binary trees @('x') and @('y') below.</p>

 <p><img src='res/tours/binary-trees-x-y.gif'></img></p>

 <p>In Lisp, @('x') is written as the list @(''(A B)') or, equivalently, as
 @(''(A B . NIL)').  Similarly, @('y') may be written @(''(C D E)').  Suppose
 we wish to replace the right-most tip of @('x') by the entire tree @('y').
 This is denoted @('(app x y)'), where @('app') stands for ``append''.</p>

 <p><img src='res/tours/binary-trees-app.gif'></img></p>

 <p>We can define @('app') with:</p>

 <code>
 <b>(defun app (x y)</b>                           <i>; Concatenate x and y.</i>
   <b>(declare (type (satisfies true-listp) x))</b><i>; We expect x to end in NIL.</i>
   <b>(cond ((endp x) y)</b>                       <i>; If x is empty, return y.</i>
         <b>(t (cons (car x)</b>                   <i>; Else, copy first node</i>
                  <b>(app (cdr x) y)))))</b>       <i>;  and recur into next.</i>
 </code>

 <p>If you defined this function in some Common Lisp, then to run @('app') on
 the @('x') and @('y') above you could then type</p>

 @({
  (app '(A B) '(C D E))
 })

 <p>and Common Lisp will print the result @('(A B C D E)').</p>

 <p><see topic='@(url |An Example of ACL2 in Use|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |An Example of ACL2 in Use|
  :parents (|Pages Written Especially for the Tours|)
  :short "An Example of ACL2 in Use"
  :long "<p><see topic='@(url |How To Find Out about ACL2 Functions|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>To introduce you to ACL2 we will consider the @('app') function discussed
 in the <see topic='@(url |Common Lisp|)'>Common Lisp</see> page, <b>except</b>
 we will omit for the moment the <b>declare</b> form, which in ACL2 is called a
 <b>guard</b>.</p>

 <p>Guards are arbitrary ACL2 terms that express the ``intended domain'' of
 functions.  In that sense, guards are akin to type signatures.  However,
 Common Lisp and ACL2 are untyped programming languages: while the language
 supports several different data types and the types of objects can be
 determined by predicates at runtime, any type of object may be passed to any
 function.  Thus, guards are ``extra-logical.''  Recognizing both the practical
 and intellectual value of knowing that your functions are applied to the kinds
 of objects you intend, ACL2 imposes guards on Common Lisp and provides a means
 of proving that functions are used as intended.  But the story is necessarily
 complicated and we do not recommend it to the new user.  Get used to the fact
 that any ACL2 function may be applied to any objects and program accordingly.
 Read about guards later.</p>

 <p>Here is the definition again</p>

 <code>
 <b>(defun app (x y)</b>
   <b>(cond ((endp x) y)</b>
         <b>(t (cons (car x) </b>
                  <b>(app (cdr x) y)))))</b>
 </code>

 <p>The next few stops along the Walking Tour will show you</p>

 <code> * how to use the ACL2 documentation, * what happens when the above
 definition is submitted to ACL2, * what happens when you evaluate calls of
 @('app'), * what one simple theorem about @('app') looks like, * how ACL2
 proves the theorem, and * how that theorem can be used in another proof.
 </code>

 <p>Along the way we will talk about the <b>definitional principle</b>,
 <b>types</b>, the ACL2 <b>read-eval-print loop</b>, and how the <b>theorem
 prover</b> works.</p>

 <p>When we complete this part of the tour we will return briefly to the notion
 of <b>guards</b> and revisit several of the topics above in that context.</p>

 <p><see topic='@(url |How To Find Out about ACL2 Functions|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |Analyzing Common Lisp Models|
  :parents (|Pages Written Especially for the Tours|)
  :short "Analyzing Common Lisp Models"
  :long "<p>To analyze a model you must be able to reason about the operations
 and relations involved.  Perhaps, for example, some aspect of the model
 depends upon the fact that the concatenation operation is associative.</p>

 <p>In any Common Lisp you can confirm that</p>

 @({
  (app '(A B) (app '(C D) '(E F)))
 })

 <p>and</p>

 @({
  (app (app '(A B) '(C D)) '(E F)))
 })

 <p>both evaluate to the same thing, @('(A B C D E F)').</p>

 <p>But what distinguishes ACL2 (the logic) from applicative Common Lisp (the
 language) is that in ACL2 you can <b>prove</b> that the concatenation function
 @('app') is associative when its arguments are true-lists, whereas in Common
 Lisp all you can do is test that proposition.</p>

 <p>That is, in ACL2 it makes sense to say that the following formula is a
 ``theorem.''</p>

 <code>
 <b>Theorem</b> Associativity of App
 (implies (and (true-listp a)
               (true-listp b))
          (equal (app (app a b) c)
                 (app a (app b c))))
 </code>

 <p>Theorems about the properties of models are proved by symbolically
 manipulating the operations and relations involved.  If the concatenation of
 sequences is involved in your model, then you may well need the theorem above
 in order to that your model has some particular property.</p>")

(defxdoc backchaining
  :parents (rule-classes)
  :short "Attempting to relieve the hypotheses of a rule"
  :long "<p>When the theorem prover attempts to apply a rule (e.g., a @(see
  rewrite) rule), it must relieve (prove) the hypotheses of that rule.  In the
  ACL2 community, this process of relieving hypotheses is called
  backchaining.</p>

  <p>There is no such thing as a backchaining or backward-chaining rule
  class (see @(see rule-classes)) in ACL2.</p>")

(defxdoc backchain-limit
  :parents (rewrite meta linear type-prescription)
  :short "Limiting the effort expended on relieving hypotheses"
  :long "<p>Before ACL2 can apply a rule with hypotheses, it must establish
 that the hypotheses are true.  (We ignore the relaxing of this requirement
 afforded by @(tsee case-split)s and @(tsee force)d hypotheses.)  ACL2
 typically establishes each hypothesis by backchaining &mdash; instantiating
 the hypothesis and then rewriting it recursively.  Here we describe how ACL2
 allows the user to limit backchaining.  At the end, below, we describe the
 function @(tsee backchain-limit).</p>

 <p>Each hypothesis of a @(tsee rewrite), @(tsee meta), @(tsee linear), or
 @(tsee type-prescription) rule is assigned a backchain-limit when the rule is
 stored.  By default, this limit is @('nil'), denoting infinity (no limit).
 However, the value used for the default may be set to a non-negative integer
 (or to @('nil')) by the user; see @(see set-default-backchain-limit).  The
 default is overridden when a @(':backchain-limit-lst') is supplied explicitly
 with the rule; see @(see rule-classes).  The number of recursive applications
 of backchaining starting with the hypothesis of a rule is limited to the
 backchain-limit associated with that hypothesis.</p>

 <p>Moreover, the user may set global backchain-limits that limit the total
 backchaining depth.  See @(see set-backchain-limit).  One limit is for the use
 of @(tsee rewrite), @(tsee meta), and @(tsee linear) rules, while the other
 limit is for so-called ``@(see type-set) reasoning'', which uses rules of
 class @(tsee type-prescription) rules.  The two limits operate independently.
 Below, we discuss the first kind of backchain limits, i.e., for other than
 @(tsee type-prescription) rules, except as otherwise indicated; but the
 mechanism for those rules is similar.</p>

 <p>Below we lay out the precise sense in which a global backchain-limit
 interacts with the backchain-limits of individual rules in order to limit
 backchaining.  But first we note that when further backchaining is disallowed,
 ACL2 can still prove a hypothesis in a given context by using that contextual
 information.  In fact, @(see type-set) reasoning may be used (except that a
 weaker version of it is used in the second case above, i.e., where we are
 already doing type-set reasoning).  Thus, the relieving of hypotheses may be
 limited to the use of contextual information (without backchaining, i.e.,
 without recursively rewriting hypotheses) by executing @(':set-backchain-limit
 0').</p>

 <p>Recall that there are two sorts of backchain limits: those applied to
 hypotheses of individual rules, as assigned by their @(':')@(tsee
 rule-classes) or else taken from the default (see @(see
 set-default-backchain-limit)); and the global limit, initially @('nil') (no
 limit) but settable with @(':')@(tsee set-backchain-limit).  Here is how these
 two types of limits interact to limit backchaining, i.e., recursive rewriting
 of hypotheses.  ACL2 maintains a current backchain limit, which is the limit
 on the depth of recursive calls to the rewriter, as well as a current
 backchain depth, which is initially 0 and is incremented each time ACL2
 backchains (and is decremented when a backchain completes).  When ACL2 begins
 to rewrite a literal (crudely, one of the ``top-level'' terms of the goal
 currently being worked on), it sets the current backchain-limit to the global
 value, which is initially @('nil') but can be set using @(':')@(tsee
 set-backchain-limit).  When ACL2 is preparing to relieve a hypothesis by
 backchaining (hence, after it has already tried type-set reasoning), it first
 makes sure that the current backchain limit is greater than the current
 backchain depth.  If not, then it refuses to relieve that hypothesis.
 Otherwise, it increments the current backchain depth and calculates a new
 current backchain-limit by taking the minimum of two values: the existing
 current backchain-limit, and the sum of the current backchain depth and the
 backchain-limit associated with the hypothesis.  Thus, ACL2 only modifies the
 current backchain-limit if it is necessary to decrease that limit in order to
 respect the backchain limit associated with the hypothesis.</p>

 <p>We illustrate with the following examples.</p>

 @({
  ; We stub out some functions so that we can reason about them.

  (defstub p0 (x) t)
  (defstub p1 (x) t)
  (defstub p2 (x) t)
  (defstub p3 (x) t)

  ; Initially, the default-backchain-limit is nil, or infinite.

  (defaxiom p2-implies-p1-limitless
    (implies (p2 x)
             (p1 x)))

  ; The following rule will have a backchain-limit of 0.

  (defaxiom p1-implies-p0-limit-0
    (implies (p1 x)
             (p0 x))
    :rule-classes ((:rewrite :backchain-limit-lst 0)))

  ; We have (p2 x) ==> (p1 x) ==> (p0 x).  We wish to establish that
  ; (p2 x) ==> (p0 x).  Normally, this would be no problem, but here
  ; we fail because ACL2 cannot establish (p0 x) by type-set reasoning
  ; alone.

  (thm
    (implies (p2 x)
             (p0 x)))

  ; We set the default-backchain-limit (for rewriting) to 1.

  :set-default-backchain-limit 1

  ; The following is more powerful than p1-implies-p0-limit-0
  ; because it can use rewrite rules to establish (p1 x).

  (defaxiom p1-implies-p0-limit-1
    (implies (p1 x)
             (p0 x)))

  ; This theorem will succeed:

  (thm
    (implies (p2 x)
             (p0 x)))

  ; We return the default-backchain-limit to its initial value.

  :set-default-backchain-limit nil

  ; Here is our last axiom.

  (defaxiom p3-implies-p2-limitless
    (implies (p3 x)
             (p2 x)))

  ; We now have (p3 x) ==> (p2 x) ==> (p1 x) ==> (p0 x).  However the
  ; rule p1-implies-p0-limit-1 has a backchain-limit of 1; hence we
  ; are not allowed to backchain far enough back to use
  ; p3-implies-p2-limitless.  We therefore lose.

  (defthm will-fail
    (implies (p3 x)
             (p0 x)))
 })

 <p>Finally, we remark that to see the current global backchain-limits, issue
 the following commands.</p>

 @({
  (backchain-limit wrld :ts) ; backchain limit for type-set reasoning
  (backchain-limit wrld :rewrite) ; backchain limit for rewriting
 })")

(defxdoc basics
  :parents (programming)
  :short "Basic control structures for @(see programming) like @(see if) and
 @(see cond), binding operators like @(see let) and @(see flet), multiple-value
 constructs like @(see mv), and so forth.")

(defxdoc bdd
  :parents (acl2)
  :short "Ordered binary decision diagrams with rewriting"
  :long "<p>Ordered binary decision diagrams (OBDDs, often simply called BDDs)
 are a technique, originally published by Randy Bryant, for the efficient
 simplification of Boolean expressions.  In ACL2 we combine this technique with
 rewriting to handle arbitrary ACL2 terms that can represent not only Boolean
 values, but non-Boolean values as well.  In particular, we provide a setting
 for deciding equality of bit vectors (lists of Boolean values).</p>

 <p>An introduction to BDDs for the automated reasoning community may be found
 in ``Introduction to the OBDD Algorithm for the ATP Community'' by J Moore,
 <i>Journal of Automated Reasoning</i> (1994), pp. 33&ndash;45.  (This paper
 also appears as Technical Report #84 from Computational Logic, Inc.)</p>

 <p>Further information about BDDs in ACL2 can be found in the subtopics of
 this @(see documentation) section.  In particular, see @(see bdd-introduction)
 for a good starting place that provides a number of examples.</p>

 <p>See @(see hints) for a description of @(':bdd') hints.  For quick
 reference, here is an example; but only the @(':vars') part of the hint is
 required, as explained in the documentation for @(see hints).  The values
 shown are the defaults.</p>

 @({
  (:vars nil :bdd-constructors (cons) :prove t :literal :all)
 })

 <p>We suggest that you next visit the documentation topic @(see
 BDD-INTRODUCTION).</p>")

(defxdoc bdd-algorithm
  :parents (bdd)
  :short "Summary of the BDD algorithm in ACL2"
  :long "<p>The BDD algorithm in ACL2 uses a combination of manipulation of
 @('IF') terms and unconditional rewriting.  In this discussion we begin with
 some relevant mathematical theory.  This is followed by a description of how
 ACL2 does BDDs, including concluding discussions of soundness, completeness,
 and efficiency.</p>

 <p>We recommend that you read the other documentation about BDDs in ACL2
 before reading the rather technical material that follows.  See @(see
 BDD).</p>

 <p>Here is an outline of our presentation.  Readers who want a user
 perspective, without undue mathematical theory, may wish to skip to Part (B),
 referring to Part (A) only on occasion if necessary.</p>

 <p>(A) <b>Mathematical Considerations</b></p>

 <blockquote>

 <p>(A1) BDD term order</p>

 <p>(A2) BDD-constructors and BDD terms, and their connection with aborting the
 BDD algorithm</p>

 <p>(A3) Canonical BDD terms</p>

 <p>(A4) A theorem stating the equivalence of provable and syntactic equality
 for canonical BDD terms</p>

 </blockquote>

 <p>(B) <b>Algorithmic Considerations</b></p>

 <blockquote>

 <p>(B1) BDD rules (rules used by the rewriting portion of the ACL2 BDD
 algorithm)</p>

 <p>(B2) Terms ``known to be Boolean''</p>

 <p>(B3) An ``IF-lifting'' operation used by the algorithm, as well as an
 iterative version of that operation</p>

 <p>(B4) The ACL2 BDD algorithm</p>

 <p>(B5) Soundness and Completeness of the ACL2 BDD algorithm</p>

 <p>(B6) Efficiency considerations</p></blockquote>

 <p>(A) <b>Mathematical Considerations</b></p>

 <p>(A1) <i>BDD term order</i></p>

 <p>Our BDD algorithm creates a total ``BDD term order'' on ACL2 terms, on the
 fly.  We use this order in our discussions below of IF-lifting and of
 canonical BDD terms, and in the algorithm's use of commutativity.  The
 particular order is unimportant, except that we guarantee (for purposes of
 commutative functions) that constants are smaller in this order than
 non-constants.</p>

 <p>(A2) <i>BDD-constructors</i> (assumed to be @(''(cons)')) and <i>BDD
 terms</i></p>

 <p>We take as given a list of function symbols that we call the
 ``BDD-constructors.''  By default, the only BDD-constructor is @(tsee cons),
 although it is legal to specify any list of function symbols as the
 BDD-constructors, either by using the @(see acl2-defaults-table) (see @(see
 acl2-defaults-table)) or by supplying a @(':BDD-CONSTRUCTORS') hint (see @(see
 hints)).  Warning: this capability is largely untested and may produce
 undesirable results.  Henceforth, except when explicitly stated to the
 contrary, we assume that BDD-constructors is @(''(cons)').</p>

 <p>Roughly speaking, a @(see BDD) term is the sort of @(see term) produced by
 our BDD algorithm, namely a tree with all @(tsee cons) nodes lying above all
 non-@('CONS') nodes.  More formally, a @(see term) is said to be a @(see BDD)
 term if it contains <b>no</b> subterm of either of the following forms, where
 @('f') is not @('CONS').</p>

 @({
  (f ... (CONS ...) ...)

  (f ... 'x ...)  ; where (consp x) = t
 })

 <p>We will see that whenever the BDD algorithm attempts to create a @(see
 term) that is not a @(see BDD) term, it aborts instead.  Thus, whenever the
 algorithm completes without aborting, it creates a @(see BDD) term.</p>

 <p>(A3) <i>Canonical BDD terms</i></p>

 <p>We can strengthen the notion of ``BDD term'' to a notion of ``canonical BDD
 term'' by imposing the following additional requirements, for every subterm of
 the form @('(IF x y z)'):</p>

 <blockquote><p>(a) @('x') is a variable, and it precedes (in the BDD term
 order) every variable occurring in @('y') or @('z');</p>

 <p>(b) @('y') and @('z') are syntactically distinct; and,</p>

 <p>(c) it is not the case that @('y') is @('t') and @('z') is
 @('nil').</p></blockquote>

 <p>We claim that it follows easily from our description of the BDD algorithm
 that every term it creates is a canonical BDD term, assuming that the
 variables occurring in all such terms are treated by the algorithm as being
 Boolean (see (B2) below) and that the terms contain no function symbols other
 than @('IF') and @('CONS').  Thus, under those assumptions the following
 theorem shows that the BDD algorithm never creates distinct terms that are
 provably equal, a property that is useful for completeness and efficiency (as
 we explain in (B5) and (B6) below).</p>

 <p>(A4) <i>Provably equal canonical BDD terms are identical</i></p>

 <p>We believe that the following theorem and proof are routine extensions of a
 standard result and proof to terms that allow calls of @('CONS').</p>

 <p><b>Theorem</b>.  Suppose that @('t1') and @('t2') are canonical BDD terms
 that contain no function symbols other than @('IF') and @('CONS').  Also
 suppose that @('(EQUAL t1 t2)') is a theorem.  Then @('t1') and @('t2') are
 syntactically identical.</p>

 <p>Proof of theorem: By induction on the total number of symbols occurring in
 these two terms.  First suppose that at least one term is a variable; without
 loss of generality let it be @('t1').  We must prove that @('t2') is
 syntactically the same as @('t1').  Now it is clearly consistent that
 @('(EQUAL t1 t2)') is false if @('t2') is a call of @('CONS') (to see this,
 simply let @('t1') be an value that is not a @('CONSP')).  Similarly, @('t2')
 cannot be a constant or a variable other than @('t1').  The remaining
 possibility to rule out is that @('t2') is of the form @('(IF t3 t4 t5)'),
 since by assumption its function symbol must be @('IF') or @('CONS') and we
 have already handled the latter case.  Since @('t2') is canonical, we know
 that @('t3') is a variable.  Since @('(EQUAL t1 t2)') is provable, i.e.,</p>

 @({
  (EQUAL t1 (if t3 t4 t5))
 })

 <p>is provable, it follows that we may substitute either @('t') or @('nil')
 for @('t3') into this equality to obtain two new provable equalities.  First,
 suppose that @('t1') and @('t3') are distinct variables.  Then these
 substitutions show that @('t1') is provably equal to both @('t4') and @('t5')
 (since @('t3') does not occur in @('t4') or @('t5') by property (a) above, as
 @('t2') is canonical), and hence @('t4') and @('t5') are provably equal to
 each other, which implies by the inductive hypothesis that they are the same
 term &mdash; and this contradicts the assumption that @('t2') is canonical
 (property (b)).  Therefore @('t1') and @('t3') are the same variable, i.e.,
 the equality displayed above is actually @('(EQUAL t1 (if t1 t4 t5))').
 Substituting @('t') and then @('nil') for @('t1') into this provable equality
 lets us prove @('(EQUAL t t4)') and @('(EQUAL nil t5)'), which by the
 inductive hypothesis implies that @('t4') is (syntactically) the term @('t')
 and @('t5') is @('nil').  That is, @('t2') is @('(IF t1 t nil)'), which
 contradicts the assumption that @('t2') is canonical (property (c)).</p>

 <p>Next, suppose that at least one term is a call of @('IF').  Our first
 observation is that the other term is also a call of @('IF').  For if the
 other is a call of @('CONS'), then they cannot be provably equal, because the
 former has no function symbols other than @('IF') and hence is Boolean when
 all its variables are assigned Boolean values.  Also, if the other is a
 constant, then both branches of the @('IF') term are provably equal to that
 constant and hence these branches are syntactically identical by the inductive
 hypothesis, contradicting property (b).  Hence, we may assume for this case
 that both terms are calls of @('IF'); let us write them as follows.</p>

 @({
  t0:  (IF t1 t2 t3)
  u0:  (IF u1 u2 u3)
 })

 <p>Note that @('t1') and @('u1') are variables, by property (a) of canonical
 BDD terms.  First we claim that @('t1') does not strictly precede @('u1') in
 the BDD term order.  For suppose @('t1') does strictly precede @('u1').  Then
 property (a) of canonical BDD terms guarantees that @('t1') does not occur in
 @('u0').  Hence, an argument much like one used above shows that @('u0') is
 provably equal to both @('t2') (substituting @('t') for @('t1')) and @('t3')
 (substituting @('nil') for @('t1')), and hence @('t2') and @('t3') are
 provably equal.  That implies that they are identical terms, by the inductive
 hypothesis, which then contradicts property (b) for @('t0').  Similarly,
 @('u1') does not strictly precede @('t1') in the BDD term order.  Therefore,
 @('t1') and @('u1') are the same variable.  By substituting @('t') for this
 variable we see that @('t2') and @('u2') are provably equal, and hence they
 are equal by the inductive hypothesis.  Similarly, by substituting @('nil')
 for @('t1') (and @('u1')) we see that @('t3') and @('u3') are provably, hence
 syntactically, equal.</p>

 <p>We have covered all cases in which at least one term is a variable or at
 least one term is a call of @('IF').  If both terms are constants, then
 provable and syntactic equality are clearly equivalent.  Finally, then, we may
 assume that one term is a call of @('CONS') and the other is a constant or a
 call of @('CONS').  The constant case is similar to the @('CONS') case if the
 constant is a @('CONSP'), so we omit it; while if the constant is not a
 @('CONSP') then it is not provably equal to a call of @('CONS'); in fact it is
 provably <i>not</i> equal!</p>

 <p>So, we are left with a final case, in which canonical BDD terms @('(CONS t1
 t2)') and @('(CONS u1 u2)') are provably equal, and we want to show that
 @('t1') and @('u1') are syntactically equal as are @('t2') and @('u2').  These
 conclusions are easy consequences of the inductive hypothesis, since the ACL2
 axiom @('CONS-EQUAL') (which you can inspect using @(':')@(tsee PE)) shows
 that equality of the given terms is equivalent to the conjunction of @('(EQUAL
 t1 t2)') and @('(EQUAL u1 u2)').  Q.E.D.</p>

 <p>(B) <b>Algorithmic Considerations</b></p>

 <p>(B1) <i>BDD rules</i></p>

 <p>A rule of class @(':')@(tsee rewrite) (see @(see rule-classes)) is said to
 be a ``@(see BDD) rewrite rule'' if and only if it satisfies the following
 criteria.  (1) The rule is @(see enable)d.  (2) Its @(see equivalence)
 relation is @(tsee equal).  (3) It has no hypotheses.  (4) Its @(':')@(tsee
 loop-stopper) field is @('nil'), i.e., it is not a permutative rule.  (5) All
 variables occurring in the rule occur in its left-hand side (i.e., there are
 no ``free variables''; see @(see rewrite)).  A rule of class @(':')@(tsee
 definition) (see @(see rule-classes)) is said to be a ``@(see BDD) definition
 rule'' if it satisfies all the criteria above (except (4), which does not
 apply), and moreover the top function symbol of the left-hand side was not
 recursively (or mutually recursively) defined.  Technical point: Note that
 this additional criterion is independent of whether or not the indicated
 function symbol actually occurs in the right-hand side of the rule.</p>

 <p>Both BDD rewrite rules and BDD definition rules are said to be ``BDD
 rules.''</p>

 <p>(B2) <i>Terms ''known to be Boolean''</i></p>

 <p>We apply the BDD algorithm in the context of a top-level goal to prove,
 namely, the goal at which the @(':BDD') hint is attached.  As we run the BDD
 algorithm, we allow ourselves to say that a set of @(see term)s is ``known to
 be Boolean'' if we can verify that the goal is provable from the assumption
 that at least one of the terms is not Boolean.  Equivalently, we allow
 ourselves to say that a set of terms is ``known to be Boolean'' if we can
 verify that the original goal is provably equivalent to the assertion that if
 all terms in the set are Boolean, then the goal holds.  The notion ``known to
 be Boolean'' is conservative in the sense that there are generally sets of
 terms for which the above equivalent criteria hold and yet the sets of terms
 are not noted as as being ``known to be Boolean.''  However, ACL2 uses a
 number of tricks, including @(see type-set) reasoning and analysis of the
 structure of the top-level goal, to attempt to establish that a sufficiently
 inclusive set of terms is known to be Boolean.</p>

 <p>From a practical standpoint, the algorithm determines a set of terms known
 to be Boolean; we allow ourselves to say that each term in this set is ``known
 to be Boolean.''  The algorithm assumes that these terms are indeed Boolean,
 and can make use of that assumption.  For example, if @('t1') is known to be
 Boolean then the algorithm simplifies @('(IF t1 t nil)') to @('t1'); see (iv)
 in the discussion immediately below.</p>

 <p>(B3) <i>IF-lifting</i> and the <i>IF-lifting-for-IF loop</i></p>

 <p>Suppose that one has a @(see term) of the form @('(f ... (IF test x y)
 ...)'), where @('f') is a function symbol other than @('CONS').  Then we say
 that ``IF-lifting'' @('test') ``from'' this term produces the following term,
 which is provably equal to the given term.</p>

 @({
  (if test
      (f ... x ...)  ; resulting true branch
      (f ... y ...)) ; resulting false branch
 })

 <p>Here, we replace each argument of @('f') of the form @('(IF test .. ..)'),
 for the same @('test'), in the same way.  In this case we say that
 ``IF-lifting applies to'' the given term, ``yielding the test'' @('test') and
 with the ``resulting two branches'' displayed above.  Whenever we apply
 IF-lifting, we do so for the available @('test') that is least in the BDD term
 order (see (A1) above).</p>

 <p>We consider arguments @('v') of @('f') that are ``known to be Boolean''
 (see above) to be replaced by @('(IF v t nil)') for the purposes of
 IF-lifting, i.e., before IF-lifting is applied.</p>

 <p>There is one special case, however, for IF-lifting.  Suppose that the given
 term is of the form @('(IF v y z)') where @('v') is a variable and is the test
 to be lifted out (i.e., it is least in the BDD term order among the potential
 tests).  Moreover, suppose that neither @('y') nor @('z') is of the form
 @('(IF v W1 W2)') for that same @('v').  Then IF-lifting does not apply to the
 given term.</p>

 <p>We may now describe the IF-lifting-for-IF loop, which applies to terms of
 the form @('(IF test tbr fbr)') where the algorithm has already produced
 @('test'), @('tbr'), and @('fbr').  First, if @('test') is @('nil') then we
 return @('fbr'), while if @('test') is a non-@('nil') constant or a call of
 @('CONS') then we return @('tbr').  Otherwise, we see if IF-lifting applies.
 If IF-lifting does not apply, then we return @('(IF test tbr fbr)').
 Otherwise, we apply IF-lifting to obtain a term of the form @('(IF x y z)'),
 by lifting out the appropriate test.  Now we recursively apply the
 IF-lifting-for-IF loop to the term @('(IF x y z)'), unless any of the
 following special cases apply.</p>

 <blockquote><p>(i) If @('y') and @('z') are the same term, then return
 @('y').</p>

 <p>(ii) Otherwise, if @('x') and @('z') are the same term, then replace @('z')
 by @('nil') before recursively applying IF-lifting-for-IF.</p>

 <p>(iii) Otherwise, if @('x') and @('y') are the same term and @('y') is known
 to be Boolean, then replace @('y') by @('t') before recursively applying
 IF-lifting-for-IF.</p>

 <p>(iv) If @('z') is @('nil') and either @('x') and @('y') are the same term
 or @('x') is ``known to be Boolean'' and @('y') is @('t'), then return
 @('x').</p></blockquote>

 <p>NOTE: When a variable @('x') is known to be Boolean, it is easy to see that
 the form @('(IF x t nil)') is always reduced to @('x') by this algorithm.</p>

 <p>(B4) <i>The ACL2 BDD algorithm</i></p>

 <p>We are now ready to present the BDD algorithm for ACL2.  It is given an
 ACL2 @(see term), @('x'), as well as an association list @('va') that maps
 variables to terms, including all variables occurring in @('x').  We maintain
 the invariant that whenever a variable is mapped by @('va') to a term, that
 term has already been constructed by the algorithm, except: initially @('va')
 maps every variable occurring in the top-level term to itself.  The algorithm
 proceeds as follows.  We implicitly ordain that whenever the BDD algorithm
 attempts to create a @(see term) that is not a @(see BDD) term (as defined
 above in (A2)), it aborts instead.  Thus, whenever the algorithm completes
 without aborting, it creates a @(see BDD) term.</p>

 <blockquote>

 <p>If @('x') is a variable, return the result of looking it up in @('va').</p>

 <p>If @('x') is a constant, return @('x').</p>

 <p>If @('x') is of the form @('(IF test tbr fbr)'), then first run the
 algorithm on @('test') with the given @('va') to obtain @('test'').  If
 @('test'') is @('nil'), then return the result @('fbr'') of running the
 algorithm on @('fbr') with the given @('va').  If @('test'') is a constant
 other than @('nil'), or is a call of @('CONS'), then return the result
 @('tbr'') of running the algorithm on @('tbr') with the given @('va').  If
 @('tbr') is identical to @('fbr'), return @('tbr').  Otherwise, return the
 result of applying the IF-lifting-for-IF loop (described above) to the term
 <tt>(IF test' tbr' fbr')</tt>.</p>

 <p>If @('x') is of the form @('(IF* test tbr fbr)'), then compute the result
 exactly as though @(tsee IF) were used rather than @(tsee IF*), except that if
 @('test'') is not a constant or a call of @('CONS') (see paragraph above),
 then abort the BDD computation.  Informally, the tests of @(tsee IF*) terms
 are expected to ``resolve.''  NOTE: This description shows how @(tsee IF*) can
 be used to implement conditional rewriting in the BDD algorithm.</p>

 <p>If @('x') is a @('LAMBDA') expression @('((LAMBDA vars body) . args)')
 (which often corresponds to a @(tsee LET) term; see @(see let)), then first
 form an alist @('va'') by binding each @('v') in @('vars') to the result of
 running the algorithm on the corresponding member of @('args'), with the
 current alist @('va').  Then, return the result of the algorithm on @('body')
 in the alist @('va'').</p>

 <p>Otherwise, @('x') is of the form @('(f x1 x2 ... xn)'), where @('f') is a
 function symbol other than @(tsee IF) or @(tsee IF*).  In that case, let
 @('xi'') be the result of running the algorithm on @('xi'), for @('i') from 1
 to @('n'), using the given alist @('va').  First there are a few special
 cases.  If @('f') is @(tsee EQUAL) then we return @('t') if @('x1'') is
 syntactically identical to @('x2'') (where this test is very fast; see (B6)
 below); we return @('x1'') if it is known to be Boolean and @('x2'') is
 @('t'); and similarly, we return @('x2'') if it is known to be Boolean and
 @('x1'') is @('t').  Next, if each @('xi'') is a constant and the @(':')@(tsee
 executable-counterpart) of @('f') is enabled, then the result is obtained by
 computation.  Next, if @('f') is @(tsee BOOLEANP) and @('x1'') is known to be
 Boolean, @('t') is returned.  Otherwise, we proceed as follows, first possibly
 swapping the arguments if they are out of (the BDD term) order and if @('f')
 is known to be commutative (see below).  If a BDD rewrite rule (as defined
 above) matches the term <tt>(f x1'... xn')</tt>, then the most recently stored
 such rule is applied.  If there is no such match and @('f') is a
 BDD-constructor, then we return <tt>(f x1'... xn')</tt>.  Otherwise, if a BDD
 definition rule matches this term, then the most recently stored such rule
 (which will usually be the original definition for most users) is applied.  If
 none of the above applies and neither does IF-lifting, then we return <tt>(f
 x1'... xn')</tt>.  Otherwise we apply IF-lifting to <tt>(f x1'... xn')</tt> to
 obtain a term @('(IF test tbr fbr)'); but we aren't done yet.  Rather, we run
 the BDD algorithm (using the same alist) on @('tbr') and @('fbr') to obtain
 terms @('tbr'') and @('fbr''), and we return <tt>(IF test tbr' fbr')</tt>
 unless @('tbr'') is syntactically identical to @('fbr''), in which case we
 return @('tbr'').</p></blockquote>

 <p>When is it the case that, as said above, ``@('f') is known to be
 commutative''?  This happens when an enabled rewrite rule is of the form
 @('(EQUAL (f X Y) (f Y X))').  Regarding swapping the arguments in that case:
 recall that we may assume very little about the BDD term order, essentially
 only that we swap the two arguments when the second is a constant and the
 first is not, for example, in @('(+ x 1)').  Other than that situation, one
 cannot expect to predict accurately when the arguments of commutative
 operators will be swapped.</p>

 <p>(B5) Soundness and Completeness of the ACL2 BDD algorithm</p>

 <p>Roughly speaking, ``soundness'' means that the BDD algorithm should give
 correct answers, and ``completeness'' means that it should be powerful enough
 to prove all true facts.  Let us make the soundness claim a little more
 precise, and then we'll address completeness under suitable hypotheses.</p>

 <p><b>Claim</b> (Soundness).  If the ACL2 BDD algorithm runs to completion on
 an input term @('t0'), then it produces a result that is provably equal to
 @('t0').</p>

 <p>We leave the proof of this claim to the reader.  The basic idea is simply
 to check that each step of the algorithm preserves the meaning of the term
 under the bindings in the given alist.</p>

 <p>Let us start our discussion of completeness by recalling the theorem proved
 above in (A4).</p>

 <p><b>Theorem</b>.  Suppose that @('t1') and @('t2') are canonical BDD terms
 that contain no function symbols other than @('IF') and @('CONS').  Also
 suppose that @('(EQUAL t1 t2)') is a theorem.  Then @('t1') and @('t2') are
 syntactically identical.</p>

 <p>Below we show how this theorem implies the following completeness property
 of the ACL2 BDD algorithm.  We continue to assume that @('CONS') is the only
 BDD-constructor.</p>

 <p><b>Claim</b> (Completeness).  Suppose that @('t1') and @('t2') are provably
 equal terms, under the assumption that all their variables are known to be
 Boolean.  Assume further that under this same assumption, top-level runs of
 the ACL2 BDD algorithm on these terms return terms that contain only the
 function symbols @('IF') and @('CONS').  Then the algorithm returns the same
 term for both @('t1') and @('t2'), and the algorithm reduces @('(EQUAL t1
 t2)') to @('t').</p>

 <p>Why is this claim true?  First, notice that the second part of the
 conclusion follows immediately from the first, by definition of the algorithm.
 Next, notice that the terms @('u1') and @('u2') obtained by running the
 algorithm on @('t1') and @('t2'), respectively, are provably equal to @('t1')
 and @('t2'), respectively, by the Soundness Claim.  It follows that @('u1')
 and @('u2') are provably equal to each other.  Since these terms contain no
 function symbols other than @('IF') or @('CONS'), by hypothesis, the Claim now
 follows from the Theorem above together with the following lemma.</p>

 <p><b>Lemma</b>.  Suppose that the result of running the ACL2 BDD algorithm on
 a top-level term @('t0') is a term @('u0') that contains only the function
 symbols @('IF') and @('CONS'), where all variables of @('t0') are known to be
 Boolean.  Then @('u0') is a canonical BDD term.</p>

 <p>Proof: left to the reader.  Simply follow the definition of the algorithm,
 with a separate argument for the IF-lifting-for-IF loop.</p>

 <p>Finally, let us remark on the assumptions of the Completeness Claim above.
 The assumption that all variables are known to be Boolean is often true; in
 fact, the system uses the forward-chaining rule @('boolean-listp-forward')
 (you can see it using @(':')@(tsee pe)) to try to establish this assumption,
 if your theorem has a form such as the following.</p>

 @({
  (let ((x (list x0 x1 ...))
        (y (list y0 y1 ...)))
    (implies (and (boolean-listp x)
                  (boolean-listp y))
             ...))
 })

 <p>Moreover, the @(':BDD') hint can be used to force the prover to abort if it
 cannot check that the indicated variables are known to be Boolean; see @(see
 hints).</p>

 <p>Finally, consider the effect in practice of the assumption that the terms
 resulting from application of the algorithm contain calls of @('IF') and
 @('CONS') only.  Typical use of BDDs in ACL2 takes place in a theory (see
 @(see theories)) in which all relevant non-recursive function symbols are
 enabled and all recursive function symbols possess enabled BDD rewrite rules
 that tell them how open up.  For example, such a rule may say how to expand on
 a given function call's argument that has the form @('(CONS a x)'), while
 another may say how to expand when that argument is @('nil')).  (See for
 example the rules @('append-cons') and @('append-nil') in the documentation
 for @(tsee IF*).)  We leave it to future work to formulate a theorem that
 guarantees that the BDD algorithm produces terms containing calls only of
 @('IF') and @('CONS') assuming a suitably ``complete'' collection of rewrite
 rules.</p>

 <p>(B6) <i>Efficiency considerations</i></p>

 <p>Following Bryant's algorithm, we use a graph representation of @(see term)s
 created by the BDD algorithm's computation.  This representation enjoys some
 important properties.</p>

 <blockquote>

 <p>(Time efficiency) The test for syntactic equality of BDD terms is very
 fast.</p>

 <p>(Space efficiency) Equal BDD data structures are stored identically in
 memory.</p></blockquote>

 <p><i>Implementation note.</i> The representation actually uses a sort of hash
 table for BDD terms that is implemented as an ACL2 1-dimensional array.  See
 @(see arrays).  In addition, we use a second such hash table to avoid
 recomputing the result of applying a function symbol to the result of running
 the algorithm on its arguments.  We believe that these uses of hash tables are
 standard.  They are also discussed in Moore's paper on BDDs; see @(see bdd)
 for the reference.</p>")

(defxdoc bdd-introduction
  :parents (bdd)
  :short "Examples illustrating the use of BDDs in ACL2"
  :long "<p>See @(see bdd) for a brief introduction to BDDs in ACL2 and for
 pointers to other documentation on BDDs in ACL2.  Here, we illustrate the use
 of BDDs in ACL2 by way of some examples.  For a further example, see @(see
 if*).</p>

 <p>Let us begin with a really simple example.  (We will explain the @(':bdd')
 hint @('(:vars nil)') below.)</p>

 @({
  ACL2 !>(thm (equal (if a b c) (if (not a) c b))
              :hints ((\"Goal\" :bdd (:vars nil)))) ; Prove with BDDs

  [Note:  A hint was supplied for our processing of the goal above.
  Thanks!]

  But simplification with BDDs (7 nodes) reduces this to T, using the
  :definitions EQUAL and NOT.

  Q.E.D.

  Summary
  Form:  ( THM ...)
  Rules: ((:DEFINITION EQUAL) (:DEFINITION NOT))
  Warnings:  None
  Time:  0.18 seconds (prove: 0.05, print: 0.02, other: 0.12)

  Proof succeeded.
  ACL2 !>
 })

 <p>The @(':bdd') hint @('(:vars nil)') indicates that BDDs are to be used on
 the indicated goal, and that any so-called ``variable ordering'' may be used:
 ACL2 may use a convenient order that is far from optimal.  It is beyond the
 scope of the present documentation to address the issue of how the user may
 choose good variable orderings.  Someday our implementation of BDDs may be
 improved to include heuristically-chosen variable orderings rather than rather
 random ones.</p>

 <p>Here is a more interesting example.</p>

 @({
  (defun v-not (x)
  ; Complement every element of a list of Booleans.
    (if (consp x)
        (cons (not (car x)) (v-not (cdr x)))
      nil))

  ; Now we prove a rewrite rule that explains how to open up v-not on
  ; a consp.
  (defthm v-not-cons
    (equal (v-not (cons x y))
           (cons (not x) (v-not y))))

  ; Finally, we prove for 7-bit lists that v-not is self-inverting.
  (thm
   (let ((x (list x0 x1 x2 x3 x4 x5 x6)))
     (implies (boolean-listp x)
              (equal (v-not (v-not x)) x)))
   :hints ((\"Goal\" :bdd
                   ;; Note that this time we specify a variable order.
                   (:vars (x0 x1 x2 x3 x4 x5 x6)))))
 })

 <p>It turns out that the variable order doesn't seem to matter in this
 example; using several orders we found that 30 nodes were created, and the
 proof time was about 1/10 of a second on a (somewhat enhanced) Sparc 2.  The
 same proof took about a minute and a half without any @(':bdd') hint!  This
 observation is a bit misleading perhaps, since the theorem for arbitrary
 @('x'),</p>

 @({
  (thm
   (implies (boolean-listp x)
            (equal (v-not (v-not x)) x)))
 })

 <p>only takes about 1.5 times as long as the @(':bdd') proof for 7 bits,
 above!  Nevertheless, BDDs can be very useful in reducing proof time,
 especially when there is no regular structure to facilitate proof by
 induction, or when the induction scheme is so complicated to construct that
 significant user effort is required to get the proof by induction to go
 through.</p>

 <p>Finally, consider the preceding example, with a @(':bdd') hint of (say)
 @('(:vars nil)'), but with the rewrite rule @('v-not-cons') above disabled.
 In that case, the proof fails, as we see below.  That is because the BDD
 algorithm in ACL2 uses hypothesis-free @(':')@(see rewrite) rules,
 @(':')@(tsee executable-counterpart)@('s'), and nonrecursive definitions, but
 it does not use recursive definitions.</p>

 <p>Notice that when we issue the @('(show-bdd)') command, the system's
 response clearly shows that we need a rewrite rule for simplifying terms of
 the form @('(v-not (cons ...))').</p>

 @({
  ACL2 !>(thm
          (let ((x (list x0 x1 x2 x3 x4 x5 x6)))
            (implies (boolean-listp x)
                     (equal (v-not (v-not x)) x)))
          :hints ((\"Goal\" :bdd (:vars nil)
                   :in-theory (disable v-not-cons))))

  [Note:  A hint was supplied for our processing of the goal above.
  Thanks!]

  ACL2 Error in ( THM ...):  Attempted to create V-NOT node during BDD
  processing with an argument that is a call of a bdd-constructor,
  which would produce a non-BDD term (as defined in :DOC
  bdd-algorithm).  See :DOC show-bdd.

  Summary
  Form:  ( THM ...)
  Rules: NIL
  Warnings:  None
  Time:  0.58 seconds (prove: 0.13, print: 0.00, other: 0.45)

  ******** FAILED ********  See :DOC failure  ******** FAILED ********
  ACL2 !>(show-bdd)

  BDD computation on Goal yielded 17 nodes.
  ------------------------------

  BDD computation was aborted on Goal, and hence there is no
  falsifying assignment that can be constructed.  Here is a backtrace
  of calls, starting with the top-level call and ending with the one
  that led to the abort.  See :DOC show-bdd.

  (LET ((X (LIST X0 X1 X2 X3 X4 X5 ...)))
       (IMPLIES (BOOLEAN-LISTP X)
                (EQUAL (V-NOT (V-NOT X)) X)))
    alist: ((X6 X6) (X5 X5) (X4 X4) (X3 X3) (X2 X2) (X1 X1) (X0 X0))

  (EQUAL (V-NOT (V-NOT X)) X)
    alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...)))

  (V-NOT (V-NOT X))
    alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...)))

  (V-NOT X)
    alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...)))
  ACL2 !>
 })

 <p>The term that has caused the BDD algorithm to abort is thus @('(V-NOT X)'),
 where @('X') has the value @('(LIST X0 X1 X2 X3 X4 X5 ...)'), i.e., @('(CONS
 X0 (LIST X1 X2 X3 X4 X5 ...))').  Thus, we see the utility of introducing a
 rewrite rule to simplify terms of the form @('(V-NOT (CONS ...))').  The moral
 of this story is that if you get an error of the sort shown above, you may
 find it useful to execute the command @('(show-bdd)') and use the result as
 advice that suggests the left hand side of a rewrite rule.</p>

 <p>Here is another sort of failed proof.  In this version we have omitted the
 hypothesis that the input is a bit vector.  Below we use @('show-bdd') to see
 what went wrong, and use the resulting information to construct a
 counterexample.  This failed proof corresponds to a slightly modified input
 theorem, in which @('x') is bound to the 4-element list @('(list x0 x1 x2
 x3)').</p>

 @({
  ACL2 !>(thm
          (let ((x (list x0 x1 x2 x3)))
            (equal (v-not (v-not x)) x))
          :hints ((\"Goal\" :bdd
                   ;; This time we do not specify a variable order.
                   (:vars nil))))

  [Note:  A hint was supplied for our processing of the goal above.
  Thanks!]

  ACL2 Error in ( THM ...):  The :BDD hint for the current goal has
  successfully simplified this goal, but has failed to prove it.
  Consider using (SHOW-BDD) to suggest a counterexample; see :DOC
  show-bdd.

  Summary
  Form:  ( THM ...)
  Rules: NIL
  Warnings:  None
  Time:  0.18 seconds (prove: 0.07, print: 0.00, other: 0.12)

  ******** FAILED ********  See :DOC failure  ******** FAILED ********
  ACL2 !>(show-bdd)

  BDD computation on Goal yielded 73 nodes.
  ------------------------------

  Falsifying constraints:
  ((X0 \"Some non-nil value\")
   (X1 \"Some non-nil value\")
   (X2 \"Some non-nil value\")
   (X3 \"Some non-nil value\")
   ((EQUAL 'T X0) T)
   ((EQUAL 'T X1) T)
   ((EQUAL 'T X2) T)
   ((EQUAL 'T X3) NIL))

  ------------------------------

  Term obtained from BDD computation on Goal:

  (IF X0
      (IF X1
          (IF X2 (IF X3 (IF # # #) (IF X3 # #))
              (IF X2 'NIL (IF X3 # #)))
          (IF X1 'NIL
              (IF X2 (IF X3 # #) (IF X2 # #))))
      (IF X0 'NIL
          (IF X1 (IF X2 (IF X3 # #) (IF X2 # #))
              (IF X1 'NIL (IF X2 # #)))))

  ACL2 Query (:SHOW-BDD):  Print the term in full?  (N, Y, W or ?):
  n ; I've seen enough.  The assignment shown above suggests
    ; (though not conclusively) that if we bind x3 to a non-nil
    ; value other than T, and bind x0, x1, and x2 to t, then we
    ; this may give us a counterexample.
  ACL2 !>(let ((x0 t) (x1 t) (x2 t) (x3 7))
           (let ((x (list x0 x1 x2 x3)))
             ;; Let's use LIST instead of EQUAL to see how the two
             ;; lists differ.
             (list (v-not (v-not x)) x)))
  ((T T T T) (T T T 7))
  ACL2 !>
 })

 <p>See @(see if*) for another example.</p>")

(defxdoc bibliography
  :parents (about-acl2)
  :short "Reports about ACL2"
  :long "<p>The ACL2 home page includes a <a
  href='http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html'>list
  of notes and reports about ACL2</a>.</p>")

(defxdoc binary-*
  :parents (* acl2-built-ins)
  :short "Multiplication function"
  :long "<p>Completion Axiom (@('completion-of-*')):</p>

 @({
  (equal (binary-* x y)
         (if (acl2-numberp x)
             (if (acl2-numberp y)
                 (binary-* x y)
               0)
           0))
 })

 <p>@(see Guard) for @('(binary-* x y)'):</p>

 @({
  (and (acl2-numberp x) (acl2-numberp y))
 })

 <p>Notice that like all arithmetic functions, @('binary-*') treats non-numeric
 inputs as @('0').</p>

 <p>Calls of the macro @(tsee *) expand to calls of @('binary-*'); see @(see
 *).</p>")

(defxdoc binary-+
  :parents (+ acl2-built-ins)
  :short "Addition function"
  :long "<p>Completion Axiom (@('completion-of-+')):</p>

 @({
  (equal (binary-+ x y)
         (if (acl2-numberp x)
             (if (acl2-numberp y)
                 (binary-+ x y)
               x)
           (if (acl2-numberp y)
               y
             0)))
 })

 <p>@(see Guard) for @('(binary-+ x y)'):</p>

 @({
  (and (acl2-numberp x) (acl2-numberp y))
 })

 <p>Notice that like all arithmetic functions, @('binary-+') treats non-numeric
 inputs as @('0').</p>

 <p>Calls of the macro @(tsee +) expand to calls of @('binary-+'); see @(see
 +).</p>")

(defxdoc binary-append
  :parents (append acl2-built-ins)
  :short "@(see concatenate) two lists"
  :long "<p>This binary function implements @(tsee append), which is a macro in
 ACL2.  See @(see append)</p>

 <p>The @(see guard) for @('binary-append') requires the first argument to be a
 @(tsee true-listp).</p>

 @(def binary-append)")

(defxdoc bind-free
  :parents (rewrite linear definition)
  :short "To bind free variables of a rewrite, definition, or linear rule"
  :long "@({
  Examples:
  (IMPLIES (AND (RATIONALP LHS)
                (RATIONALP RHS)
                (BIND-FREE (FIND-MATCH-IN-PLUS-NESTS LHS RHS) (X)))
           (EQUAL (EQUAL LHS RHS)
                  (EQUAL (+ (- X) LHS) (+ (- X) RHS))))

  (IMPLIES (AND (BIND-FREE
                  (FIND-RATIONAL-MATCH-IN-TIMES-NESTS LHS RHS MFC STATE)
                  (X))
                (RATIONALP X)
                (CASE-SPLIT (NOT (EQUAL X 0))))
           (EQUAL (< LHS RHS)
                  (IF (< 0 X)
                      (< (* (/ X) LHS) (* (/ X) RHS))
                     (< (* (/ X) RHS) (* (/ X) LHS)))))
 })

 <p>General Forms:</p>

 @({
  (BIND-FREE term var-list)
  (BIND-FREE term t)
  (BIND-FREE term)
 })

 <p>A rule which uses a @('bind-free') hypothesis has similarities to both a
 rule which uses a @(tsee syntaxp) hypothesis and to a @(':')@(tsee meta) rule.
 @('Bind-free') is like @(tsee syntaxp), in that it logically always returns
 @('t') but may affect the application of a @(':')@(tsee rewrite), @(':')@(tsee
 definition), or @(':')@(tsee linear) rule when it is called at the top-level
 of a hypothesis.  It is like a @(':')@(tsee meta) rule, in that it allows the
 user to perform transformations of terms under programmatic control.</p>

 <p>Note that a @('bind-free') hypothesis does not, in general, deal with the
 meaning or semantics or values of the terms, but rather with their syntactic
 forms.  Before attempting to write a rule which uses @('bind-free'), the user
 should be familiar with @(tsee syntaxp) and the internal form that ACL2 uses
 for terms.  This internal form is similar to what the user sees, but there are
 subtle and important differences.  @(tsee Trans) can be used to view this
 internal form.</p>

 <p>Just as for a @(tsee syntaxp) hypothesis, there are two basic types of
 @('bind-free') hypotheses.  The simpler type of @('bind-free') hypothesis may
 be used as the nth hypothesis in a @(':')@(tsee rewrite), @(':')@(tsee
 definition), or @(':')@(tsee linear) rule whose @(':')@(tsee corollary) is
 @('(implies (and hyp1 ... hypn ... hypk) (equiv lhs rhs))') provided @('term')
 is a term, @('term') contains at least one variable, and every variable
 occurring freely in @('term') occurs freely in @('lhs') or in some @('hypi'),
 @('i<n').  In addition, @('term') must not use any stobjs.  Later below we
 will describe the second type, an <i>extended</i> @('bind-free') hypothesis,
 which may use @(tsee state).  Whether simple or extended, a @('bind-free')
 hypothesis may return an alist that binds free variables, as explained below,
 or it may return a list of such alists.  We focus on the first of these cases:
 return of a single binding alist.  We conclude our discussion with a section
 that covers the other case: return of a list of alists.</p>

 <p>We begin our description of @('bind-free') by examining the first example
 above in some detail.</p>

 <p>We wish to write a rule which will cancel ``like'' addends from both sides
 of an equality.  Clearly, one could write a series of rules such as</p>

 @({
  (DEFTHM THE-HARD-WAY-2-1
     (EQUAL (EQUAL (+ A X B)
                   (+ X C))
            (EQUAL (+ A B)
                   (FIX C))))
 })

 <p>with one rule for each combination of positions the matching addends might
 be found in (if one knew before-hand the maximum number of addends that would
 appear in a sum).  But there is a better way.  (In what follows, we assume the
 presence of an appropriate set of rules for simplifying sums.)</p>

 <p>Consider the following definitions and theorem:</p>

 @({
  (DEFUN INTERSECTION-EQUAL (X Y)
    (COND ((ENDP X)
           NIL)
          ((MEMBER-EQUAL (CAR X) Y)
           (CONS (CAR X) (INTERSECTION-EQUAL (CDR X) Y)))
          (T
           (INTERSECTION-EQUAL (CDR X) Y))))

  (DEFUN PLUS-LEAVES (TERM)
    (IF (EQ (FN-SYMB TERM) 'BINARY-+)
        (CONS (FARGN TERM 1)
              (PLUS-LEAVES (FARGN TERM 2)))
      (LIST TERM)))

  (DEFUN FIND-MATCH-IN-PLUS-NESTS (LHS RHS)
    (IF (AND (EQ (FN-SYMB LHS) 'BINARY-+)
             (EQ (FN-SYMB RHS) 'BINARY-+))
        (LET ((COMMON-ADDENDS (INTERSECTION-EQUAL (PLUS-LEAVES LHS)
                                                  (PLUS-LEAVES RHS))))
          (IF COMMON-ADDENDS
              (LIST (CONS 'X (CAR COMMON-ADDENDS)))
            NIL))
      NIL))

  (DEFTHM CANCEL-MATCHING-ADDENDS-EQUAL
    (IMPLIES (AND (RATIONALP LHS)
                  (RATIONALP RHS)
                  (BIND-FREE (FIND-MATCH-IN-PLUS-NESTS LHS RHS) (X)))
             (EQUAL (EQUAL LHS RHS)
                    (EQUAL (+ (- X) LHS) (+ (- X) RHS)))))
 })

 <p>How is this rule applied to the following term?</p>

 @({
  (equal (+ 3 (expt a n) (foo a c))
         (+ (bar b) (expt a n)))
 })

 <p>As mentioned above, the internal form of an ACL2 term is not always what
 one sees printed out by ACL2.  In this case, by using @(':')@(tsee trans) one
 can see that the term is stored internally as</p>

 @({
  (equal (binary-+ '3
                   (binary-+ (expt a n) (foo a c)))
         (binary-+ (bar b) (expt a n))).
 })

 <p>When ACL2 attempts to apply @('cancel-matching-addends-equal') to the term
 under discussion, it first forms a substitution that instantiates the
 left-hand side of the conclusion so that it is identical to the target term.
 This substitution is kept track of by the substitution alist:</p>

 @({
  ((LHS . (binary-+ '3
                     (binary-+ (expt a n) (foo a c))))
   (RHS . (binary-+ (bar b) (expt a n)))).
 })

 <p>ACL2 then attempts to relieve the hypotheses in the order they were given.
 Ordinarily this means that we instantiate each hypothesis with our
 substitution and then attempt to rewrite the resulting instance to true.
 Thus, in order to relieve the first hypothesis, we rewrite:</p>

 @({
  (RATIONALP (binary-+ '3
                        (binary-+ (expt a n) (foo a c)))).
 })

 <p>Let us assume that the first two hypotheses rewrite to @('t').  How do we
 relieve the @('bind-free') hypothesis?  Just as for a @(tsee syntaxp)
 hypothesis, ACL2 evaluates @('(find-match-in-plus-nests lhs rhs)') in an
 environment where @('lhs') and @('rhs') are instantiated as determined by the
 substitution.  In this case we evaluate</p>

 @({
  (FIND-MATCH-IN-PLUS-NESTS '(binary-+ '3
                                        (binary-+ (expt a n) (foo a c)))
                            '(binary-+ (bar b) (expt a n))).
 })

 <p>Observe that, just as in the case of a @(tsee syntaxp) hypothesis, we
 substitute the quotation of the variables bindings into the term to be
 evaluated.  See @(see syntaxp) for the reasons for this.  The result of this
 evaluation, @('((X . (EXPT A N)))'), is then used to extend the substitution
 alist:</p>

 @({
  ((X . (EXPT A N))
   (LHS . (binary-+ '3
                     (binary-+ (expt a n) (foo a c))))
   (RHS . (binary-+ (bar b) (expt a n)))),
 })

 <p>and this extended substitution determines
 @('cancel-matching-addends-equal')'s result:</p>

 @({
  (EQUAL (+ (- X) LHS) (+ (- X) RHS))
  ==>
  (EQUAL (+ (- (EXPT A N)) 3 (EXPT A N) (FOO A C))
         (+ (- (EXPT A N)) (BAR B) (EXPT A N))).
 })

 <p>Question: What is the internal form of this result?<br></br>

 Hint: Use @(':')@(tsee trans).</p>

 <p>When this rule fires, it adds the negation of a common term to both sides
 of the equality by selecting a binding for the otherwise-free variable @('x'),
 under programmatic control.  Note that other mechanisms such as the binding of
 @(see free-variables) may also extend the substitution alist.</p>

 <p>Just as for a @(tsee syntaxp) test, a @('bind-free') form signals failure
 by returning @('nil').  However, while a @(tsee syntaxp) test signals success
 by returning true, a @('bind-free') form signals success by returning an alist
 which is used to extend the current substitution alist.  Because of this use
 of the alist, there are several restrictions on it &mdash; in particular the
 alist must only bind variables, these variables must not be already bound by
 the substitution alist, and the variables must be bound to ACL2 terms.  If
 @('term') returns an alist and the alist meets these restrictions, we append
 the alist to the substitution alist and use the result as the new current
 substitution alist.  This new current substitution alist is then used when we
 attempt to relieve the next hypothesis or, if there are no more, instantiate
 the right hand side of the rule.</p>

 <p>There is also a second, optional, @('var-list') argument to a
 @('bind-free') hypothesis.  If provided, it must be either @('t') or a list of
 variables.  If it is not provided, it defaults to @('t').  If it is a list of
 variables, this second argument is used to place a further restriction on the
 possible values of the alist to be returned by @('term'): any variables bound
 in the alist must be present in the list of variables.  We strongly recommend
 the use of this list of variables, as it allows some consistency checks to be
 performed at the time of the rule's admittance which are not possible
 otherwise.</p>

 <p>An extended @('bind-free') hypothesis is similar to the simple type
 described above, but it uses two additional variables, @('mfc') and
 @('state'), which must not be bound by the left hand side or an earlier
 hypothesis of the rule.  They must be the last two variables mentioned by
 @('term'): first @('mfc'), then @('state').  These two variables give access
 to the functions @('mfc-')xxx; see @(see extended-metafunctions).  As
 described there, @('mfc') is bound to the so-called metafunction-context and
 @('state') to ACL2's @(tsee state).  See @(see bind-free-examples) for
 examples of the use of these extended @('bind-free') hypotheses.</p>

 <p><b>SECTION</b>: Returning a list of alists.</p>

 <p>As promised above, we conclude with a discussion of the case that
 evaluation of the @('bind-free') term produces a list of alists, @('x'),
 rather than a single alist.  In this case each member @('b') of @('x') is
 considered in turn, starting with the first and proceeding through the list.
 Each such @('b') is handled exactly as discussed above, as though it were the
 result of evaluating the @('bind-free') term.  Thus, each @('b') extends the
 current variable binding alist, and all remaining hypotheses are then
 relieved, as though @('b') had been the value obtained by evaluating the
 @('bind-free') term.  As soon as one such @('b') leads to successful relieving
 of all remaining hypotheses, the process of relieving hypotheses concludes, so
 no further members of @('x') are considered.</p>

 <p>We illustrate with a simple pedagogical example.  First introduce functions
 @('p1') and @('p2') such that a rewrite rule specifies that @('p2') implies
 @('p1'), but with a free variable.</p>

 @({
  (defstub p1 (x) t)
  (defstub p2 (x y) t)

  (defaxiom p2-implies-p1
    (implies (p2 x y)
             (p1 x)))
 })

 <p>If we add the following axiom, then @('(p1 x)') follows logically for all
 @('x').</p>

 @({
  (defaxiom p2-instance
    (p2 v (cons v 4)))
 })

 <p>Unfortunately, evaluation of @('(thm (p1 a))') fails, because ACL2 fails to
 bind the free variable @('y') in order to apply the rule @('p2-instance').</p>

 <p>Let's define a function that produces a list of alists, each binding the
 variable @('y').  Of course, we know that only the middle one below is
 necessary in this simple example.  In more complex examples, one might use
 heuristics to construct such a list of alists.</p>

 @({
  (defun my-alists (x)
    (list (list (cons 'y (fcons-term* 'cons x ''3)))
          (list (cons 'y (fcons-term* 'cons x ''4)))
          (list (cons 'y (fcons-term* 'cons x ''5)))))
 })

 <p>The following rewrite rule uses @('bind-free') to return a list of
 candidate alists binding @('y').</p>

 @({
  (defthm p2-implies-p1-better
    (implies (and (bind-free (my-alists x)
                             (y)) ; the second argument, (y), is optional
                  (p2 x y))
             (p1 x)))
 })

 <p>Now the proof succeeds for @('(thm (p1 a))').  Why?  When ACL2 applies the
 @('rewrite') rule @('p2-implies-p1-better'), it evaluates @('my-alists'), as
 we can see from the following @(see trace), to bind @('y') in three different
 alists.</p>

 @({
  ACL2 !>(thm (p1 a))
  1> (ACL2_*1*_ACL2::MY-ALISTS A)
  <1 (ACL2_*1*_ACL2::MY-ALISTS (((Y CONS A '3))
                                ((Y CONS A '4))
                                ((Y CONS A '5))))

  Q.E.D.
 })

 <p>The first alist, binding @('y') to @('(cons a '3)'), fails to allow the
 hypothesis @('(p2 x y)') to be proved.  But the next binding of @('y'), to
 @('(cons a '4)'), succeeds: then the current binding alist is @('((x . a) (y
 . (cons a '4)))'), for which the hypothesis @('(p2 x y)') rewrites to true
 using the rewrite rule @('p2-instance').</p>")

(defxdoc bind-free-examples
  :parents (bind-free)
  :short "Examples pertaining to @(tsee bind-free) hypotheses"
  :long "<p>See @(see bind-free) for a basic discussion of the use of
 @('bind-free') to control rewriting.</p>

 <p>Note that the examples below all illustrate the common case in which a
 @('bind-free') hypothesis generates a binding alist.  See @(see bind-free), in
 particular the final section, for a discussion of the case that instead a list
 of binding alists is generated.</p>

 <p>We give examples of the use of @(tsee bind-free) hypotheses from the
 perspective of a user interested in reasoning about arithmetic, but it should
 be clear that @(tsee bind-free) can be used for many other purposes also.</p>

 <p>EXAMPLE 1: Cancel a common factor.</p>

 @({
  (defun bind-divisor (a b)

  ; If a and b are polynomials with a common factor c, we return a
  ; binding for x.  We could imagine writing get-factor to compute the
  ; gcd, or simply to return a single non-invertible factor.

    (let ((c (get-factor a b)))
      (and c (list (cons 'x c)))))

  (defthm cancel-factor
    ;; We use case-split here to ensure that, once we have selected
    ;; a binding for x, the rest of the hypotheses will be relieved.
    (implies (and (acl2-numberp a)
                  (acl2-numberp b)
                  (bind-free (bind-divisor a b) (x))
                  (case-split (not (equal x 0)))
                  (case-split (acl2-numberp x)))
             (iff (equal a b)
                  (equal (/ a x) (/ b x)))))
 })

 <p>EXAMPLE 2: Pull integer summand out of floor.  Note: This example has an
 <i>extended</i> @(tsee bind-free) hypothesis, which uses the term
 @('(find-int-in-sum sum mfc state)').</p>

 @({
  (defun fl (x)
    ;; This function is defined, and used, in the IHS books.
    (floor x 1))

  (defun int-binding (term mfc state)
    ;; The call to mfc-ts returns the encoded type of term. ;
    ;; Thus, we are asking if term is known by type reasoning to ;
    ;; be an integer. ;
    (declare (xargs :stobjs (state) :mode :program))
    (if (ts-subsetp (mfc-ts term mfc state)
                    *ts-integer*)
        (list (cons 'int term))
      nil))

  (defun find-int-in-sum (sum mfc state)
    (declare (xargs :stobjs (state) :mode :program))
    (if (and (nvariablep sum)
             (not (fquotep sum))
             (eq (ffn-symb sum) 'binary-+))
        (or (int-binding (fargn sum 1) mfc state)
            (find-int-in-sum (fargn sum 2) mfc state))
      (int-binding sum mfc state)))

  ; Some additional work is required to prove the following.  So for
  ; purposes of illustration, we wrap skip-proofs around the defthm.

  (skip-proofs
   (defthm cancel-fl-int
    ;; The use of case-split is probably not needed, since we should
    ;; know that int is an integer by the way we selected it.  But this
    ;; is safer.
     (implies (and (acl2-numberp sum)
                   (bind-free (find-int-in-sum sum mfc state) (int))
                   (case-split (integerp int)))
              (equal (fl sum)
                     (+ int (fl (- sum int)))))
     :rule-classes ((:rewrite :match-free :all)))
  )

  ; Arithmetic libraries will have this sort of lemma.
  (defthm hack (equal (+ (- x) x y) (fix y)))

  (in-theory (disable fl))

  (thm (implies (and (integerp x) (acl2-numberp y))
                (equal (fl (+ x y)) (+ x (fl y)))))
 })

 <p>EXAMPLE 3: Simplify terms such as (equal (+ a (* a b)) 0)</p>

 @({
  (defun factors (product)
    ;; We return a list of all the factors of product.  We do not
    ;; require that product actually be a product.
    (if (eq (fn-symb product) 'BINARY-*)
        (cons (fargn product 1)
              (factors (fargn product 2)))
      (list product)))

  (defun make-product (factors)
    ;; Factors is assumed to be a list of ACL2 terms.  We return an
    ;; ACL2 term which is the product of all the elements of the
    ;; list factors.
    (cond ((atom factors)
           ''1)
          ((null (cdr factors))
           (car factors))
          ((null (cddr factors))
           (list 'BINARY-* (car factors) (cadr factors)))
          (t
           (list 'BINARY-* (car factors) (make-product (cdr factors))))))

  (defun quotient (common-factors sum)
    ;; Common-factors is a list of ACL2 terms.   Sum is an ACL2 term each
    ;; of whose addends have common-factors as factors.  We return
    ;; (/ sum (make-product common-factors)).
    (if (eq (fn-symb sum) 'BINARY-+)
        (let ((first (make-product (set-difference-equal (factors (fargn sum 1))
                                                         common-factors))))
          (list 'BINARY-+ first (quotient common-factors (fargn sum 2))))
      (make-product (set-difference-equal (factors sum)
                                          common-factors))))

  (defun intersection-equal (x y)
    (cond ((endp x)
           nil)
          ((member-equal (car x) y)
           (cons (car x) (intersection-equal (cdr x) y)))
          (t
           (intersection-equal (cdr x) y))))

  (defun common-factors (factors sum)
    ;; Factors is a list of the factors common to all of the addends
    ;; examined so far.  On entry, factors is a list of the factors in
    ;; the first addend of the original sum, and sum is the rest of the
    ;; addends.  We sweep through sum, trying to find a set of factors
    ;; common to all the addends of sum.
    (declare (xargs :measure (acl2-count sum)))
    (cond ((null factors)
           nil)
          ((eq (fn-symb sum) 'BINARY-+)
           (common-factors (intersection-equal factors (factors (fargn sum 1)))
                           (fargn sum 2)))
          (t
           (intersection-equal factors (factors sum)))))

  (defun simplify-terms-such-as-a+ab-rel-0-fn (sum)
    ;; If we can find a set of factors common to all the addends of sum,
    ;; we return an alist binding common to the product of these common
    ;; factors and binding quotient to (/ sum common).
    (if (eq (fn-symb sum) 'BINARY-+)
        (let ((common-factors (common-factors (factors (fargn sum 1))
                                              (fargn sum 2))))
          (if common-factors
              (let ((common (make-product common-factors))
                    (quotient (quotient common-factors sum)))
                (list (cons 'common common)
                      (cons 'quotient quotient)))
            nil))
      nil))

  (defthm simplify-terms-such-as-a+ab-=-0
    (implies (and (bind-free
                   (simplify-terms-such-as-a+ab-rel-0-fn sum)
                   (common quotient))
                  (case-split (acl2-numberp common))
                  (case-split (acl2-numberp quotient))
                  (case-split (equal sum
                                     (* common quotient))))
             (equal (equal sum 0)
                    (or (equal common 0)
                        (equal quotient 0)))))

  (thm (equal (equal (+ u (* u v)) 0)
        (or (equal u 0) (equal v -1))))
 })")

(defxdoc bitp
  :parents (numbers acl2-built-ins)
  :short "A recognizer for the set of bits, {0,1}"
  :long "<p>@('Bitp') returns @('t') if and only its argument is @('0') or
 @('1'), and @('nil') otherwise.</p>

 <p>Note that this is a predicate form of the @(see type-spec) declaration
 @('(TYPE BIT b)').</p>

 @(def bitp)")

(defxdoc book-compiled-file
  :parents (books-reference)
  :short "Creating and loading of compiled and expansion files for @(see books)"
  :long "<p>An effect of @(see compilation) is to speed up the execution of the
 functions defined in a book.  Compilation can also remove tail recursion, thus
 avoiding stack overflows.  The presence of compiled code for the functions in
 the book should not otherwise affect the performance of ACL2.  See @(see
 guard) for a discussion; also see @(see compilation).</p>

 <p>By default, the @(tsee certify-book) command compiles the book that it
 certifies.  see @(see certify-book) for how to control this behavior.</p>

 <p>By default, the @(tsee include-book) command loads the compiled file for
 the book.  The details of how this loading works are subtle, and do not need
 to be understood by most users.  The ACL2 source code contains an ``Essay on
 Hash Table Support for Compilation'' that explains such details for those
 interested.  All that users should generally need to know about this is that
 the compiled file is always the result of compiling a so-called ``expansion
 file'', which contains certain additional code besides the book itself.  The
 relevance to users of the expansion file is that it can be loaded if the
 compiled file is missing (except when @(':load-compiled-file t') is specified
 by the @(tsee include-book) form), and its existence is required in order for
 @(tsee include-book) to create a book's compiled file, as described below.</p>

 <p>Most users can skip the remainder of this documentation topic, which
 addresses the uncommon activity of using @(tsee include-book) to compile
 books.</p>

 <p>@('Include-book') can be made to compile a book by supplying its keyword
 argument @(':load-compiled-file') the value @(':comp').  However, a compiled
 file can only be produced if there is already an <i>expansion file</i> that is
 at least as recent as the book's @(see certificate).  Such a file, whose name
 happens to be the result of concatenating the string @('\"@expansion.lsp\"')
 to the book name (without the @('\".lisp\"') suffix), is created by @(tsee
 certify-book) when state global variable @(''save-expansion-file') has a
 non-@('nil') value.  That will be the case if ACL2 started up when environment
 variable @('ACL2_SAVE_EXPANSION') was @('t') (or any value that is not the
 empty string and whose @(tsee string-upcase) is not @('\"NIL\"')), until the
 time (if any) that @(''save-expansion-file') is assigned a different value by
 the user.  In most respects, the @(':comp') setting is treated exactly the
 same as @(':warn'); but after all events in the book are processed, the
 expansion file is compiled if a compiled file was not loaded, after which the
 resulting compiled file is loaded.</p>

 <p>One can thus, for example, compile books for several different host Lisps
 &mdash; useful when installing ACL2 executables at the same site that are
 built on different host Lisps.  A convenient way to do this in an environment
 that provides Gnu `make' is to certify the community books using the shell
 command ``@('make regression')'' in the @('acl2-sources/') directory, after
 setting environment variable @('ACL2_SAVE_EXPANSION') to @('t'), and then
 moving to the @('books') directory and executing the appropriate `make'
 commands to compile the books (targets @('fasl'), @('o'), and so on, according
 to the compiled file extension for the host Lisp).</p>

 <p>We conclude by saying more about the @(':load-compiled-file') argument of
 @(tsee include-book).  We assume that @(see state) global
 @(''compiler-enabled') has a non-@('nil') value; otherwise
 @(':load-compiled-file') is always treated as @('nil').</p>

 <p>We do not consider raw mode below (see @(see set-raw-mode)), which presents
 a special case: ACL2 will attempt to load the book itself whenever it would
 otherwise load the expansion or compiled file, but cannot (either because the
 @(':load-compiled-file') argument is @('nil'), or for each of the expansion
 and compiled files, either it does not exist or it is out of date with respect
 to the @('.cert') file).</p>

 <p>The @(':load-compiled-file') argument is not recursive: calls of
 @('include-book') that are inside the book supplied to @('include-book') use
 their own @(':load-compiled-file') arguments.  However, those subsidiary
 @('include-book') calls can nevertheless be sensitive to the
 @(':load-compiled-file') arguments of enclosing @('include-book') calls, as
 follows.  If @(':load-compiled-file') has value @('t'), then every subsidiary
 @('include-book') is required to load a compiled file.  Moreover, if a book's
 compiled file or expansion file is loaded in raw Lisp, then an attempt will be
 made to load the compiled file or expansion file for any @(tsee include-book)
 form encountered during that load.  If that attempt fails, then that load
 immediately aborts, as does its parent load, and so on up the chain.  If, when
 going up the chain, an @(tsee include-book) is aborted for which keyword
 argument @(':load-compiled-file') has value @('t'), then an error occurs.</p>

 <p>When loading a book's compiled file or expansion file, @('FILE'), it is
 possible to encounter an @(tsee include-book) form for a book that has no
 suitable compiled file or expansion file.  In that case, the load of @('FILE')
 is aborted at that point.  Similarly, the load of @('FILE') is aborted in the
 case that this @('include-book') form has a suitable compiled file or
 expansion file whose load is itself aborted.  Thus, whenever any
 @('include-book') aborts, so do all of its parent @('include-book')s, up the
 chain.  Such an abort causes an error when the @('include-book') form
 specifies a @(':load-compiled-file') value of @('t').</p>")

(defxdoc book-contents
  :parents (books-tour)
  :short "Restrictions on the forms inside @(see books)"
  :long "@({
  Example Book:

  ; This book defines my app function and the theorem that it is
  ; associative.  One irrelevant help lemma is proved first but
  ; it is local and so not seen by include-book.  I depend on the
  ; inferior book \"weird-list-primitives\" from which I get
  ; definitions of hd and tl.

  (in-package \"MY-PKG\")

  (include-book \"weird-list-primitives\")

  (defun app (x y) (if (consp x) (cons (hd x) (app (tl x) y)) y))

  (local
   (defthm help-lemma
     (implies (true-listp x) (equal (app x nil) x))))

  (defthm app-is-associative
    (equal (app (app a b) c) (app a (app b c))))
 })

 <p>The first form in a book must be @('(in-package \"pkg\")') where
 @('\"pkg\"') is some package name known to ACL2 whenever the book is
 certified.  The rest of the forms in a book are embedded event forms, i.e.,
 @(tsee defun)s, @(tsee defthm)s, etc., some of which may be marked @(tsee
 local).  See @(see embedded-event-form).  The usual Common Lisp commenting
 conventions are provided.  Note that since a book consists of embedded event
 forms, we can talk about the ``@(tsee local)'' and ``non-local'' @(see events)
 of a book.</p>

 <p>Because @(tsee in-package) is not an embedded event form, the only @(tsee
 in-package) in a book is the initial one.  Because @(tsee defpkg) is not an
 embedded event form, a book can never contain a @(tsee defpkg) form.  Because
 @(tsee include-book) is an embedded event form, @(see books) may contain
 references to other @(see books).  This makes @(see books) structured
 objects.</p>

 <p>When the forms in a book are read from the file, they are read with @(tsee
 current-package) set to the package named in the @(tsee in-package) form at
 the top of the file.  The effect of this is that all symbols are @(see
 intern)ed in that package, except those whose packages are given explicitly
 with the ``::'' notation.  For example, if a book begins with @('(in-package
 \"ACL2-X\")') and then contains the form</p>

 @({
    (defun fn (x)
      (acl2::list 'car x))
 })

 <p>then @(tsee defun), @('fn'), @('x'), and @(tsee car) are all @(see
 intern)ed in the @('\"ACL2-X\"') package.  I.e., it is as though the following
 form were read instead:</p>

 @({
    (acl2-x::defun acl2-x::fn (acl2-x::x)
        (acl2::list 'acl2-x::car acl2-x::x)).
 })

 <p>Of course, @('acl2-x::defun') would be the same symbol as @('acl2::defun')
 if the @('\"ACL2-X\"') package imported @('acl2::defun').</p>

 <p>If each book has its own unique package name and all the names defined
 within the book are in that package, then name clashes between @(see books)
 are completely avoided.  This permits the construction of useful logical @(see
 world)s by the successive inclusion of many @(see books).  Although it is
 often too much trouble to manage several packages, their judicious use is a
 way to minimize name clashes.  Often, a better way is to use @('local'); see
 @(see local).</p>

 <p>How does @(tsee include-book) know the definitions of the packages used in
 a book, since @(tsee defpkg)s cannot be among the forms?  More generally, how
 do we know that the forms in a book will be admissible in the host logical
 @(see world) of an @(tsee include-book)?  See @(see certificate) for answers
 to these questions.</p>")

(defxdoc book-example
  :parents (books-tour)
  :short "How to create, certify, and use a simple book"
  :long "<p>Suppose you have developed a sequence of admissible @(see events)
 which you want to turn into a book.  We call this ``publishing'' the book.
 This note explains how to do that.</p>

 <p>A key idea of @(see books) is that they are ``incremental'' in the sense
 that when you include a book in a host logical @(see world), the @(see world)
 is incrementally extended by the results established in that book.  This is
 allowed only if every name defined by the incoming book is either new or is
 already identically defined.  See @(see redundant-events).  This is exactly
 the same problem faced by a programmer who wishes to provide a utility to
 other people: how can he make sure he doesn't create name conflicts?  The
 solution, in Common Lisp, is also the same: use packages.  While @(see books)
 and packages have a very tenuous formal connection (every book must start with
 an @(tsee in-package)), the creation of a book is intimately concerned with
 the package issue.  Having motivated what would otherwise appear as an
 unnecessary fascination with packages below, we now proceed with a description
 of how to publish a book.</p>

 <p>Just to be concrete, let's suppose you have already gotten ACL2 to accept
 the following sequence of @(see command)s, starting in the ACL2 initial @(see
 state).</p>

 @({
     (defpkg \"ACL2-MY-BOOK\"
             (union-eq *common-lisp-symbols-from-main-lisp-package*
                       *acl2-exports*))
     (in-package \"ACL2-MY-BOOK\")
     (defun app (x y)
       (if (consp x) (cons (car x) (app (cdr x) y)) y))
     (defun rev (x)
       (if (consp x) (app (rev (cdr x)) (list (car x))) nil))
     (defthm rev-app-hack
       (equal (rev (app a (list x))) (cons x (rev a))))
     (defthm rev-rev
       (implies (acl2::true-listp x) (equal (rev (rev x)) x)))
 })

 <p>Observe that the first form above defines a package (which imports the
 symbols defined in CLTL such as @(tsee if) and @(tsee cons) and the symbols
 used to @(see command) ACL2 such as @(tsee defun) and @(tsee defthm)).  The
 second form selects that package as the current one.  All subsequent forms are
 read into that package.  The remaining forms are just event forms: @(tsee
 defun)s and @(tsee defthm)s in this case.</p>

 <p>Typically you would have created a file with Emacs containing these forms
 and you will have submitted each of them interactively to ACL2 to confirm that
 they are all admissible.  That interactive verification should start in ACL2's
 initial @(see world) &mdash; although you might, of course, start your
 sequence of @(see events) with some @(tsee include-book)s to build a more
 elaborate @(see world).</p>

 <p>The first step towards publishing a book containing the results above is to
 create a file that starts with the @(tsee in-package) and then contains the
 rest of the forms.  Let's call that file @('\"my-book.lisp\"').  The name is
 unimportant, except it must end with @('\".lisp\"').  If there are @(see
 events) that you do not wish to be available to the user of the book &mdash;
 e.g., lemmas you proved on your way toward proving the main ones &mdash; you
 may so mark them by enclosing them in @(tsee local) forms.  See @(see local).
 Let us suppose you wish to hide @('rev-app-hack') above.  You may also add
 standard Lisp comments to the file.  The final content of
 @('\"my-book.lisp\"') might be:</p>

 @({
   ; This book contains my app and rev functions and the theorem
   ; that rev is its own inverse.

     (in-package \"ACL2-MY-BOOK\")
     (defun app (x y)
       (if (consp x) (cons (car x) (app (cdr x) y)) y))
     (defun rev (x)
       (if (consp x) (app (rev (cdr x)) (list (car x))) nil))

   ; The following hack is not exported.
     (local (defthm rev-app-hack
       (equal (rev (app a (list x))) (cons x (rev a)))))

     (defthm rev-rev
       (implies (acl2::true-listp x) (equal (rev (rev x)) x)))
 })

 <p>The file shown above <b>is</b> the book.  By the time this note is done you
 will have seen how to certify that the book is correct, how to compile it, and
 how to use it in other host @(see world)s.  Observe that the @(tsee defpkg) is
 not in the book.  It cannot be: Common Lisp compilers disagree on how to treat
 new package definitions appearing in files to be compiled.</p>

 <p>Since a book is just a source file typed by the user, ACL2 provides a
 mechanism for checking that the @(see events) are all admissible and then
 marking the file as checked.  This is called certification.  To certify
 @('\"my-book.lisp\"') you should first get into ACL2 with an initial @(see
 world).  Then, define the package needed by the book, by typing the following
 @(tsee defpkg) to the ACL2 @(see prompt):</p>

 @({
  ACL2 !>(defpkg \"ACL2-MY-BOOK\"
                 (union-eq *common-lisp-symbols-from-main-lisp-package*
                           *acl2-exports*))
 })

 <p>Then execute the @(see command):</p>

 @({
  ACL2 !>(certify-book \"my-book\" 1 t) ; the `t' is in fact the default
 })

 <p>Observe that you do not type the @('\".lisp\"') part of the file name.  For
 purposes of @(see books), the book's name is @('\"my-book\"') and by the time
 all is said and done, there will be several extensions in addition to the
 @('\".lisp\"') extension associated with it.</p>

 <p>The @('1') tells @(tsee certify-book) that you acknowledge that there is
 one command in this ``certification @(see world)'' (namely the @(tsee
 defpkg)).  To use the book, any prospective host @(see world) must be extended
 by the addition of whatever @(see command)s occurred before certification.  It
 would be a pity to certify a book in a @(see world) containing junk because
 that junk will become the ``@(see portcullis)'' guarding entrance to the book.
 The @('t') above tells @(tsee certify-book) that you wish to compile
 @('\"my-book.lisp\"') also (but see @(see compilation) for an exception).
 @(tsee Certify-book) makes many checks but by far the most important and
 time-consuming one is that it ``proves'' every event in the file.</p>

 <p>When @(tsee certify-book) is done it will have created two new files.  The
 first will be called @('\"my-book.cert\"') and contains the ``@(see
 certificate)'' attesting to the admissibility of the @(see events) in
 @('\"my-book.lisp\"').  The @(see certificate) contains the @(tsee defpkg) and
 any other forms necessary to construct the certification @(see world).  It
 also contains so-called @(see book-hash) values that are used to help you keep
 track of which version of @('\"my-book.lisp\"') was certified.</p>

 <p>The second file that may be created by @(tsee certify-book) is the compiled
 version of @('\"my-book.lisp\"') and will have a name that is assigned by the
 host compiler (e.g., @('\"my-book.o\"') in GCL, @('\"my-book.fasl\"') in
 SBCL).  @(tsee Certify-book) will also load this object file.  When @(tsee
 certify-book) is done, you may throw away the logical @(see world) it created,
 for example by executing the @(see command) @(':u').</p>

 <p>To use the book later in any ACL2 session, just execute the event
 @('(include-book \"my-book\")').  This will do the necessary @(tsee defpkg),
 load the non-@(tsee local) @(see events) in @('\"my-book.lisp\"') and then may
 load the compiled code for the non-local functions defined in that file.
 Checks are made to ensure that the @(see certificate) file exists and
 describes the version of @('\"my-book.lisp\"') that is read.  The compiled
 code is loaded if and only if it exists and has a later write date than the
 source file (but see @(see compilation) for an exception).</p>

 <p>Since @(tsee include-book) is itself an event, you may put such forms into
 other @(see books).  Thus it is possible for the inclusion of a single book to
 lead to the inclusion of many others.  The @(see book-hash) information
 maintained in @(see certificate)s helps deal with the version control problem
 of the referenced @(see books).  I.e., if this version of @('\"my-book\"') is
 used during the certification of @('\"your-book\"'), then the @(see
 certificate) for @('\"your-book\"') includes the book-hash for this version of
 @('\"my-book\"').  If a later @('(include-book \"your-book\")') finds a
 version of @('\"my-book\"') with a different book-hash, an error is signaled.
 But book-hash values are not perfect and the insecurity of the host file
 system prevents ACL2 from guaranteeing the logical soundness of an @(tsee
 include-book) event, even for a book that appears to have a valid @(see
 certificate) (they can be forged, after all).  (See @(see certificate) for
 further discussion.)</p>

 <p>This concludes the example of how to create, certify and use a book.  If
 you wish, you could now review the @(see documentation) for book-related
 topics (see @(see books)) and browse through them.  They'll probably make
 sense in this context.  Alternatively, you could continue the ``guided tour''
 through the rest of the @(see documentation) of @(see books).  See @(see
 book-name), following the pointer given at the conclusion.</p>")

(defxdoc book-hash
  :parents (books)
  :short "Assigning ``often unique'' fingerprints to @(see books)"
  :long "<p>ACL2 provides a <i>certification</i> process for recording into a
 @(see certificate) file that a book is valid.  That process records certain
 ``fingerprint'' values for the book and the books that it includes, in order
 to give some confidence in the book's validity.  We call that value the
 ``book-hash'' for the book.  By default, a book-hash is an alist that records,
 for a given book (@('.lisp') file), its file size (in bytes) and its
 write-date.</p>

 <p>You can arrange for a book-hash to be a checksum instead of an alist, which
 gives a bit greater security, as illustrated in an example provided below.
 Nevertheless, the (default) use of book-hash alists may be worthwhile, in
 spite of the decreased security, because of faster times for @(tsee
 certify-book) and @(tsee include-book) when using book-hash alists instead of
 checksums.  If you want to use checksums, however, there are these two ways to
 do so.</p>

 <ul>

 <li>Before starting ACL2, set environment variable @('ACL2_BOOK_HASH_ALISTP')
 to @('NIL') (or @('nil'); actually it suffices that @(tsee string-upcase)
 applied to the indicated string is @('\"NIL\"')).  A common way to get this
 effect is to supply the argument @('ACL2_BOOK_HASH_ALISTP=NIL') with your
 @('\"make\"') command.</li>

 <li>After starting ACL2, set @(see state) global variable
 @('book-hash-alistp') to @('nil'), e.g.: @('(assign book-hash-alistp
 nil)').  (Set this variable to @('t') to revert to the default behavior:
 @('(assign book-hash-alistp t)').)</li>

 </ul>

 <p>The simple example below illustrates the potential weakness of book-hash
 alists (as compared to checksums), by exploiting the fact that these alists do
 not hash information in the @(see certificate) itself.  (Book-hash alists also
 ignore @(see portcullis) @(see command)s and the corresponding @('.acl2x')
 file, if any (see @(see set-write-acl2x)); but we don't exploit these facts in
 this example.)  We start with the following book, @('\"foo.lisp\"').</p>

 @({
 (in-package \"ACL2\")
 (make-event '(defun foo (x) (cons x x)))
 })

 <p>Now start ACL2 and run these commands.</p>

 @({
 (assign book-hash-alistp t) ; a no-op, by default
 (certify-book \"foo\")
 (read-file \"foo.cert\" state)
 (quit)
 })

 <p>Next, replace the contents of @('\"foo.cert\"') by the values in the list
 printed by the @('read-file') form above (hence, without the outer
 parentheses).  Further edit that file by twice changing @('(cons x x)') to
 @('x').  Also, update the write-date on the compiled file, e.g. with @('touch
 foo.dx64fsl'), if you want to avoid a warning.  Then submit @('(include-book
 \"foo\")').  We get the following contradictory behavior, without any
 warnings.</p>

 @({
 ACL2 !>(foo 3)
 (3 . 3)
 ACL2 !>(thm (equal (foo x) x))

 Q.E.D.

 Summary
 Form:  ( THM ...)
 Rules: ((:DEFINITION FOO))
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
 Prover steps counted:  5

 Proof succeeded.
 ACL2 !>
 })

 <p>For more information about connections between book-hash values and
 certification status, see @(see book-hash-mismatch).</p>")

(defxdoc book-hash-mismatch
  :parents (book-hash)
  :short "Deeming a book uncertified because of a @(see book-hash) mismatch"
  :long "<p>When @(tsee include-book) is invoked, the specified book may be
 considered uncertified by ACL2 because its @(see book-hash) &mdash; which by
 default is an alist specifying the book's size and write-date, but could be a
 checksum &mdash; does not match what was expected.  In that case you will
 typically see a warning such as the following, which instead will be an error
 if this occurs during certification.  In this topic, we explain how this
 warning can occur.</p>

 @({
 ACL2 Warning [Uncertified] in ( INCLUDE-BOOK \"foo\" ...):
 The certificate for \"/Users/kaufmann/temp/foo.lisp\" lists the book-
 hash of that book as ((:BOOK-LENGTH . 38) (:BOOK-WRITE-DATE . 3674050905)).
 But its book-hash is now computed to be
 ((:BOOK-LENGTH . 39) (:BOOK-WRITE-DATE . 3674050914)).
 See :DOC book-hash-mismatch.
 })

 <p>Probably the simplest way for such a mismatch to occur is if you change the
 book after certifying it, and then try to include the book.  In the example
 message displayed above, the book-hash for @('foo.lisp') stored into
 @('foo.cert') was 516310554.  But then @('foo.lisp') was edited (in this case,
 by adding a single newline character), and ACL2 complained because at
 @('include-book') time it computed a different book-hash for that book.</p>

 <p>The mismatch might occur on a book that is being included while including a
 superior book.  For example, suppose that the act of evaluating
 @('(include-book \"bk1\")') triggers evaluation of the event @('(include-book
 \"bk2\")') from @('bk1.lisp'), which similarly in turn causes evaluation of
 the event @('(include-book \"bk3\")') from @('bk2.lisp').  Now certify
 @('bk3.lisp'), then @('bk2.lisp'), and finally @('bk1.lisp').  So far, so
 good.  But now suppose we edit the lowest-level book, @('bk3.lisp').  We will
 likely get a warning (or error, if during book certification) such as the
 one displayed above when evaluating @('(include-book \"bk1\")'), complaining
 that the book-hash for @('bk3.lisp') has changed &mdash; followed by warnings
 complaining about inclusions of uncertified books by superior books.</p>

 <p>There are several ways for a book-hash in a @('.cert') file to become
 invalid, that is, to fail to match a recomputation of the book-hash when later
 including the book.  All such mismatches are due to a difference between the
 value of a book-hash at certification time and at later @('include-book')
 time; see @(see book-hash).</p>

 <p>Note that it is possible to mix alist and checksum book-hash values.  The
 key is to avoid conflicts between book-hash values stored for the same book in
 different @('.cert') files.  The following example works fine, because there
 is no such conflict: the book @('\"sub\"') is associated with a book-hash
 checksum in @('sub.cert'), which provides that same checksum as the book-hash
 value for @('\"sub\"') in @('top.cert'); and the book @('\"top\"') is
 associated with a book-hash alist in @('top.cert').</p>

 @({
 (certify-book \"sub\")
 (u)
 (assign book-hash-alistp t)
 (certify-book \"top\") ; contains the event (include-book \"sub\")
 (u)
 (include-book \"top\") ; no problem!
 })

 <p>However, if we instead evaluate the following forms in a fresh ACL2
 session, the last one causes an error, because a checksum serves as the
 book-hash for @('\"sub\"') in @('top.cert'), but at @('include-book') time the
 book-hash for @('\"sub\"') in @('sub.cert') is an alist, not a checksum.</p>

 @({
 (certify-book \"sub\")
 :u
 (certify-book \"top\") ; contains the event (include-book \"sub\")
 :u
 (assign book-hash-alistp t)
 (certify-book \"sub\") ; now the book-hash for sub is an alist
 :u
 ; Error: mismatch for book-hash values for \"sub\" in
 ;        new sub.cert and earlier top.cert.
 (include-book \"top\")
 })

 <p>That said, ACL2 does not care about the current value of state global
 @('book-hash-alistp') at @('include-book') time.  For example, the following
 works without error: ACL2 sees the checksum stored in @('sub.cert'), so at
 @('include-book') time it computes a checksum for the book @('\"sub\"'), not
 an alist, even though @(''book-hash-alistp') has value @('t').</p>

 @({
 (assign book-hash-alistp nil)
 (certify-book \"foo\")
 (assign book-hash-alistp t)
 (include-book \"foo\")
 })

 <p>We conclude by discussing a rather insidious book-hash mismatch that can
 occur when including a book using an ACL2 executable that differs from the
 executable that was used when certified the book.  Here is an example.
 Consider a book, @('\"foo.lisp\"'), containing the event @('(include-book
 \"tools/remove-hyps\" :dir :system)').  Suppose we have ACL2 executables
 @('acl2-cksum') and @('acl2-alist'), in different ACL2 directories.  Also
 suppose that we have certified (disjoint copies of) the @(see community-books)
 with each of these ACL2 executables, where we used
 @('ACL2_BOOK_HASH_ALISTP=NIL') in our @('\"make\"') command with
 @('acl2-cksum') but not with @('acl2-alist').  Now suppose we certify
 @('\"foo.lisp\"') using @('acl2-cksum') but then, in a session with
 @('acl2-alist'), we include that same book.  Then we will see a warning
 beginning as displayed below.  It complains that the book-hash required of
 @('books/tools/remove-hyps.cert') according to @('foo.cert') &mdash; which was
 created using @('acl2-cksum') &mdash; differs from the book-hash in the
 @('.cert') file of the copy of that book that is under the directory of the
 currently running ACL2, @('acl2-alist').</p>

 @({
 ACL2 Warning [Uncertified] in ( INCLUDE-BOOK \"foo\" ...):  After including
 the book \"/Users/smith/temp/foo.lisp\":

 -- its certificate requires the book \"/Users/smith/acl2/books/tools/remove-
 hyps.lisp\" with certificate annotations
   ((:SKIPPED-PROOFSP) (:AXIOMSP) (:TTAGS))
 and book hash 1958615726, but we have included a version of \"remove-hyps\"
 with certificate annotations
   ((:SKIPPED-PROOFSP) (:AXIOMSP) (:TTAGS))
 and book-hash ((:BOOK-LENGTH . 14650) (:BOOK-WRITE-DATE . 3656629263)),
 so book recertification is probably required;
 })")

(defxdoc book-name
  :parents (books-tour)
  :short "Conventions associated with book names"
  :long "@({
  Examples:
  \"list-processing\"
  \"/usr/home/smith/my-arith\"
 })

 <p>Book names are string constants that can be elaborated into file names.  We
 elaborate book names by concatenating the ``connected book directory'' (see
 @(see cbd)) string on the left and some ``extension,'' such as @('\".lisp\"'),
 on the right.  However, the connected book directory is not added if the book
 name itself already represents an absolute file name.  Furthermore, @(tsee
 include-book) and @(tsee certify-book) temporarily reset the connected book
 directory to be the directory of the book being processed.  This allows @(tsee
 include-book) forms to use file names without explicit mention of the
 enclosing book's directory.  This in turn allows @(see books) (together with
 those that they include, using @(tsee include-book)) to be moved between
 directories while maintaining their certification and utility.</p>

 <p>You may wish to read elsewhere for details of ACL2 file name conventions
 (see @(see pathname)), for a discussion of the filename that is the result of
 the elaboration described here (see @(see full-book-name)), and for details of
 the concept of the connected book directory (see @(see cbd)).  For details of
 how @(tsee include-book) (see @(see include-book)) and @(tsee certify-book)
 (see @(see certify-book)) use these concepts, see below.</p>

 <p>Often a book name is simply the familiar name of the file.  (See @(see
 full-book-name) for discussion of the notions of ``directory string,''
 ``familiar name,'' and ``extension''.  These concepts are not on the guided
 tour through @(see books) and you should read them separately.)  However, it
 is permitted for book names to include a directory or part of a directory
 name.  Book names never include the extension, since ACL2 must routinely tack
 several different extensions onto the name during @(tsee include-book).  For
 example, @(tsee include-book) uses the @('\".lisp\"'), @('\".cert\"') and
 possibly the @('\".o\"') or @('\".lbin\"') extensions of the book name.</p>

 <p>Book names are elaborated into full file names by @(tsee include-book) and
 @(tsee certify-book).  This elaboration is sensitive to the ``connected book
 directory.'' The connected book directory is an absolute filename string (see
 @(see pathname)) that is part of the ACL2 @(tsee state).  (You may wish to see
 @(see cbd) and to see @(see set-cbd) &mdash; note that these are not on the
 guided tour).  If a book name is an absolute filename string, ACL2 elaborates
 it simply by appending the desired extension to the right.  If a book name is
 a relative filename string, ACL2 appends the connected book directory on the
 left and the desired extension on the right.</p>

 <p>Note that it is possible that the book name includes some partial
 specification of the directory.  For example, if the connected book directory
 is @('\"/usr/home/smith/\"') then the book name @('\"project/task-1/arith\"')
 is a book name that will be elaborated to</p>

 @({
  \"/usr/home/smith/project/task-1/arith.lisp\".
 })

 <p>Observe that while the @(see events) in this @('\"arith\"') book are being
 processed the connected book directory will temporarily be set to</p>

 @({
  \"/usr/home/smith/project/task-1/\".
 })

 <p>Thus, if the book requires other @(see books), e.g.,</p>

 @({
  (include-book \"naturals\")
 })

 <p>then it is not necessary to specify the directory on which they reside
 provided that directory is the same as the superior book.</p>

 <p>This inheritance of the connected book directory and its use to elaborate
 the names of inferior @(see books) makes it possible to move @(see books) and
 their inferiors to new directories, provided they maintain the same relative
 relationship.  It is even possible to move with ease whole collections of
 @(see books) to different filesystems that use a different operating system
 than the one under which the original certification was performed.</p>

 <p>The @('\".cert\"') extension of a book, if it exists, is presumed to
 contain the most recent @(see certificate) for the book.  See @(see
 certificate) (or, if you are on the guided tour, wait until the tour gets
 there).</p>

 <p>See @(see book-contents) to continue the guided tour.</p>")

(defxdoc bookdata
  :parents (books)
  :short "An optional tool for writing out small files with meta-data about
 the books that are being certified."

  :long "<p>ACL2 provides a primitive capability for writing out a file of data
 associated with a book.  This information might be useful, for example, in
 building a database that allows you to search for name conflicts.  See @(see
 community-books) directory @('books/tools/book-conflicts/') for an application
 of this capability by Dave Greve.  If you use this capability and have ideas
 for enhancing it, please feel free to send them to the ACL2 developers.</p>

 <p>If the book has the name @('BK'), then the output file is named
 @('BK__bookdata.out').  That file is generated in the same directory as
 @('BK'), by certifying @('BK') when @(see state) global @(''write-bookdata')
 has a non-@('nil') value, for example as follows.</p>

 @({
  (assign write-bookdata t)
  (certify-book \"BK\" ...)
 })

 <p>The resulting file will contain a single form of the following shape,
 although not necessarily in the following order, according to the description
 that follows below.</p>

 @({
  (\"...BK.lisp\"
   :PKGS          pkgs-val
   :BOOKS         book-val
   :PORT-BOOKS    port-book-val
   :CONSTS        consts-val
   :PORT-CONSTS   port-consts-val
   :FNS           fns-val
   :PORT-FNS      port-fns-val
   :LABELS        labels-val
   :PORT-LABELS   port-labels-val
   :MACROS        macros-val
   :PORT-MACROS   port-macros-val
   :STOBJS        stobjs-val
   :PORT-STOBJS   port-stobjs-val
   :THEORIES      theories-val
   :PORT-THEORIES port-theories-val
   :THMS          thms-val
   :PORT-THMS     port-thms-val
 }))

 <p>The first entry in the form will always be the full book name (see @(see
 full-book-name)) of the certified book, @('BK').</p>

 <p>Subsequent values in the form are based on @(see events) introduced by
 including @('BK').  For various values of @('xxx') as described below,
 @('port-')<i>xxx</i>@('-val') is a list of values corresponding to @(see
 events) introduced in the certification @(see world) for @('BK') (see @(see
 portcullis)), and <i>xxx</i>@('-val') is a list of values corresponding to
 @(see events) introduced non-@(tsee local)ly by @('BK').  These lists include
 only ``top-level'' events, not those that are introduced by a book included
 either in @('BK') or its certification world.</p>

 <p>@('pkgs-val') is a list of names of packages introduced in the
 certification world (at the top level, not in an included book).  Note that no
 packages are introduced in a book itself, so no distinction is made between
 @('pkgs-val') and @('port-pkgs-val').  Both @('port-book-val') and
 @('book-val') are lists of full book names (see @(see full-book-name)) of
 included books.  The values associated with the other keywords are,
 themselves, association lists (see @(see alistp)) such that each key is a
 package name, which is associated with a list of @(see symbol-name)s for
 symbols in that package that are introduced for that keyword.  For example,
 @('fns-val') may be the alist</p>

 @({
  ((\"ACL2\" \"F1\" \"F2\")
   (\"MY-PKG\" \"G1\" \"G2\"))
 })

 <p>if the function symbols introduced in the book are @('F1') and @('F2') in
 the @('\"ACL2\"') package, as well as @('G1') and @('G2') in the
 @('\"MY-PKG\"') package.</p>

 <p>We next explain what kinds of symbols are introduced for each keyword
 @(':xxx').  Each such symbol would be associated with either the keyword
 @(':port-xxx') or the keyword @(':xxx') depending respectively on whether the
 symbol is introduced at the top level of the certification world for @('BK')
 or @('BK') itself.</p>

 <dl>

 <dt>@(':CONSTS')</dt>

 <dd>constant symbol introduced by @('defconst')</dd>

 <dt>@(':FNS')</dt>

 <dd>function symbol: introduced by @('defun'), @('defuns'), or @('defchoose'); or
 constrained (by an @(tsee encapsulate) event)</dd>

 <dt>@(':LABELS')</dt>

 <dd>symbol introduced by @('deflabel')</dd>

 <dt>@(':MACROS')</dt>

 <dd>macro name introduced by @('defmacro')</dd>

 <dt>@(':STOBJS')</dt>

 <dd>@('stobj') name introduced by @('defstobj') or @('defabsstobj')</dd>

 <dt>@(':THEORIES')</dt>

 <dd>theory name introduced by @('deftheory')</dd>

 <dt>@(':THMS')</dt>

 <dd>theorem name, which may be introduced by @('defthm') or a macro call
 expanding to a call of @('defthm'), such as see @(see defequiv) or
 @('defaxiom'); but may be introduced by @(tsee defpkg), for example, with
 name @('\"MYPKG-PACKAGE\"') if the package name is @('\"MYPKG\"')</dd>

 </dl>

 <p>Our hope is that people in the ACL2 community will generate and use this
 data to improve the ACL2 @(see community-books).  Here is an example
 illustrating how to generate bookdata files for those books as a byproduct of
 a regression run.  Below, we write @('{DIR}') as an abbreviation for the ACL2
 sources directory, and assume that this command is run from that directory.
 Of course, you may wish to use @('make') options like @('-j 8') and @('make')
 variable settings like @('ACL2={DIR}/my-saved_acl2'); see @(see
 books-certification) for details.</p>

 @({
   make regression-fresh \\
   ACL2_CUSTOMIZATION={DIR}/acl2-customization-files/bookdata.lisp
 })")

(defxdoc books
  :parents (acl2)
  :short "<i>Books</i> are files of ACL2 @(see events)&mdash;they are the main
way to split up large ACL2 developments into separate modules."

  :long "<p>This @(see documentation) topic is about ACL2 <a
 href='https://en.wikipedia.org/wiki/Source_code'>source code</a> files.
 However, there are also <a
 href='http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html#Books'>traditional,
 paper books</a> published about ACL2 and its applications.</p>

 <p>You will almost surely want to organize your own ACL2 work into books.
 They facilitate reuse, allow you to reload proofs more quickly, allow you to
 rebuild parts of your proof in parallel, and so forth.  You will also want to
 be aware of the many <i>community books</i>, which provide useful tools and
 lemmas to build upon.  See @(see community-books) for more information,
 including how to contribute.</p>

 <h3>Introduction</h3>

 <p>A <b>book</b> is a file of ACL2 forms.  Books are prepared entirely by the
 user of the system, i.e., they are <i>source files</i> not <i>object
 files</i>.  Some of the forms in a book are marked @(tsee local) and the
 others are considered ``non-local.''</p>

 <p>@(tsee Include-book) lets you load a book into any ACL2 @(see world).  A
 successful @('include-book') extends the logic of the host @(see world) by
 adding just the non-local @(see events) in the book.  Ordinarily, you might
 include a variety of books to load all of their definitions and rules.</p>

 <p>Successful book inclusion is consistency preserving, provided that the book
 itself is consistent, as discussed later.  However, @(tsee include-book)
 assumes the @(see events) in a book are valid, so if you include a book that
 contains an inconsistency (e.g., an inadmissible definition) then the
 resulting theory is inconsistent!</p>

 <p>@(tsee Certify-book) lets you <i>certify</i> a book to guarantee that its
 successful inclusion is consistency preserving.  During certification, both
 the @(tsee local) and non-local forms are processed.  This lets you mark as
 @(tsee local) any @(see events) you need for certification, but that you want
 to hide from users of the book&mdash;e.g., the hacks, crocks, and kludges on
 the way to a good set of @(see rewrite) rules.</p>

 <p>Certification can also <see topic='@(url compilation)'>compile</see> a book
 to speed up the execution of the functions defined within it.  The desire to
 compile books is largely responsible for the restrictions we put on the forms
 allowed in books.</p>

 <p>Extensive @(see documentation) is available on the various aspects of
 books.  We recommend that you read it all before using books.  It has been
 written so as to make sense when read in a certain linear sequence, called the
 ``guided tour'', though in general you may browse through it randomly.  If you
 are on the guided tour, you should next read @(see book-example).</p>")

(defxdoc books-certification
  :parents (community-books)
  :short "Instructions for certifying the ACL2 @(see community-books)."

  :long "<p>The <see topic='@(url community-books)'>Community Books</see>
provides a @('make') system, which is recommended for certifying a specified
subset of those books from the @('books/') directory of your ACL2 distribution.
Alternate instructions are however available for certifying from the top-leel
directory (see @(see books-certification-alt)).</p>

<p>Below are instructions for certifying various sets of books.  They all have
the following form in common.</p>

@({
cd /path/to/acl2-sources/books
make ACL2=/path/to/acl2-sources/saved_acl2 ...
})

<p>Success is indicated by a Linux exit status of 0.  Equivalently, there
should be no failures in the log.  Failures may be found by searching for
@('**'); for example, if output is redirected to a log file
@('make-regression.log'), then the following should provide no output.</p>

@({
fgrep -a '**' make-regression.log
})

<p>Unusual books that create output in the log file should not produce the
string @('**') except upon failure.</p>

<h3>Prerequisites</h3>

<p>We assume that you have already downloaded and installed ACL2 as per the <a
href=\"@(`(:raw *installation-url*)`)\">ACL2 installation instructions</a> on
the ACL2 home page.</p>

<p>We assume you know the path to your ACL2 executable.  Typically this is a
script named @('saved_acl2') in your @('acl2-sources') directory.</p>

<p>We assume the ACL2 @(see community-books) are installed in the @('books/')
subdirectory of your ACL2 distribution, as is the case when you have followed
the ACL2 installation instructions above.</p>

<p>The instructions below are suitable for ACL2 and all of its experimental
extensions, e.g., ACL2(p) and ACL2(r).</p>


<h3>A Basic Build</h3>

<p>In previous versions of ACL2, building the Community Books could take
several hours.  Starting in ACL2 6.4, the default build has been made <b>much
faster by excluding many books</b> by default.</p>

<p>The new default @('make') target, called @('basic'), now certifies only the
following, widely used books:</p>

<ul>
<li>arithmetic</li>
<li>arithmetic-3</li>
<li>arithmetic-5</li>
<li>@(see ihs)</li>
<li>misc</li>
<li>tools</li>
<li>@(see std)</li>
<li>@(see xdoc)</li>
<li>data-structures</li>
</ul>

<p>To certify these books, you should be able to run @('make') as follows.  The
@('-j 2') part of this command is suitable for a computer with two cores.  If
you have, e.g., a quad-core computer, you should probably use @('-j 4')
instead, and so on.</p>

@({
    $ cd /path/to/acl2-sources/books
    $ make ACL2=/path/to/acl2-sources/saved_acl2 -j 2 basic
})

<p>If you configure your @('PATH') so that you can launch ACL2 by typing
@('acl2'), then you may omit the @('ACL2=...') part.</p>


<h3>Certifying Additional Books</h3>

<p>We expect that most ACL2 users will want to certify at least the @('basic')
books described above.  But what if you also need other books?  One option is
to do a full build (see below).  But it is usually <b>much faster</b> to simply
tell @('make') to build the books you actually want to use.</p>

<p>There are @('make') targets corresponding to most directory names.  For
instance, to build the books under @('coi') and @('rtl') and @('cgen'), you can
run:</p>

@({
    $ cd /path/to/acl2-sources/books
    $ make ACL2=/path/to/acl2-sources/saved_acl2 coi rtl cgen -j 2
})

<p>For finer grained control, you can name individual books.  This works
particularly well for libraries that have @('top') books.  For instance, if you
want the @('rtl/rel9') library, you could run:</p>

@({
    $ cd /path/to/acl2-sources/books
    $ make ACL2=/path/to/acl2-sources/saved_acl2 rtl/rel9/lib/top.cert -j 2
})


<h3>Books that Require ACL2 Extensions</h3>

<p>Some books require experimental extensions to ACL2, such as ACL2(p) (see
@(see parallelism)) or ACL2(r) (see @(see real)) or their classic variants,
ACL2(cp) or ACL2(cr).  Other books require certain additional software.</p>

<p>The build system will automatically determine which kind of ACL2 you are
running (e.g., ACL2(c), ACL2(p), ACL2(r)) and, based on this, may prevent
incompatible books from being certified.  The output of @('make') should
explain which books are being excluded and why.</p>

<p>These kinds of book requirements are controlled by special @(see
build::cert_param) comments.</p>


<h3>Books that Require Quicklisp</h3>

<p>Some books, especially @(see interfacing-tools) like @(see oslib) and the
ACL2 @(see bridge), require certain Common Lisp libraries.</p>

<p>These libraries are now bundled with ACL2 via @(see quicklisp), so you
should not need to download anything extra to use them.  However, since these
libraries are not portable across all Lisps that can run ACL2, you must
<b>explicitly enable Quicklisp</b> by setting @('USE_QUICKLISP=1') in your
@('make') command if you want to use them.  For instance:</p>

@({
    make ACL2=... USE_QUICKLISP=1 doc/top.cert -j 4
})

<p>Using Quicklisp should definitely work for CCL and SBCL.  We have not tested
it with other Lisps, but there is some chance it will work with Lisps such as
Allegro, Lispworks, and CMUCL.  It will almost certainly <b>not</b> work for
GCL.</p>


<h3>Books that Require Additional Software</h3>

<p>Some other books based on @(see satlink) and @(see gl) require a SAT solver,
typically Glucose, to be installed; see @(see satlink::sat-solver-options) for
installation options.  The build system should automatically determine if
Glucose is installed on your system, and will avoid trying to certify these
books unless Glucose is present.</p>


<h3>Building the manual</h3>

<p>If you just want to get a copy of the ACL2+Books manual for local viewing,
you probably <b>don't need to build it yourself</b> because you can just <a
href='download/'>download</a> a copy.  If for some reason you do want to build
the manual yourself, you should be able to do so as follows, provided you have
installed glucose.  (That requirement might be eliminated in the future.)</p>

@({
    $ cd /path/to/acl2-sources/books
    $ make manual -j 4
})

<p>Building the manual should work on at least CCL and SBCL on Linux and Mac OS
X.  It <b>may not work</b> for some other OS/Lisp combinations.  In particular,
building the manual requires some features from @(see oslib) and @(see
quicklisp) that may not be available on some other Lisps.</p>

<p>The resulting web-based manual may be found in:</p>

@({
    acl2-sources/books/doc/manual/index.html
})

<p>See also @(see acl2::acl2-doc) for details about how to build your own
Emacs-based manual, and @(see xdoc::save) for general information about how to
build and distribute custom XDOC manuals, e.g., manuals that additionally
include your own unreleased books.</p>


<h3>A Full Build</h3>

<p>Building all of the books can take hours and is <b>usually unnecessary</b>.
That said, it is easy to do: just run @('make all'), e.g.,</p>

@({
    $ cd /path/to/acl2-sources/books
    $ make ACL2=/path/to/acl2-sources/saved_acl2 -j 2 all
})

<p>This actually still skips a few books that are very slow.  If you
<i>really</i> need to certify absolutely everything, you can run @('make
everything'), but this will likely add hours to your build!</p>


<h3>Cleaning Up</h3>

<p>If you want to delete generated files, you can run @('make clean') to remove
certificates, compiled files, and build logs.</p>

<p>If you just want to remove the files in a particular subdirectory (and its
subdirectories), you can go into that directory and then run the
@('build/clean.pl') script.  This will delete, starting from your current
directory, recursively, all certificates, logs, compiled files, etc.</p>

<p>Note that @('make clean') doesn't remove some files, e.g., @(see xdoc)
manuals.  To remove everything, try @('make moreclean').</p>


<h3>Debugging Failed Certifications</h3>

<p>If a book fails to certify, you may want to try certifying it in an
interactive session.  The most reliable way to do this is to replicate the
environment and commands that the build system used.  This information can be
found at the top of the @('[bookname].cert.out') file.  For instance:</p>

@({
    ;; foo.cert.out
    -*- Mode: auto-revert -*-
    ...
    Environment variables:
    ACL2_CUSTOMIZATION=NONE                 ;; <-- first configure your
    ACL2_SYSTEM_BOOKS=/path/to/acl2/books   ;;     environment to match
    ACL2=/path/to/saved_acl2                ;;     these settings
    ...
    Temp lisp file:
    (acl2::value :q)                 ;; <--- then submit these commands to
    (acl2::in-package \"ACL2\")      ;;      $ACL2 to debug the failure
    ...                              ;;      interactively
    --- End temp lisp file ---
})

<p>Some other notes/tips:</p>

<ul>

<li>Make sure the ACL2 image you run is the same as the one listed as ACL2 in
those environment variables!</li>

<li>You may wish to set the environment variables for only the duration of your
ACL2 session by using the \"env\" command.</li>

<li>You may wish to edit some of the commands for better debugging purposes;
e.g. you may modify the @(see set-inhibit-output-lst) command, or insert a
@(see set-debugger-enable) command, etc.</li>

<li>If you don't want your session to exit after a successful certification,
replace the last form @('(er-progn (time$ (certify-book ...') with just the
@('(time$ (certify-book ...))') part.</li>

</ul>


<h3>Further Resources</h3>

<p>The build system is largely based on @(see BUILD::cert.pl).  There is
considerable documentation about @('cert.pl'), and we highly recommend using it
to manage your own ACL2 projects.</p>

<p>The main build script is @('books/GNUmakefile').  There are many comments at
the start of this file, and you can also inspect it to see what targets are
available.</p>

<p>Please feel absolutely free to contact the @(see acl2-help) mailing list
with any questions about building the community books.</p>")

(defxdoc books-certification-alt
  :parents (books-certification)
  :short "Alternate instructions for certifying the @(see community-books),
 from the perspective of the @('acl2-sources') directory."

  :long "<p>WARNING: Parts of this documentation are probably obsolete, but parts
 are still relevant.  See @(see books-certification) as the primary source of
 information on how to certify the @(see community-books).</p>

 <p>For background on the ACL2 community books, see @(see community-books).
 Here we explain how to certify those books, or some of those books, with ACL2.
 We thank Bishop Brock, Jared Davis, and Sol Swords for their substantial
 contributions to this methodology.  See @('books/GNUmakefile'), in the
 community books, for more about ``Credits and History'', and for additional
 technical details not covered in this topic.</p>

 <p>For more information about installing ACL2, see the <a href=\"@(`(:raw
 *installation-url*)`)\">ACL2 installation instructions</a>.  For information
 about so-called ``classic ACL2 `make'-based certification'', which provides
 support for certifying directories of books but may disappear in a future ACL2
 release, see @(see books-certification-classic).</p>

 <p><b>The Basics</b></p>

 <p>We make the following assumptions.</p>

 <ul>
  <li>Gnu `make' is available on your system via the `make' command
 (rather than some other flavor of `make').  (Execute `@('make --version') to
 verify this.)</li>

  <li>You have built or obtained an ACL2 executable.</li>

  <li>The ACL2 @(see community-books) are installed in the @('books/')
 subdirectory of your ACL2 distribution, as is the case when you have followed
 the standard installation instructions.</li> </ul>

 <box><p>Note: All commands shown below are issued in the top-level (ACL2
 sources) directory of your ACL2 distribution.</p></box>

 <p>By default the ACL2 executable is file @('saved_acl2') in your ACL2
 sources directory, and you can issue the following command to the shell in
 order to do a ``regression run'' that certifies all of the community books
 using that executable.</p>

 @({
  make regression
 })

 <p>Better yet, save a log file in case there are problems, for example as
 follows.</p>

 @({
  (make regression) >& make-regression.log
 })

 <p>or perhaps better yet:</p>

 @({
  (time nice make regression) >& make-regression.log
 })

 <p>For the sake of brevity, below we'll skip mentioning any of `@('time')',
 `@('nice')', or `@('>& make-regression.log')'.  But saving a log file, in
 particular, is useful in case you encounter problems to report.</p>

 <p>If you fetched the community books using git, then you will have a
 directory @('books/workshops/') that is not necessary for certifying the other
 books.  If you want to skip certification of the books under
 @('books/workshops/'), use target `@('certify-books')' instead of target
 `@('regression')', for example as follows.</p>

 @({
  (time nice make certify-books) >& make-certify-books.log
 })

 <p>Whether you use target `@('regression')' or target `@('certify-books')',
 then for each book @('foo.lisp') whose certification is attempted, a file
 @('foo.cert.out') in the same directory will contain the output from the
 book's certification attempt.</p>

 <p>A regression run may take a few hours, but if you have a multiprocessing
 computer, you can speed it up by certifying some books in parallel, by
 providing a value for `make' option @('-j').  For example, if you have 8
 hardware threads then you might want to issue the following command.</p>

 @({
  make regression -j 8
 })

 <p><b>Specifying the ACL2 Executable</b></p>

 <p>If your ACL2 executable is not file @('saved_acl2') in the ACL2 sources
 directory, then you will need to specify that executable.  You can do that by
 setting variable @('ACL2'), either as an environment variable or, as displayed
 below, as a `make' variable.  Either way, you will need to avoid relative
 pathnames.  For example, the first two forms below are legal, but the third is
 not, assuming that @('my-acl2') is on your @('PATH') in a Unix-like
 environment (e.g., linux or MacOS) and that @('my-saved_acl2') is just a
 pathname relative to your ACL2 sources directory, which is not on your
 path.</p>

 @({
  make regression -j 8 ACL2=my-acl2
  make regression -j 8 ACL2=/u/smith/bin/acl2
  # The following only works if my-saved_acl2 is on your path (see above).
  make regression -j 8 ACL2=my-saved_acl2
 })

 <p><b>Cleaning</b></p>

 <p>You can delete files generated by book certification (including @('.cert')
 files, @('.out') files, compiled files, and more) by issuing the following
 command (again, in your ACL2 sources directory).</p>

 @({
  make clean-books
 })

 <p>If you want to cause such deletion and then do a regression, simply replace
 the `@('regression')' or `@('certify-books')' target by
 `@('regression-fresh')' or `@('certify-books-fresh')', respectively, for
 example as follows.  follows.</p>

 @({
  make -j 4 regression-fresh
  make -j 4 certify-books-fresh
 })

 <p>If however you only want to clean up generated files residing under a given
 directory (or its subdirectories, and recursively), you can issue the
 following command while standing in that directory, where @('DIR') is a
 pathname of your @('books') directory.</p>

 @({
  DIR/clean.pl
 })

 <p>For example, to clean up generated files under @('books/arithmetic'), you
 could do the following.</p>

 @({
  cd books/arithmetic
  ../clean.pl
  cd - # to return to the ACL2 sources directory, if you wish to do so
 })

 <p><b>Restricting to Specific Directories and Books</b></p>

 <p>You can specify which books you want certified by using any or all of the
 variables @('EXCLUDED_PREFIXES'), @('ACL2_BOOK_CERTS'), or
 @('ACL2_BOOK_DIRS').  First, the set of desired @('.cert') files is restricted
 to those that do not start with any string that is one of the words in the
 value of @('EXCLUDED_PREFIXES').  Then @('ACL2_BOOK_CERTS') and
 @('ACL2_BOOK_DIRS'), if supplied, specify which books should be certified, as
 illustrated by the following example.</p>

 @({
  make -j 8 regression-fresh \\
   ACL2_BOOK_DIRS=\"symbolic paco\" \\
   ACL2_BOOK_CERTS=\" \\
    workshops/2006/cowles-gamboa-euclid/Euclid/ed6a.cert \\
    workshops/2006/cowles-gamboa-euclid/Euclid/ed4bb.cert \\
    \"
 })

 <p>Then all book in directories @('symbolic') and @('paco') will be certified,
 as will the books @('workshops/2006/cowles-gamboa-euclid/Euclid/ed6a.lisp')
 and @('workshops/2006/cowles-gamboa-euclid/Euclid/ed4bb.lisp').  Note that all
 pathnames should be relative to your community books directory; in particular,
 they should not be absolute pathnames.  Also notice the @('.cert') extension
 used in files supplied for @('ACL2_BOOK_CERTS').</p>

 <p>Alternatively, you may wish to invoke @('books/cert.pl') while standing in
 a directory under which you want to certify books.  This will certify not only
 those books, but all supporting books &mdash; even those not under the current
 directory &mdash; that do not have up-to-date @('.cert') files.  The following
 is a simple command to invoke that will certify all books in the current
 directory, where if the @('books/') directory is not on your path, you will
 need to provide a suitable filename, e.g. @('../../cert.pl') or
 @('~/acl2/books/cert.pl').</p>

 @({
  cert.pl -j 4 *.lisp
 })

 <p>Here is a more complex command, which illustrates a way to certify books in
 subdirectories (as well as the current directory), the use of provisional
 certification (see @(see provisional-certification)), and `make'-level
 parallelism (in this case specifying four parallel processes).</p>

 @({
  ACL2_PCERT=t cert.pl -j 4 `find . -name '*.lisp'`
 })

 <p>Note that with this approach, unlike classic ACL2 `make'-based
 certification (see @(see books-certification-classic), out-of-date @('.cert')
 files that are not under the current directory will also be built.  For
 documentation of @('cert.pl') invoke:</p>

 @({
  cert.pl -h
 })

 <p>See the top of @('cert.pl') for authorship and copyright information.</p>

 <p>Finally, we give a brief summary of how to use so-called ``classic ACL2
 `make'-based certification'' for community books; see @(see
 books-certification-classic) for details.  Note that support for this approach
 might be eliminated in a future ACL2 release.  We welcome comments from the
 ACL2 community about whether or not that would be a good thing to do.  See the
 discussion above about @('ACL2_BOOK_DIRS') for the ``modern'' way to
 accomplish the same thing.</p>

 <p>Many community book directories have a @('Makefile').  If you modify books
 only in such a directory, you can recertify by standing in that directory and
 issuing a `make' command.  This command can optionally specify an ACL2
 executable as well as parallelism, for example as follows, where the first
 line (@('make clean')) is optional.</p>

 @({
  make clean
  (time nice make -j 8 ACL2=my-acl2)
 })

 <p><b>ACL2 Customization Files</b></p>

 <p>By default, your acl2-customization file (see @(see acl2-customization)) is
 ignored by all flavors of ``@('make regression')''.  However, you can specify
 the use of an acl2-customization file by setting the value of environment
 variable @('ACL2_CUSTOMIZATION') to the empty string, indicating a default
 such file, or to the desired absolute pathname.  For example:</p>

 @({
  make regression ACL2_CUSTOMIZATION=''
  make regression ACL2_CUSTOMIZATION='~/acl2-customization.lisp'
 })

 <p><b>Regressions for Variants of ACL2</b></p>

 <p>The discussion above also pertains to using ACL2(p) (see @(see parallel))
 or ACL2(r) (see @(see real)), in which case the default is @('saved_acl2p') or
 @('saved_acl2r') respectively, rather than @('saved_acl2').  However, we
 recommend that you use ACL2, not ACL2(p), for your regression.  Then you can
 use ACL2(p) for your own proof developments.  However, if you want to use
 ACL2(p) or for your regression, see @(see
 waterfall-parallelism-for-book-certification).</p>

 <p><b>Provisional Certification</b></p>

 <p>To use provisional certification (see @(see provisional-certification)),
 supply @('ACL2_PCERT=t') with your `make' command.  Here is an example.</p>

 @({
  time nice make regression -j 4 ACL2_BOOK_DIRS=deduction ACL2_PCERT=t
 })

 <p><b>Miscellany</b></p>

 <p>Other control of the certification process may be found by perusing
 community books file @('books/make_cert').  In particular, the @('INHIBIT')
 variable may be set to a call of @(tsee set-inhibit-output-lst), for example
 as follows to obtain the output one would get by default in an (interactive)
 ACL2 session.</p>

 @({
  time nice make regression -j 4 ACL2_BOOK_DIRS=arithmetic \\
    INHIBIT='(set-inhibit-output-lst proof-tree)'
 })

 <p><b>Troubleshooting</b></p>

 <p>If you run into problems, you can get help by joining the @('acl2-help')
 email list (follow the link from the ACL2 home page) and sending a message to
 that list.  Also consider trying another version of GNU `make'; for example,
 we have found that versions 3.81 and 3.82 sometimes cause errors on Linux
 where version 3.80 does not.  Note however that Version 3.80 does not print
 certain informational messages that are printed by later versions.</p>")

(defxdoc books-certification-classic
  :parents (books-certification)
  :short "Classic ACL2 `make'-based certification of @(see books)"
  :long "<p>This @(see documentation) topic explains an approach to certifying
 directories of books, which we call ``classic ACL2 `make'-based
 certification''.</p>

 <p>Warning: The capability described in this section might be replaced at any
 time by a capability based on corresponding support for community books (see
 @(see books-certification)).  If you think that would be a hardship, please
 contact the ACL2 implementors.</p>

 <p>This topic discusses a way to certify a directory of books other than the
 ACL2 community books.  See @(see books-certification) for how to certify the
 set of ACL2 community @(see books).  There is also a section in that @(see
 documentation) topic, ``Restricting to Specific Directories and Books'', that
 provides an alternative to classic ACL2 `make'-based certification (as
 discussed in the present topic) for certifying specified sets of books.</p>

 <p>We assume here a familiarity with Unix/Linux `make'.  We also assume that
 you are using GNU `make' rather than some other flavor of `make'.  And
 finally, we assume, as is typically the case by following the standard
 installation instructions, that you install the ACL2 community books in the
 @('books/') subdirectory of your ACL2 distribution.  We will refer below to
 that directory as @('BOOKS').</p>

 <p>In summary: to use `make' to certify @(see books) under a given directory,
 you may create a simple Makefile in that directory (as explained below) so
 that when you stand in that directory, you can submit the command, `make', to
 certify those books.  If you have a multi-processor machine or the like, then
 you can use the `@('-j') flag `make'-level parallelism by specifying the
 number of concurrent processes.  For example:</p>

 @({
  make -j 4
 })

 <p>For each book @('foo.lisp'), a file @('foo.out') in the same directory as
 @('foo.lisp') will contain the output from the corresponding certification
 attempt.  If you have previously executed such a command, then you might first
 want to delete @(see certificate) files and other generated files by executing
 the following command.</p>

 @({
  make clean
 })

 <p>Note that when you run `make', then by default, the first error will cause
 the process to stop.  You can use @('make -i') to force `make' to ignore
 errors, thus continuing past them.  Or, use @('make -k') to keep going, but
 skipping certification for any book that includes another whose certification
 has failed.</p>

 <p>By default, your acl2-customization file (see @(see acl2-customization)) is
 ignored by such `make' commands.  However, you can specify the use of an
 acl2-customization file by setting the value of environment variable
 @('ACL2_CUSTOMIZATION') to the empty string, indicating a default such file,
 or to the desired absolute pathname.  For example:</p>

 @({
  make ACL2_CUSTOMIZATION=''
  make ACL2_CUSTOMIZATION='~/acl2-customization.lisp'
 })

 <p>We now discuss how to create makefiles to support `make' commands as
 discussed above.</p>

 <p>First we give five steps for creating a @('Makefile') to support
 certification of a directory of books, without subdirectories.  For examples
 of such Makefiles you can look in community book directories (which, however,
 might disappear in future versions of ACL2).</p>

 <blockquote><p>1. Include the file @('Makefile-generic') from the @('books/')
 subdirectory of your ACL2 sources directory, but first perhaps define the
 variable `@('ACL2')'.  Consider the following example.</p>

 @({
  ACL2 ?= /Users/john_doe/acl2/acl2-sources/saved_acl2
  include /Users/john_doe/acl2/acl2-sources/books/Makefile-generic
 })

 <p>In this example, you can omit the first line, because the default ACL2
 executable is file @('saved_acl2') in the directory immediately above the
 directory of the specified @('Makefile-generic') file.  Indeed, that is the
 common case.  Note the use of @('?=') instead of @('=') or @(':='), so that
 @('ACL2') can instead be defined by the environment or provided on the command
 line as part of the `make' command.</p>

 <p>2. (Optional; usually skipped.)  Set the @('INHIBIT') variable if you want
 to see more than the summary output.  For example, if you want to see the same
 output as you would normally see at the terminal, put this line in your
 Makefile after the `@('include')' lines.</p>

 @({
  INHIBIT = (assign inhibit-output-lst (list (quote proof-tree)))
 })

 <p>For other values to use for @('INHIBIT'), see @(see set-inhibit-output-lst)
 and see the original setting of @('INHIBIT') in
 @('books/Makefile-generic').</p>

 <p>3. Specify the books to be certified.  Normally, every file with extension
 @('.lisp') will be a book that you want to certify, in which case you can skip
 this step.  Otherwise, put a line in your @('Makefile') after the ones above
 that specifies the books to be certified.  The following example, from an old
 version of community books file @('books/finite-set-theory/osets/Makefile'),
 should make this clear.</p>

 @({
  BOOKS = computed-hints fast instance map membership outer primitives \\
          quantify set-order sets sort
 })

 <p>But better yet, use the extension @('.lsp') for any Lisp or ACL2 files that
 are not to be certified, so that the definition of @('BOOKS') can be
 omitted.</p>

 <p>4. Create @('.acl2') files for books that are to be certified in other than
 the initial ACL2 world (see @(see portcullis)).  For example, if you look in
 community books file @('books/arithmetic/equalities.acl2') you will see @(tsee
 defpkg) forms followed by a @(tsee certify-book) command, because it was
 determined that @(tsee defpkg) forms were necessary in the certification world
 in order to certify the @('equalities') book.  In general, for each
 @('<book-name>.lisp') whose certification requires a non-initial certification
 world, you will need a corresponding @('<book-name>.acl2') file that ends with
 the appropriate @(tsee certify-book) command.</p>

 <p>You also have the option of creating a file @('cert.acl2') that has a
 special role.  When file @('<book-name>.lisp') is certified, if there is no
 file @('<book-name>.acl2') but there is a file @('cert.acl2'), then
 @('cert.acl2') will be used as @('<book-name>.acl2') would have been used, as
 described in the preceding paragraph, except that the appropriate @(tsee
 certify-book) command will be generated automatically.  Thus, no
 @('certify-book') command should occur in @('cert.acl2').</p>

 <p>It is actually allowed to put raw lisp forms in a @('.acl2') file
 (presumably preceded by @(':q') or @('(value :q)') and followed by @('(lp)')).
 But this is not recommended; we make no guarantees about certification
 performed any time after raw Lisp has been entered in the ACL2 session.</p>

 <p>5. Generally, the next step is to include the following line after the
 `@('include')' of @('Makefile-generic') (see the first step above).</p>

 @({
  -include Makefile-deps
 })

 <p>This will cause `make' to create and then include a file @('Makefile-deps')
 that contains ``dependency'' lines needed by `make'.  If those dependencies
 are somehow flawed, it may be because you have @(tsee include-book) forms that
 are not truly including books, for example in multi-line comments
 (@('#|..|#')).  These will be ignored if preceded by a semicolon (@(';')), or
 if you add a line break after ``@('include-book').''  But instead of adding
 the `@('-include')' line above, you can create dependency lines yourself by
 running the command</p>

 @({
  make dependencies
 })

 <p>and pasting the result into the end of your @('Makefile'), and editing as
 you see fit.</p></blockquote>

 <p>This concludes the basic instructions for creating a @('Makefile') in a
 directory including books.  Here are some other capabilities offered by
 community books file @('books/Makefile-subdirs').  Not included below is a
 discussion of how to increase parallelism by avoiding the need to certify
 included books before certifying a given book; see @(see
 provisional-certification).</p>

 <p><b>Subdirectory Support</b></p>

 <p>There is support for using `make' to certify books in subdirectories.
 Consider the following example.</p>

 @({
  DIRS = pass1 bind-free floor-mod
  include ../Makefile-subdirs
 })

 <p>This indicates that we are to run `make' in subdirectories @('pass1/'),
 @('bind-free/'), and @('floor-mod/') of the current directory.</p>

 <p>You can combine this subdirectory support with the support already
 discussed for certifying books in the top-level directory.  Here is an
 example, which as of this writing is in community books file
 @('books/arithmetic-3/Makefile') contains the following lines.</p>

 @({
  arith-top: top all
  all: top

  DIRS = pass1 bind-free floor-mod
  include ../Makefile-subdirs
  include ../Makefile-generic

  -include Makefile-deps
 })

 <p>The `@('top')' target is defined in @('../Makefile-subdirs') to call `make'
 in each subdirectory specified in @('DIRS').  We have set the default target
 in the example above to a new name, @('arith-top'), that makes that @('top')
 target before making the `@('all')' target which, in turn, is the default
 target in any @('Makefile-generic'), and is responsible for certifying books
 in the current directory as discussed in the five steps displayed above.</p>

 <p>Use @('Makefile-psubdirs') instead of @('Makefile-subdirs') if
 certification of a book in a subdirectory never depends on certification of a
 book in a different subdirectory, because then the @('-j') option of `make'
 can allow subdirectories to be processed in parallel.</p>

 <p><b>Cleaning Up</b></p>

 <p>We note that there is a @('clean') target.  Thus,</p>

 @({
  make clean
 })

 <p>will remove generated files including @('.cert'), @('.out') files, and
 compiled files.</p>

 <p><b>System Books</b></p>

 <p>An environment variable @('ACL2_SYSTEM_BOOKS') is generally set
 automatically, so you can probably skip reading the following paragraph unless
 your attempt to certify books fails to locate those books properly.</p>

 <p>The environment variable @('ACL2_SYSTEM_BOOKS') can be set to the top-level
 directory of the ACL2 community books.  A Unix-style pathname, typically
 ending in @('books/') or @('books'), is permissible.  In most cases, your ACL2
 executable is a small script in which you can set this environment variable
 just above the line on which the actual ACL2 image is invoked, for
 example:</p>

 @({
  export ACL2_SYSTEM_BOOKS
  ACL2_SYSTEM_BOOKS=/home/acl2/v3-2/acl2-sources/books
 })

 <p>However, you can also set @('ACL2_SYSTEM_BOOKS') as a `make' variable, by
 setting it in your @('Makefile') before the first target definition, e.g.:</p>

 @({
  ACL2_SYSTEM_BOOKS ?= /home/acl2/v3-2/acl2-sources/books
 })

 <p><b>Compilation Support</b></p>

 <p>The file @('books/Makefile-generic') provides support for compiling books
 that are already certified (but see @(see compilation) for an exception).  For
 example, suppose that you have certified books using GCL as the host Lisp,
 resulting in compiled files with the @('.o') extension.  Now suppose you would
 like to compile the books for Allegro Common Lisp, whose compiled files have
 the @('.fasl') extension.  The following command will work if you have
 included @('books/Makefile-generic') in your @('Makefile').</p>

 @({
  make fasl
 })

 <p>In general, the compiled file extension for a Lisp supported by ACL2 will
 be a target name for building compiled files for all your books (after
 certifying the books, if not already up-to-date on certification).</p>

 <p>If you run into problems, you can get help by joining the @('acl2-help')
 email list (follow the link from the ACL2 home page) and sending a message to
 that list.  Also consider trying another version of GNU `make'; for example,
 we have found that versions 3.81 and 3.82 sometimes cause errors on Linux
 where version 3.80 does not.</p>")

(defxdoc books-reference
  :parents (books)
  :short "Reference guide for ACL2 functionality related to books, e.g.,
@(see include-book), @(see certify-book), @(see cbd), etc.")

(defxdoc books-tour
  :parents (books)
  :short "The <i>guided tour</i> of concepts related to ACL2 @(see books)."
  :long "<p>The tour begins with @(see book-example).</p>")

(defxdoc boole$
  :parents (numbers acl2-built-ins)
  :short "Perform a bit-wise logical operation on 2 two's complement integers"
  :long "<p>When integers @('x') and @('y') are viewed in their two's
 complement representation, @('(boole$ op x y)') returns the result of applying
 the bit-wise logical operation specified by @('op').  The following table is
 adapted from documentation for the analogous Common Lisp function
 @(`(:raw (clhs \"Body/f_boole.htm\" \"boole\"))`) in the @(`(:raw (clhs \"\"
 \"Common Lisp Hyperspec\"))`).  Note that the values of @('op') for
 @('boole$') are ACL2 constants, rather than corresponding values of @('op')
 for the Common Lisp function @('boole').</p>

 @({
  op               result
  -----------      ---------
  *boole-1*        x
  *boole-2*        y
  *boole-andc1*    and complement of x with y
  *boole-andc2*    and x with complement of y
  *boole-and*      and
  *boole-c1*       complement of x
  *boole-c2*       complement of y
  *boole-clr*      the constant 0 (all zero bits)
  *boole-eqv*      equivalence (exclusive nor)
  *boole-ior*      inclusive or
  *boole-nand*     not-and
  *boole-nor*      not-or
  *boole-orc1*     or complement of x with y
  *boole-orc2*     or x with complement of y
  *boole-set*      the constant -1 (all one bits)
  *boole-xor*      exclusive or
 })

 <p>The guard of @('boole$') specifies that @('op') is the value of one of the
 constants above and that @('x') and @('y') are integers.</p>

 <p>See any Common Lisp documentation for analogous information about Common
 Lisp function @('boole').</p>

 @(def boole$)")

(defxdoc boolean-listp
  :parents (booleanp lists acl2-built-ins)
  :short "Recognizer for a true list of booleans"
  :long "<p>The predicate @('boolean-listp') tests whether its argument is a
 @(tsee true-listp) of objects each or which satisfies @(tsee booleanp), i.e.,
 is @('t') or @('nil').</p>

 @(def boolean-listp)")

(defxdoc booleanp
  :parents (basics acl2-built-ins)
  :short "Recognizer for booleans"
  :long "<p>@('(Booleanp x)') is @('t') if @('x') is @('t') or @('nil'), and is
 @('nil') otherwise.</p>

 <p>See @(see generalized-booleans) for a discussion of a potential soundness
 problem for ACL2 related to the question: Which Common Lisp functions are
 known to return Boolean values?</p>

 @(def booleanp)")

(defxdoc bounders
  :parents (tau-system)
  :short "Intervals, bounder functions, and bounder correctness"
  :long "<code>
 <i>Bounder Forms 1 and 2</i>:
 (implies (and (tau-intervalp i1)
               ...
               (or (equal (tau-interval-dom i1) 'dom1-1)
                   ...)
               ...
               (in-tau-intervalp x1 i1)
               ...)
          (and (tau-intervalp (bounder-fn i1 ...))
               (in-tau-intervalp <i>target</i>
                                 (bounder-fn i1 ...))))
 </code>

 <p>where <i>target</i> is either @('(fn x1 ... y1 ...)') or @('(mv-nth 'n (fn
 x1 ... y1 ...))'), depending on whether we are in the <i>Form 1</i> or <i>Form
 2</i> case, respectively.  However, the shape above is meant just as a
 reminder.  Details are given below.</p>

 <p>This topic first explains the basic shape of <i>Bounder Form 1</i>.  Then
 it illustrates <i>Bounder Form 2</i>.  Finally, it deals briefly with proving
 bounder correctness theorems.  The community book
 @('tau-bounders/elementary-bounders') contains bounders for various elementary
 functions including @(tsee +), @(tsee *), @(tsee /), @(tsee FLOOR), @(tsee
 MOD), @(tsee LOGAND), @(tsee LOGNOT), @(tsee LOGIOR), @(tsee LOGORC1), @(tsee
 LOGEQV), @(tsee LOGXOR), and @(tsee ASH).  You might look at or include this
 book to see more example theorems, to see how proofs of such theorems are
 managed, and to experiment with their effects on proving theorems involving
 arithmetic over finite or half-finite intervals.</p>

 <p>A bounder correctness theorem establishes that @('bounder-fn') is a
 ``bounder'' for the function @('fn').  That means that when trying to compute
 a tau for a call of @('fn') (or, in the case of <i>Form 2</i>, for the
 @('n')th component of the multiple-value vector returned by a call of @('fn'))
 the tau system can call @('bounder-fn') on the intervals containing certain
 arguments of @('fn').</p>

 <p>Let us start with an example.  Let @('fn') be the addition function, @('+')
 (actually, @(tsee binary-+)).  Consider the target term @('(+ x y)') and
 contemplate the question: if you know intervals containing @('x') and @('y'),
 say @('intx') and @('inty') respectively, what is an interval containing their
 sum?  The answer is pretty easy to state in English: the domain of the answer
 interval is the less restrictive of the domains of @('intx') and @('inty').
 The lower bound of the answer interval is the sum of the lower bounds of
 @('intx') and @('inty'), and the lower relation is the stronger of the lower
 relations of @('intx') and @('inty').  Analogous comments define the upper
 bound and relation of the answer interval.  So for example, if @('x') is an
 @('INTEGERP') such that @('0 <= x <= 10') and @('y') is a @('RATIONALP') such
 that @('0 < y <= 20'), then @('(+ x y)') is a @('RATIONALP') such that @('0 <
 (+ x y) <= 30').</p>

 <p>Defining this precisely is more tedious than describing it in English
 because one must make precise the notions of ``less restrictive'' domains,
 ``weaker'' relations, and the possibility that either or both of the bounds
 could be ``infinite.''  But we can easily imagine defining the function
 @('bounder-for-+') that returns the answer interval described, given @('intx')
 and @('inty').</p>

 <p>Then the following <i>Bounder Form 1</i> formula establishes the
 correctness of @('bounder-for-+') and allows the tau system to use it to
 produce bounds in the tau computed for @('+')-expressions:</p>

 @({
  (implies (and (tau-intervalp intx)
                (tau-intervalp inty)
                (in-tau-intervalp x intx)
                (in-tau-intervalp y inty))
           (and (tau-intervalp (bounder-for-+ intx inty))
                (in-tau-intervalp (+ x y)
                                  (bounder-for-+ intx inty))))
 })

 <p>For example, suppose we have a formula with the following hypotheses</p>

 @({
  (and (integerp a)
       (<= 0 a)
       (<= a 10)
       (rationalp b)
       (< 0 b)
       (<= b 20))
 })

 <p>and suppose the tau system encounters the term @('(+ a b)').  When the term
 is encountered, the tau for @('a') would include an @('INTEGERP') interval such
 that @('0 <= a <= 10') and the tau for @('b') would include a @('RATIONALP')
 interval such that @('0 < b <= 20').  In its most primitive configuration, the
 tau system would only know that the tau for @('(+ a b)') includes the
 recognizer @('RATIONALP') (and all that it is known to imply).  But after the
 bounder theorem above is proved and available as a @(':tau-system') rule the
 tau system would infer that @('(+ a b)') was in the @('RATIONALP') interval
 such that @('0 < (+ a b) <= 30').</p>

 <p>Thus, by defining bounder functions and proving them correct the user can
 give the tau system the ability to compute the bounds on function calls as a
 function of the known bounds on their actuals.</p>

 <p>It is sometimes useful to restrict the domains of the intervals to be
 considered.  For example, in bounding @('*')-expressions it is simplifying to
 restrict one's attention to intervals over the integers or rationals (and thus
 exclude the complex rationals so one need not think about the getting negative
 bounds by multiplying two ``positive'' complex rationals or how to ``round
 up'' from complex bounds to the rationals required by our intervals).</p>

 <p>If we were to define @('bounder-for-*') so that it works correctly to bound
 @('*')-expressions, but only for integer or rational arguments, its
 correctness theorem would be:</p>

 @({
  (implies (and (tau-intervalp intx)                             ; (a)
                (tau-intervalp inty)
                (or (equal (tau-interval-dom intx) 'INTEGERP)    ; (b)
                    (equal (tau-interval-dom intx) 'RATIONALP))
                (or (equal (tau-interval-dom inty) 'INTEGERP)
                    (equal (tau-interval-dom inty) 'RATIONALP))
                (in-tau-intervalp x intx)                        ; (c)
                (in-tau-intervalp y inty))
           (and (tau-intervalp (bounder-for-* intx inty))       ; (d)
                (in-tau-intervalp (* x y)                        ; (e)
                                  (bounder-for-* intx inty))))
 })

 <p>In this case, @('bounder-for-*') would be applied to the intervals for
 @('x') and @('y') only if those intervals were over the integers or the
 rationals.</p>

 <p>The above theorem for @('bounder-for-*') begins to suggest the general form
 of a bounder theorem and we will use it to explain the general form.</p>

 <p>The hypotheses of a bounder theorem must be a conjunction and the conjuncts
 must be partitionable into three parts, (a), (b), and (c).  The conclusion,
 must be a conjunction, must contain at least two conjuncts, (d) and (e), and
 is allowed to contain others that are simply ignored for purposes of bounders.
 (See the note below about why we allow but ignore additional conjuncts in the
 conclusion.)</p>

 <p>Part (a) introduces some distinct ``interval variables,'' here called
 ``ivars,'' that are known to denote intervals; for the example above, the
 ivars are @('intx') and @('inty').  Each hypothesis in part (a) is of the form
 @('(TAU-INTERVALP ivar)').</p>

 <p>Part (b) allows us to restrict the domains of some of the intervals.  Each
 hypothesis in part (b) must be a disjunction and each of the disjuncts must be
 of the form @('(EQUAL (TAU-INTERVAL-DOM ivar) 'dom)'), where @('ivar') is one
 of the interval variables and @('dom') is one of @('INTEGERP'),
 @('RATIONALP'), @('ACL2-NUMBERP'), or @('NIL').  It is not necessary to
 restrict every interval variable.  Indeed, part (b) may be empty, as in the
 theorem for @('bounder-for-+') above.</p>

 <p>Part (c) consists of a set of @('(IN-TAU-INTERVALP avar ivar)') hypotheses
 where each @('avar') is a variable and no two hypotheses in part (c) use the
 same @('avar') or @('ivar').  We call the set of all such @('avar') the
 ``actual variables'' or ``avars.''  The avars and ivars must be distinct.
 Part (c) sets up a correspondence between the avars and the ivars, each avar
 is in an interval denoted by one ivar.</p>

 <p>Part (d) introduces the name of the bounder function, here
 @('bounder-for-*'), and the order of its ivar arguments.  We see that
 @('bounder-for-*') takes two arguments and they correspond, in order, to the
 intervals containing @('x') and @('y').  Part (d) also establishes that the
 bounder function always returns an interval under hypotheses (a), (b), and
 (c).  Note that it is sometimes useful to return the ``universal interval''
 (one that contains everything) if you don't want to compute a better interval
 for some case; see @(tsee tau-intervalp) or @(tsee in-tau-intervalp).</p>

 <p>Part (e) introduces the name of the function being bounded, here @('*'),
 and the order of its arguments.  It establishes that the function being
 bounded really is bounded by the interval computed by the bounder function.
 In general, the function being bounded may take additional arguments.  It is
 possible that the function being bounded takes some arguments that do not
 affect the bounds of its output.</p>

 <p>Thus, parts (c) and (e) together establish a mapping between the actuals of
 a call of the function being bounded and the intervals to be supplied to the
 bounder.</p>

 <p>The parts identified above may be presented in any order and the literals
 constituting those parts may be mingled.  Thus, for example, here is another
 version of the theorem above that generates the same bounding information for
 the tau system.  In this version, the hypotheses and conclusions are
 rearranged, @('bounder-for-*') takes its arguments in the opposite order, and
 the theorem includes an additional conclusion.</p>

 @({
  (implies (and (tau-intervalp intx)                             ; (a)
                (or (equal (tau-interval-dom intx) 'INTEGERP)    ; (b)
                    (equal (tau-interval-dom intx) 'RATIONALP))
                (in-tau-intervalp x intx)                        ; (c)

                (tau-intervalp inty)                             ; (a)
                (or (equal (tau-interval-dom inty) 'INTEGERP)    ; (b)
                    (equal (tau-interval-dom inty) 'RATIONALP))
                (in-tau-intervalp y inty))
           (and (in-tau-intervalp (* x y)                        ; (e)
                                  (bounder-for-* inty intx))
                (tau-intervalp (bounder-for-* inty intx))        ; (d)))

                (or (equal (tau-interval-dom (bounder-for-* inty intx))
                           'INTEGERP)
                    (equal (tau-interval-dom (bounder-for-* inty intx))
                           'RATIONALP))
 })

 <p><i>Note on why bounder forms allow additional conjuncts in the
 conclusion</i>: It is often the case that one creates bounders by composing
 other bounders.  To prove compositional bounds correct one must often prove
 more than the mere correctness of the components.  For example, one might need
 to prove that the domain of the new bounding interval is @('INTEGERP') or
 otherwise restricted.  We allow such ``unnecessary'' conclusions simply to
 save the user the burden of stating multiple theorems.</p>

 <p><i>An Illustration of Bounder Form 2</i>: Suppose @('(quad i)') is defined
 so that truncates the integer @('i') to the largest multiple of 4 weakly below
 @('i') and, additionally, returns the remainder.  For example, @('(quad 26)')
 returns @('(mv 24 2)').  Then here are bounders for each of its return
 values:</p>

 @({
  (defun quad-bounds-0 (i)
    (cond ((and (tau-interval-lo i)
                (<= 0 (tau-interval-lo i)))
           (make-tau-interval 'integerp nil 0 nil (tau-interval-hi i)))
          (t (make-tau-interval nil nil nil nil nil))))

  (defun quad-bounds-1 (i)
    (cond ((and (tau-interval-lo i)
                (<= 0 (tau-interval-lo i)))
           (make-tau-interval 'integerp nil 0 nil 3))
          (t (make-tau-interval nil nil nil nil nil))))
 })

 <p>Note that the bounders assume @('i') is an @('INTEGERP') and return the
 universal interval when @('i') is not a natural.</p>

 <p>As noted in the discussion below about how to prove bounder correctness
 theorems, proving these bounders correct will require an arithmetic book,
 e.g.,</p>

 @({
  (include-book \"arithmetic-5/top\" :dir :system)
 })

 <p>Here then are two bounder correctness theorems of <i>Form 2</i>:</p>

 @({
  (defthm quad-bounds-0-correct
    (implies (and (tau-intervalp i)
                  (equal (tau-interval-dom i) 'INTEGERP)
                  (in-tau-intervalp x i))
             (and (tau-intervalp (quad-bounds-0 i))
                  (in-tau-intervalp (mv-nth 0 (quad x))
                                    (quad-bounds-0 i))))
    :rule-classes :tau-system)

  (defthm quad-bounds-1-correct
    (implies (and (tau-intervalp i)
                  (equal (tau-interval-dom i) 'INTEGERP)
                  (in-tau-intervalp x i))
             (and (tau-intervalp (quad-bounds-1 i))
                  (in-tau-intervalp (mv-nth 1 (quad x)) (quad-bounds-1 i))))
    :rule-classes :tau-system)
 })

 <p>As noted above, if these bounders are to be used in constructing other
 bounders, we might include (in the first theorem) an additional concluding
 conjunct, such as</p>

 @({
  (equal (tau-interval-dom (quad-bounds-0 i)) 'INTEGERP)
 })

 <p>so that we can keep @('quad-bounds-0') disabled to allow us to use
 @('quad-bounds-0-correct') as a @(':rewrite') or other rule and still relieve
 hypotheses about the domain of the interval it produces.  These hypotheses
 would arise if some other verified bounder was called on the produced
 interval.  In addition, as noted below, we might replace the
 @(':rule-classes') above with</p>

 @({
  :rule-classes
   ((:rewrite)
    (:forward-chaining :trigger-terms ((quad-bounds-0 i))))
 })

 <p>Since the theorem is being stored as some kind of rule and since it
 satisfies the <i>Bounder Form 2</i> shape, it will additionally be stored as a
 @(':tau-system') rule.</p>

 <p><i>Note on proving bounder theorems</i>: Proving bounder theorems is just
 like proving any other arithmetic theorem and you will need whatever libraries
 are appropriate for the problem domain you are working in.  Do not expect the
 tau system to be of much use in proving bounder theorems.  A typical bounder
 theorem might require you to prove a subgoal like @('(< (fn x y) (g
 (tau-interval-hi int1) int2))').  But tau deals with inequalities relating
 terms to constants, e.g., @('(< ... 16)').  A bounder theorem is a sort of
 ``metatheorem'' about <i>how to construct</i> bounded intervals from other
 bounded intervals.  So when you undertake to define a bounder and prove it
 correct, go into the project with your eyes open!</p>

 <p>But bounder functions can be broadly divided into two classes, those
 defined in terms of arithmetic on the interval bounds and those defined in
 terms of other bounders.  For example, given that</p>

 @({
  (LOGXOR x y) = (LOGNOT (LOGEQV x y))
 })

 <p>an interval for bounding @('LOGXOR') can be constructed by composing the
 constructions of intervals for @('LOGEQV') and @('LOGNOT').  So some bounder
 correctness proofs will involve direct manipulation of arithmetic inequalities
 and others might involve appeal to the correctness of other bounders,
 depending on how the new bounder is defined.</p>

 <p>Regardless of which style of bounder we are dealing with, we have found it
 useful to prove the basic theorems relating the tau interval accessors to
 @(tsee MAKE-TAU-INTERVAL), e.g.,</p>

 @({
  (equal (tau-interval-dom (make-tau-interval dom lo-rel lo hi-rel hi)) dom)
 })

 <p>and then disable those functions to avoid seeing excessive @('car')s and
 @('cdr')s.</p>

 <p>When dealing with bounders defined in the direct, arithmetic style, we tend
 to keep @(tsee TAU-INTERVALP) and @(tsee IN-TAU-INTERVALP) enabled so they
 unfold and expose the algebra.</p>

 <p>When dealing with bounders defined compositionally in terms of other
 verified bounders, we tend to keep @(tsee TAU-INTERVALP) and @(tsee
 IN-TAU-INTERVALP) disabled so we can rely on the previously proved bounder
 theorems as rewrite and forward chaining rules.</p>

 <p>Note that this last remark means that when you prove bounder correctness
 theorems you should include corollaries that are useful @(':rewrite') and
 possibly @(':forward-chaining') rules if you anticipate using that bounder in
 more complex ones.  We tend to trigger the forward chaining with the bounder
 expression itself, rather than one of the hypotheses.  For example in the rule
 above for @('bounder-for-*') we would include @('(:forward-chaining
 :trigger-terms ((tau-bounder-expt2 int2)))') and let the @('in-tau-intervalp')
 hypotheses select the free variables @('x') and @('y').</p>")

(defxdoc break$
  :parents (errors acl2-built-ins)
  :short "Cause an immediate Lisp break"
  :long "<p>ACL2 users are generally advised to avoid breaking into raw Lisp.
 Advanced users may, on occasion, see the need to do so.  Evaluating
 @('(break$)') will have that effect.  (Exception: @('break$') is disabled
 after evaluation of @('(set-debugger-enable :never)'); see @(see
 set-debugger-enable).)  @('Break$') returns @('nil').</p>

 @(def break$)")

(defxdoc break-lemma
  :parents (break-rewrite)
  :short "A quick introduction to breaking rewrite rules in ACL2"
  :long "@({
  Example:
  :brr t                          ; if you haven't done that yet
  :monitor (:rewrite lemma12) t   ; to install a break point on the
                                  ; rule named (:rewrite lemma12)
 })

 <p>ACL2 does not support Nqthm's @('break-lemma') but supports a very similar
 and more powerful break facility.  Suppose some proof is failing; apparently
 some particular rule is not being used and you wish to learn why.  Then you
 need the ACL2 @(see break-rewrite) facility.  See @(see break-rewrite) and all
 of its associated @(':')@(tsee doc) topics for details.  The following basic
 steps are required.</p>

 <p>(1) To enable the ``break rewrite'' feature, you must first execute</p>

 @({
  ACL2 !>:brr t
 })

 <p>at the top-level of ACL2.  Equivalently, evaluate @('(brr t)').  @(see
 Break-rewrite) stays enabled until you disable it with @('(brr nil)').  When
 @(see break-rewrite) is enabled the ACL2 rewriter will run slower than normal
 but you will be able to @(see monitor) the attempts to apply specified
 rules.</p>

 <p>(2) Decide what @(see rune)s (see @(see rune)) you wish to @(see monitor).
 For example, you might want to know why @('(:rewrite lemma12 . 2)') is not
 being used in the attempted proof.  That, by the way, is the name of the
 second rewrite rule generated from the event named @('lemma12').</p>

 <p>The command</p>

 @({
  ACL2 !>:monitor (:rewrite lemma12 . 2) t
 })

 <p>will install an ``unconditional'' break point on that rule.  The ``@('t')''
 at the end of the command means it is unconditional, i.e., a break will occur
 every time the rule is tried.  ACL2 supports conditional breaks also, in which
 case the @('t') is replaced by an expression that evaluates to non-@('nil')
 when you wish for a break to occur.  See @(see monitor).  The above keyword
 command is, of course, equivalent to</p>

 @({
  ACL2 !>(monitor '(:rewrite lemma12 . 2) t)
 })

 <p>which you may also type.  You may install breaks on as many rules as you
 wish.  You must use @(tsee monitor) on each rule.  You may also change the
 break condition on a rule with @(tsee monitor).  Use @(tsee unmonitor) (see
 @(see unmonitor)) to remove a rule from the list of @(see monitor)ed
 rules.</p>

 <p>(3) Then try the proof again.  When a @(see monitor)ed rule is tried by the
 rewriter you will enter an interactive break, called @(see break-rewrite).
 See @(see break-rewrite) for a detailed description.  Very simply, @(see
 break-rewrite) lets you inspect the context of the attempted application both
 before and after the attempt.  When @(see break-rewrite) is entered it will
 print out the ``target'' term being rewritten.  If you type @(':go') @(see
 break-rewrite) will try the rule and then exit, telling you (a) whether the
 rule was applied, (b) if so, how the target was rewritten, and (c) if not, why
 the rule failed.  There are many other commands.  See @(see brr-commands).</p>

 <p>(4) When you have finished using the @(see break-rewrite) feature you
 should disable it to speed up the rewriter.  You can disable it with</p>

 @({
  ACL2 !>:brr nil
 })

 <p>The list of @(see monitor)ed rules and their break conditions persists but
 is ignored.  If you enable @(see break-rewrite) later, the list of @(see
 monitor)ed rules will be displayed and will be used again by rewrite.</p>

 <p>You should disable the @(see break-rewrite) feature whenever you are not
 intending to use it, even if the list of @(see monitor)ed rules is empty,
 because the rewriter is slowed down as long as @(see break-rewrite) is
 enabled.</p>

 <p>If you get a stack overflow, see @(see cw-gstack).</p>")

(defxdoc break-on-error
  :parents (trace acl2-built-ins)
  :short "Break when encountering a hard or soft error caused by ACL2"
  :long "@({
  General forms:
  (break-on-error t)    ; installs a trace causing a continuable error (break)
                        ;   when an error is invoked by ACL2.
  (break-on-error)      ; same as above
  (break-on-error :all) ; same as above, but even when inside the prover
  (break-on-error nil)  ; uninstall any above trace
 })

 <p>@('(Break-on-error)') generates a suitable trace of error functions.
 Evaluate @('(trace$)') after @('(break-on-error)') if you want to see the
 specific trace forms (which you can modify and then submit directly to
 @('trace$'), if you wish).  This @(see trace) should cause entry to the Lisp
 debugger whenever ACL2 calls its error routines, except for certain errors
 when inside the theorem prover, and also at those times if option :all is
 supplied.</p>

 <p>NOTE: For technical reasons, you may see some error messages more than
 once.</p>

 <p>Finally, note that you are welcome to define your own version of
 @('break-on-error') by modifying a copy of the source definition (search for
 ``@('(defmacro break-on-error')'' in ACL2 source file other-events.lisp).
 Please feel free to send your version of @('break-on-error') to the ACL2
 implementors, for possible inclusion into ACL2.</p>

 <p>@('Break-on-error') is implemented using ACL2 @(tsee trace$).  See @(see
 trace!) if you want an explanation of the ``@('TTAG NOTE')'' that is
 printed.</p>

 <p>The argument, if supplied, is evaluated and must evaluate to @('t'),
 @('nil'), or @(':all').</p>

 <p>Also see @(see set-debugger-enable) for how to get raw-Lisp backtrace
 information when an error occurs as a result of @('break-on-error'), or even
 of a raw Lisp error, by calling @('set-debugger-enable') with argument
 @(':bt'), @(':bt-break'), or @(':break-bt').  Note that for ACL2 errors (as
 opposed to raw Lisp errors), i.e. errors affected by @('break-on-error'), all
 three of those keyword values are treated equivalently (and, all are ignored
 for non-ANSI GCL; see @(see set-debugger-enable)).</p>")

(defxdoc break-rewrite
  :parents (debugging)
  :short "The read-eval-print loop entered to @(see monitor) rules"
  :long "<p>ACL2 allows the user to @(see monitor) the application of @(see
 rewrite), @(see definition), and @(see linear) rules.  When @(see monitor)ed
 rules are about to be tried by the rewriter, an interactive break occurs and
 the user is allowed to watch and, in a limited sense, control the attempt to
 apply the rule.  This interactive loop, which is technically just a call of
 the standard top-level ACL2 read-eval-print loop, @(tsee ld), on a ``@(see
 wormhole) @(see state)'' (see @(see wormhole)), is called ``break-rewrite.''
 While in break-rewrite, certain keyword commands are available for accessing
 information about the context in which the lemma is being tried.  These
 keywords are called break-rewrite ``commands''; see @(see brr-commands).</p>

 <p>For a related utility, see @(see dmr) (Dynamically Monitor Rewrites), which
 allows you to watch progress of the rewriter in real time.</p>

 <p>To abort from inside break-rewrite at any time, execute @(':')@(tsee
 a!).</p>

 <p>For further information, see the related @(':')@(tsee doc) topics listed
 below.</p>

 <p>It is possible to cause the ACL2 rewriter to @(see monitor) the attempted
 application of selected rules.  When such a rule is about to be tried, the
 rewriter evaluates its break condition and if the result is non-@('nil'),
 break-rewrite is entered.</p>

 <p>Break-rewrite permits the user to inspect the current @(see state) by
 evaluating break-rewrite commands.  Type @(':help') in break-rewrite to see
 what the break-rewrite commands are.  However, break-rewrite is actually just
 a call of the general ACL2 read-eval-print loop, @(tsee ld), on a certain
 @(see state) and the break-rewrite commands are simply aliases provided by
 @('ld-keyword-aliases') @(see table) (see @(see ld-keyword-aliases)).  See
 @(see ld) for details about this read-eval-print loop.  Thus, with a few
 exceptions, anything you can do at the ACL2 top-level can be done within
 break-rewrite.  For example, you can evaluate arbitrary expressions, use the
 keyword command hack, access @(see documentation), print @(see events), and
 even define functions and prove theorems.  However, the ``certain @(see
 state)'' upon which @(tsee ld) was called is a ``wormhole state'' (see @(see
 wormhole)) because break-rewrite is not allowed to have any effect upon the
 behavior of rewrite.  What this means, at a high level, is that break-rewrite
 operates on a copy of the @(see state) being used by rewrite and when
 break-rewrite exits the @(see wormhole) closes and the @(see state)
 ``produced'' by break-rewrite disappears.  For example, all invocations of
 @(tsee trace$) and @(tsee untrace$) that are made during a break at a @(see
 monitor)ed @(see rune) are undone when proceeding from that break.  Thus,
 break-rewrite lets you query the state of the rewriter and even do experiments
 involving proofs, etc., but these experiments have no effect on the ongoing
 proof attempt.  In particular:</p>

 <p>Note that the output from break-rewrite is sometimes abbreviated by
 default, such as for the term causing the break.  This can be controlled by
 setting the @(':term') evisc-tuple; see @(see set-evisc-tuple).  (Another
 option: use iprinting.  See @(see set-iprint).)  But as noted above, if you
 use @('set-evisc-tuple') from inside the break-rewrite @(see wormhole), its
 effect will disappear when you exit the break.  So you might want to issue a
 @('set-evisc-tuple') command from the top level, outside break-rewrite.</p>

 <p>When you first enter break-rewrite a simple herald is printed such as:</p>

 @({
  (3 Breaking (:rewrite lemma12) on (delta a (+ 1 j)):
 })

 <p>The integer after the open parenthesis indicates the depth of nested
 break-rewrite calls.  In this discussion we use @('3') consistently for this
 integer.  Unless you abort or somehow enter unbalanced parentheses into the
 script, the entire session at a given depth will be enclosed in balanced
 parentheses, making it easy to skip over them in Emacs.</p>

 <p>You then will see the break-rewrite @(see prompt):</p>

 @({
  3 ACL2 !>
 })

 <p>The leading integer is, again, the depth.  Because breaks often occur
 recursively it is convenient always to know the level with which you are
 interacting.</p>

 <p>You may type arbitrary commands as in the top-level ACL2 loop.  For
 example, you might type:</p>

 @({
  3 ACL2 !>:help
 })

 <p>or</p>

 @({
  3 ACL2 !>:pe lemma12
 })

 <p>More likely than typing a history or @(tsee disabledp) command, upon
 entering break-rewrite you will determine the context of the attempted
 application.  Here are some useful commands:</p>

 @({
  3 ACL2 >:target           ; the term being rewritten
  3 ACL2 >:unify-subst      ; the unifying substitution
  3 ACL2 >:path             ; the stack of goals pursued by the rewriter
                            ; starting at the top-level clause being simplified
                            ; and ending with the current application
 })

 <p>At this point in the interaction the system has not yet tried to apply the
 @(see monitor)ed rule.  That is, it has not tried to establish the hypotheses,
 considered the heuristic cost of backchaining, rewritten the right-hand side
 of the conclusion, etc.  When you are ready for it to try the rule you can
 type one of several different ``proceed'' commands.  The basic proceed
 commands are @(':ok'), @(':go'), and @(':eval').</p>

 @({
  :ok
 })

 <p>exits break-rewrite without further interaction.  When break-rewrite exits
 it prints ``@('3)')'', closing the parenthesis that opened the level @('3')
 interaction.</p>

 @({
  :go
 })

 <p>exits break-rewrite without further interaction, but prints out the result
 of the application attempt, i.e., whether the application succeeded, if so,
 what the @(':target') term was rewritten to, and if not why the rule was not
 applicable.</p>

 @({
  :eval
 })

 <p>causes break-rewrite to attempt to apply the rule but interaction at this
 level of break-rewrite resumes when the attempt is complete.  When control
 returns to this level of break-rewrite a message indicating the result of the
 application attempt (just as in @(':go')) is printed, followed by the @(see
 prompt) for additional user input.</p>

 <p>Generally speaking, @(':ok') and @(':go') are used when the break in
 question is routine or uninteresting and @(':eval') is used when the break is
 one that the user anticipates is causing trouble.  For example, if you are
 trying to determine why a lemma isn't being applied to a given term and the
 @(':target') of the current break-rewrite is the term in question, you would
 usually @(':eval') the rule and if break-rewrite reports that the rule failed
 then you are in a position to determine why, for example by carefully
 inspecting the @(':')@(tsee type-alist) of governing assumptions or why some
 hypothesis of the rule could not be established.</p>

 <p>It is often the case that when you are in break-rewrite you wish to change
 the set of @(see monitor)ed @(see rune)s.  This can be done by using
 @(':')@(tsee monitor) and @(':')@(tsee unmonitor) as noted above.  For
 example, you might want to @(see monitor) a certain rule, say
 @('hyp-reliever'), just when it is being used while attempting to apply
 another rule, say @('main-lemma').  Typically then you would @(see monitor)
 @('main-lemma') at the ACL2 top-level, start the proof-attempt, and then in
 the break-rewrite in which @('main-lemma') is about to be tried, you would
 install a @(see monitor) on @('hyp-reliever').  If during the ensuing
 @(':eval') @('hyp-reliever') is broken you will know it is being used under
 the attempt to apply @('main-lemma').</p>

 <p>However, once @('hyp-reliever') is being @(see monitor)ed it will be @(see
 monitor)ed even after @('main-lemma') has been tried.  That is, if you let the
 proof attempt proceed then you may see many other breaks on @('hyp-reliever'),
 breaks that are not ``under'' the attempt to apply @('main-lemma').  One way
 to prevent this is to @(':eval') the application of @('main-lemma') and then
 @(':')@(tsee unmonitor) @('hyp-reliever') before exiting.  But this case
 arises so often that ACL2 supports several additional ``flavors'' of proceed
 commands.</p>

 <p>@(':Ok!'), @(':go!'), and @(':eval!') are just like their counterparts
 (@(':ok'), @(':go'), and @(':eval'), respectively), except that while
 processing the rule that is currently broken no @(see rune)s are @(see
 monitor)ed.  When consideration of the current rule is complete, the set of
 @(see monitor)ed @(see rune)s is restored to its original setting.</p>

 <p>@(':Ok$'), @(':go$'), and @(':eval$') are similar but take an additional
 argument which must be a list of @(see rune)s.  An example usage of
 @(':eval$') is</p>

 @({
  3 ACL2 !>:eval$ ((:rewrite hyp-reliever))
 })

 <p>These three commands temporarily install unconditional breaks on the @(see
 rune)s listed, proceed with the consideration of the currently broken rule,
 and then restore the set of @(see monitor)ed rules to its original
 setting.</p>

 <p>Thus, there are nine ways to proceed from the initial entry into
 break-rewrite although we often speak as though there are two, @(':ok') and
 @(':eval'), and leave the others implicit.  We group @(':go') with @(':ok')
 because in all their flavors they exit break-rewrite without further
 interaction (at the current level).  All the flavors of @(':eval') require
 further interaction after the rule has been tried.</p>

 <p>To abort a proof attempt and return to the top-level of ACL2 you may at any
 time type @('(a!)') followed by a carriage return.  If you are not in a raw
 Lisp break, you may type @(':a!') instead.  The utility @('p!') is completely
 analogous to @('a!') except that it pops up only one @(tsee ld) level.  If you
 have just entered the break-rewrite loop, this will pop you out of that loop,
 back to the proof.  See @(see a!) and see @(see p!).</p>

 <p>We now address ourselves to the post-@(':eval') interaction with
 break-rewrite.  As noted, that interaction begins with break-rewrite's report
 on the results of applying the rule: whether it worked and either what it
 produced or why it failed.  This information is also printed by certain
 keyword commands available after @(':eval'), namely @(':wonp'),
 @(':rewritten-rhs') or (for @(see linear) rules) @(':poly-list'), and
 @(':failure-reason').  In addition, by using @(tsee brr@) you can obtain this
 information in the form of ACL2 data objects.  This allows the development of
 more sophisticated ``break conditions''; see @(see monitor) for examples.  In
 this connection we point out the macro form @('(ok-if term)').  See @(see
 ok-if).  This command exits break-rewrite if @('term') evaluates to
 non-@('nil') and otherwise does not exit.  Thus it is possible to define
 macros that provide other kinds of exits from break-rewrite.  The only way to
 exit break-rewrite after @(':eval') is @(':ok') (or, equivalently, the use of
 @(tsee ok-if)).</p>

 <p>Note that when inside break-rewrite, all @(see history) commands, such as
 @(':')@(tsee pe), show the @(see enable)d status of rules with respect to the
 the current point in the proof attempt.  For example, if you break while the
 prover is working on Subgoal 3, and the @(see hints) supplied for the proof
 specify @('(\"Subgoal 3\" :in-theory (disable foo))') for some rule @('foo'),
 then @(':')@(tsee pe) will indicate that @('foo') is @(see disable)d: even
 though @('foo') may be enabled globally, it is shown as disabled because it is
 disabled during Subgoal 3.  See subtopics of @(see history) for a list of all
 such history commands.  In addition to those commands, the function @(tsee
 disabledp) is also evaluated inside break-rewrite with respect to the current
 enabled state of the prover.</p>

 <p>ACL2 users who wish to know more about break-rewrite so that they can
 develop more convenient ways to @(see monitor) rules are encouraged to speak
 to J Moore.</p>

 <p>The rest of this @(see documentation) discusses a few implementation
 details of break-rewrite and may not be interesting to the typical user.</p>

 <p>There is no ACL2 function named break-rewrite.  It is an illusion created
 by appropriate calls to two functions named @('brkpt1') and @('brkpt2').  As
 previously noted, break-rewrite is @(tsee ld) operating on a @(see wormhole)
 @(see state).  One might therefore wonder how break-rewrite can apply a rule
 and then communicate the results back to the rewriter running in the external
 @(see state).  The answer is that it cannot.  Nothing can be communicated
 through a @(see wormhole).  In fact, @('brkpt1') and @('brkpt2') are each
 calls of @(tsee ld) running on @(see wormhole) @(see state)s.  @('Brkpt1')
 implements the pre-@(':eval') break-rewrite and @('brkpt2') implements the
 post-@(':eval') break-rewrite.  The rewriter actually calls @('brkpt1') before
 attempting to apply a rule and calls @('brkpt2') afterwards.  In both cases,
 the rewriter passes into the @(see wormhole) the relevant information about
 the current context.  Logically @('brkpt1') and @('brkpt2') are no-ops and
 @(tsee rewrite) ignores the @('nil') they return.  But while control is in
 them, the execution of @(tsee rewrite) is suspended and cannot proceed until
 the break-rewrite interactions complete.</p>

 <p>This design causes a certain anomaly that might be troubling.  Suppose that
 inside break-rewrite before @(':evaling') a rule (i.e., in the @('brkpt1')
 @(see wormhole) @(see state)) you define some function, @('foo').  Suppose
 then you @(':eval') the rule and eventually control returns to break-rewrite
 (i.e., to @('brkpt2') on a @(see wormhole) @(see state) with the results of
 the application in it).  You will discover that @('foo') is no longer defined!
 That is because the @(see wormhole) @(see state) created during your
 @('pre-:eval') interaction is lost when we exit the @(see wormhole) to resume
 the proof attempt.  The post-@(':eval') @(see wormhole) @(see state) is in
 fact identical to the initial pre-@(':eval') @(see state) (except for the
 results of the application) because @(tsee rewrite) did not change the
 external @(see state) and both @(see wormhole) @(see state)s are copies of it.
 A similar issue occurs with the use of @(see trace) utilities: all effects of
 calling @(tsee trace$) and @(tsee untrace$) are erased when you proceed from a
 break in the break-rewrite loop.</p>

 <p>There is a lot more to know about break-rewrite, most of which is fairly
 easy to learn from looking at the code, since it is all expressed in ACL2.
 Feel free to ask questions of J Moore.</p>")

(defxdoc breaks
  :parents (errors)
  :short "Common Lisp breaks"
  :long "@({
  Example:
  Broken at PROVE.  Type :H for Help.
  >>:Q

  ACL2 !>
 })

 <p>You may interrupt the system by typing various control character sequences.
 The precise sequences are determined by the host Lisp and operating system
 environment.  For example, in GCL and Allegro Common Lisp, a console interrupt
 is caused by typing ``@('ctrl-c')''.  If, however, the GCL or Allegro is
 running in an Emacs shell buffer, one must type ``ctrl-c ctrl-c''.</p>

 <p>If a break occurs, for example because of a bug in ACL2 or a user
 interrupt, the break will run a Common Lisp read-eval-print loop, not an ACL2
 read-eval-print loop.  This may not be obvious if the @(see prompt)s in the
 two loops are similar.  Because you are typing to a Common Lisp evaluator, you
 must be careful.  It is possible to damage your ACL2 state in irreparable ways
 by executing non-ACL2 Common Lisp.  It is even possible to disrupt and render
 inaccurate the interrupted evaluation of a simple ACL2 expression.</p>

 <p>For ACL2 built on most host Common Lisps, you will see the string @('[RAW
 LISP]') in the @(see prompt) at a break, to emphasize that one is inside a
 break and hence should quit from the break.  For some host Common Lisps, the
 top-level prompt also contains the string @('[RAW LISP]').  See @(see prompt)
 for how to control printing of that string.</p>

 <p>The most reliable way to return to the ACL2 top level is by executing the
 following command: @('(')@(tsee abort!)@(')').  Appropriate cleanup will then
 be done, which should leave you in an appropriate state.</p>

 <p>However, you may be able to quit from the break in the normal Lisp manner
 (as with @(':q') in GCL or CCL, @(':reset') in Allegro CL, and @('q') in CMU
 CL).  If this attempt to quit is successful, it will return you to the
 innermost ACL2 read-eval-print loop, with appropriate cleanup performed first.
 Note that if you are within a @(tsee brr) environment when the break occurs,
 quitting from the break will only return you to that environment, not to the
 top of ACL2's read-eval-print loop.</p>")

(defxdoc broken-link
  :parents (documentation)
  :short "Placeholder for link to documentation that resides in the community
 books"
  :long "<p>You may have attempted to access information about the ACL2 @(see
 community-books) while looking at the ACL2 User's Manual, which contains @(see
 documentation) only about the ACL2 <i>system</i>, and does not include
 documentation from the @(see community-books).  Please point your browser at
 the @(`(:raw (combined-manual-ref))`) (or if browsing in @(see ACL2-Doc),
 switch to that manual with meta-0 I) to access the desired topic.</p>

 <p>If you want information about the book where your missing topic is defined,
 see @(see broken-link-table).</p>")

(defxdoc broken-link-table
  :parents (broken-link)
  :short "Map @(see documentation) topics to the community books that define
 them"
  :long "<p>The table below maps topics to book locations that reside only in
 the ACL2+Books combined manual, not the ACL2 User's Manual.  For example, the
 entry</p>

 @({
 (b* \"[books]/std/util/bstar.lisp\")
 })

 <p>signifies that the topic @('B*') is documented in the community
 book @('std/util/bstar.lisp').</p>

 <p>@(`(:code *acl2-broken-links-alist*)`)</p>")

(defxdoc brr
  :parents (break-rewrite)
  :short "To enable or disable the breaking of rewrite rules"
  :long "@({
  Example:
  :brr t       ; enable
  :brr nil     ; disable

  General Form:
  (brr flg)
 })

 <p>where @('flg') evaluates to @('t') or @('nil').  This function modifies
 @(tsee state) so that the attempted application of certain rewrite rules are
 ``broken.'' ``@('Brr')'' stands for ``break-rewrite'' and can be thought of as
 a mode with two settings.  The normal mode is ``disabled.''</p>

 <p>For a more thorough introduction to the break rewrite system see @(see
 break-rewrite).</p>

 <p>When @('brr') mode is ``enabled'' the ACL2 rewriter monitors the attempts
 to apply certain rules and advises the user of those attempts by entering an
 interactive wormhole break.  From within this break the user can watch
 selected application attempts.  The user can also interact with the system
 during @('brr') breaks via @(tsee brr-commands).</p>

 <p>The rules monitored are selected by using the @(tsee monitor) and @(tsee
 unmonitor) commands.  It is possible to break a rune ``conditionally'' in the
 sense that an interactive break will occur only if a specified predicate is
 true of the environment at the time of the attempted application.  See @(see
 monitor) and see @(see unmonitor).</p>

 <p>Even if a non-empty set of rules has been selected, no breaks will occur
 unless @('brr') mode is enabled.  Thus, the first time in a session that you
 wish to monitor a rewrite rule, use @(':brr') @('t') to enable @('brr') mode.
 Thereafter you may select runes to be monitored with @(tsee monitor) and
 @(tsee unmonitor) with the effect that whenever monitored rules are tried (and
 their break conditions are met) an interactive break will occur.  Be advised
 that when @('brr') mode is enabled the rewriter is somewhat slower than
 normal.  Furthermore, that sluggishness persists even if no runes are
 monitored.  You may regain normal performance &mdash; regardless of what runes
 are monitored &mdash; by disabling @('brr') mode with @(':brr') @('nil').</p>

 <p>Why isn't @('brr') mode disabled automatically when no runes are monitored?
 More generally, why does ACL2 have @('brr') mode at all?  Why not just test
 whether there are monitored runes?  If you care about the answers, see @(see
 why-brr).</p>

 <p>BRR Mode and Console Interrupts: If the system is operating in @('brr')
 mode and you break into raw Lisp (as by causing a console interrupt or
 happening upon a signaled Lisp error; see @(see breaks)), you can return to
 the ACL2 top-level, outside any @('brr') environment, by executing
 @('(')@(tsee abort!)@(')').  Otherwise, the normal way to quit from such a
 break (for example @(':q') in GCL, @(':reset') in Allegro CL, and @('q') in
 CMU CL) will return to the innermost ACL2 read-eval-print loop, which may or
 may not be the top-level of your ACL2 session!  In particular, if the break
 happens to occur while ACL2 is within the @('brr') environment (in which it is
 preparing to read @(tsee brr-commands)), the abort will merely return to that
 @('brr') environment.  Upon exiting that environment, normal theorem proving
 is continued (and the @('brr') environment may be entered again in response to
 subsequent monitored rule applications).  Before returning to the @('brr')
 environment, ACL2 ``cleans up'' from the interrupted @('brr') processing.
 However, it is not possible (given the current implementation) to clean up
 perfectly.  This may have two side-effects.  First, the system may
 occasionally print the self-explanatory ``Cryptic BRR Message 1'' (or 2),
 informing you that the system has attempted to recover from an aborted
 @('brr') environment.  Second, it is possible that subsequent @('brr')
 behavior in that proof will be erroneous because the cleanup was done
 incorrectly.  The moral is that you should not trust what you learn from
 @('brr') if you have interrupted and aborted @('brr') processing during the
 proof.  These issues do not affect the behavior or soundness of the theorem
 prover.</p>")

(defxdoc brr-commands
  :parents (break-rewrite)
  :short "@(see Break-Rewrite) Commands"
  :long "<code>
 :a!             abort to ACL2 top-level
 :p!             pop one level (exits a top-level break-rewrite loop)
 :target         term being rewritten
 :unify-subst    substitution making :lhs equal :target
 :hyps           hypotheses of the rule
 :hyp i          ith hypothesis of the rule
 :lhs            left-hand side of rule's conclusion
 :rhs            right-hand side of rule's conclusion
 :type-alist     type assumptions governing :target
 :initial-ttree  ttree before :eval (see @(see ttree))
 :ancestors      negations of backchaining hypotheses being pursued
 :wonp           indicates whether application succeeded (after :eval)
 :rewritten-rhs  rewritten :rhs (after :eval) of a rewrite rule
 :poly-list      list of polynomials (after :eval) of a linear rule,
                   where the leading term of each is enclosed in an extra set
                   of parentheses
 :final-ttree    ttree after :eval (see @(see ttree))
 :failure-reason reason rule failed (after :eval)
 :path           rewriter's path from top clause to :target
 :frame i        ith frame in :path
 :top            top-most frame in :path
 :btm            bottom-most frame in :path
 :ok             exit break
 :go             exit break, printing result
 :eval           try rule and re-enter break afterwards
 :ok!            :ok but no recursive breaks
 :go!            :go but no recursive breaks
 :eval!          :eval but no recursive breaks
 :ok$ runes      :ok with runes monitored during recursion
 :go$ runes      :go with runes monitored during recursion
 :eval$ runes    :eval with runes monitored during recursion
 :help           this message
 :standard-help  :help message from ACL2 top-level
 </code>

 <p>@(see Break-rewrite) is just a call of the standard ACL2 read-eval-print
 loop, @(tsee ld), on a ``@(see wormhole)'' @(see state).  Thus, you may
 execute most commands you might normally execute at the top-level of ACL2.
 However, all @(see state) changes you cause from within @(see break-rewrite)
 are lost when you exit or @(':eval') the rule.  You cannot modify @(see
 stobj)s from within the break.  See @(see break-rewrite) for more details and
 see @(see ld) for general information about the standard ACL2 read-eval-print
 loop.  Also see @(see brr@) for a utility that can return a value for many of
 the keywords above, instead of merely printing to the screen.</p>

 <p>Note that if you are breaking on a @(see monitor)ed @(see linear) rule,
 several of the commands listed above do not apply: @(':lhs'), @(':rhs'),
 @(':initial-ttree'), and @(':final-ttree').  Moreover, @(':rewritten-rhs')
 also does not apply, but instead, @(':poly-list') shows the result of applying
 the linear lemma as a list of polynomials, implicitly conjoined.  The leading
 term of each polynomial is enclosed in an extra set of parentheses.</p>")

(defxdoc brr@
  :parents (break-rewrite)
  :short "To access context sensitive information within @(tsee break-rewrite)"
  :long "@({
  Example:
  (brr@ :target)      ; the term being rewritten
  (brr@ :unify-subst) ; the unifying substitution

  General Form:
  (brr@ :symbol)
 })

 <p>where @(':symbol') is one of the keywords displayed below.  This utility
 may be most useful for system hackers; see @(see brr-commands) for queries
 that are more at a user level.  In particular, keywords marked below with
 @('*') probably require an implementor's knowledge of the system to use
 effectively.  They are supported but not well documented.  More is said on
 this topic following the table.</p>

 @({
  :symbol             (brr@ :symbol)
  -------             ---------------------

  :target             the term to be rewritten.  This term is an
                      instantiation of the left-hand side of the
                      conclusion of the rewrite-rule being broken.
                      This term is in translated form!  Thus, if
                      you are expecting (equal x nil) -- and your
                      expectation is almost right -- you will see
                      (equal x 'nil); similarly, instead of (cadr a)
                      you will see (car (cdr a)).  In translated
                      forms, all constants are quoted (even nil, t,
                      strings and numbers) and all macros are
                      expanded.

  :unify-subst        the substitution that, when applied to :target,
                      produces the left-hand side of the rule being
                      broken.  This substitution is an alist pairing
                      variable symbols to translated (!) terms.

  :wonp               t or nil indicating whether the rune was
                      successfully applied.  (brr@ :wonp) returns
                      nil if evaluated before :EVALing the rule.

  :rewritten-rhs      the result of successfully applying the rewrite
                      rule or else nil if (brr@ :wonp) is nil.  The
                      result of successfully applying the rule is
                      always a translated (!) term and is never nil.

  :poly-list          the result of successfully applying the linear
                      rule or else nil if (brr@ :wonp) is nil.  This
                      result represents the list of polynomials
                      produced by the rule application.  The leading
                      term of each polynomial is enclosed in an extra
                      set of parentheses.

  :failure-reason     some non-nil lisp object indicating why the rule
                      was not applied or else nil.  Before the rule is
                      :EVALed, (brr@ :failure-reason) is nil.  After
                      :EVALing the rule, (brr@ :failure-reason) is nil
                      if (brr@ :wonp) is t.  Rather than document the
                      various non-nil objects returned as the failure
                      reason, we encourage you simply to evaluate
                      (brr@ :failure-reason) in the contexts of interest.
                      Alternatively, study the ACL2 function tilde-@-
                      failure-reason-phrase.

  :lemma           *  the rewrite rule being broken.  For example,
                      (access rewrite-rule (brr@ :lemma) :lhs) will
                      return the left-hand side of the conclusion
                      of the rule.

  :type-alist      *  a display of the type-alist governing :target.
                      Elements on the displayed list are of the form
                      (term type), where term is a term and type
                      describes information about term assumed to hold in
                      the current context.  (See also the documentation for
                      type-alist.)  The type-alist may be used to determine
                      the current assumptions, e.g., whether A is a CONSP.

  :ancestors       *  a stack of frames indicating the backchain history
                      of the current context.  The theorem prover is in
                      the process of trying to establish each hypothesis
                      in this stack.  Thus, the negation of each hypothesis
                      can be assumed false.  Each frame also records the
                      rules on behalf of which this backchaining is being
                      done and the weight (function symbol count) of the
                      hypothesis.  All three items are involved in the
                      heuristic for preventing infinite backchaining.
                      Exception:  Some frames are ``binding hypotheses''
                      (equal var term) or (equiv var (double-rewrite term))
                      that bind variable var to the result of rewriting
                      term.  The ACL2 source code has a definition
                      (defrec ancestor ...) that may provide some relevant
                      insight.

  :initial-ttree   *  the initial and (after :EVAL) final tag trees,
  :final-ttree        respectively.  (Tag trees are low-level data structures
                      that store lemmas used and other information, as
                      documented in topic TTREE.)

  :gstack          *  the current goal stack.  The gstack is maintained
                      by rewrite and is the data structure printed as the
                      current ``path.''  Thus, any information derivable
                      from the :path brr command is derivable from gstack.
                      For example, from gstack one might determine that
                      the current term is the second hypothesis of a
                      certain rewrite rule.
 })

 <p>In general @('brr@-expressions') are used in break conditions, the
 expressions that determine whether interactive breaks occur when @(see
 monitor)ed @(see rune)s are applied.  See @(see monitor).  For example, you
 might want to break only those attempts in which one particular term is being
 rewritten or only those attempts in which the binding for the variable @('a')
 is known to be a @(tsee consp).  Such conditions can be expressed using ACL2
 system functions and the information provided by @('brr@').  Unfortunately,
 digging some of this information out of the internal data structures may be
 awkward or may, at least, require intimate knowledge of the system functions.
 But since conditional expressions may employ arbitrary functions and macros,
 we anticipate that a set of convenient primitives will gradually evolve within
 the ACL2 community.  It is to encourage this evolution that @('brr@') provides
 access to the @('*')'d data.</p>")

(defxdoc building-acl2
  :parents (about-acl2)
  :short "How to build an ACL2 executable"
  :long "<p>To build an ACL2 executable, submit the following command while
 standing in the main ACL2 directory, where @('<my-lisp>') invokes your Lisp
 executable (default: @('ccl')).</p>

 @({
 make LISP=<my-lisp>
 })

 <p>You should find \"Initialization SUCCEEDED.\" near the end the of the log.
 Note: There may be ACL2 warnings, for example: \"ACL2 Warning [Skip-proofs]
 in....\".  These may be safely ignored.</p>

 <p>Note that you will want to certify @(see books) in order to take full
 advantage of ACL2.  See @(see books-certification).</p>")

(defxdoc built-in-clause
  :parents (rule-classes)
  :short "To build a clause into the simplifier"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 @({
  Example:
  (defthm acl2-count-abl
    (and (implies (and (true-listp x)
                       (not (equal x nil)))
                  (< (acl2-count (abl x))
                     (acl2-count x)))
         (implies (and (true-listp x)
                       (not (equal nil x)))
                  (< (acl2-count (abl x))
                     (acl2-count x))))
    :rule-classes :built-in-clause)
 })

 <p>A @(':built-in-clause') rule can be built from any formula other than
 propositional tautologies.  Roughly speaking, the system uses the list of
 built-in clauses as the first method of proof when attacking a new goal.  Any
 goal that is subsumed by a built in clause is proved ``silently.''</p>

 <p>ACL2 maintains a set of ``built-in'' clauses that are used to short-circuit
 certain theorem proving tasks.  We discuss this at length below.  When a
 theorem is given the rule class @(':built-in-clause') ACL2 flattens the @(tsee
 implies) and @(tsee and) structure of the @(':')@(tsee corollary) formula so
 as to obtain a set of formulas whose conjunction is equivalent to the given
 corollary.  It then converts each of these to clausal form and adds each
 clause to the set of built-in clauses.</p>

 <p>The example above (regardless of the definition of @('abl')) will build in
 two clauses,</p>

 @({
  {(not (true-listp x))
   (equal x nil)
   (< (acl2-count (abl x)) (acl2-count x))}
 })

 <p>and</p>

 @({
  {(not (true-listp x))
   (equal nil x)
   (< (acl2-count (abl x)) (acl2-count x))}.
 })

 <p>We now give more background.</p>

 <p>Recall that a clause is a set of terms, implicitly representing the
 disjunction of the terms.  Clause @('c1') is ``subsumed'' by clause @('c2') if
 some instance of @('c2') is a subset @('c1').</p>

 <p>For example, let @('c1') be</p>

 @({
  {(not (consp l))
   (equal a (car l))
   (< (acl2-count (cdr l)) (acl2-count l))}.
 })

 <p>Then @('c1') is subsumed by @('c2'), shown below,</p>

 @({
  {(not (consp x))
   ; second term omitted here
   (< (acl2-count (cdr x)) (acl2-count x))}
 })

 <p>because we can instantiate @('x') in @('c2') with @('l') to obtain a subset
 of @('c1').</p>

 <p>Observe that @('c1') is the clausal form of</p>

 @({
  (implies (and (consp l)
                (not (equal a (car l))))
           (< (acl2-count (cdr l)) (acl2-count l))),
 })

 <p>@('c2') is the clausal form of</p>

 @({
  (implies (consp l)
           (< (acl2-count (cdr l)) (acl2-count l)))
 })

 <p>and the subsumption property just means that @('c1') follows trivially from
 @('c2') by instantiation.</p>

 <p>The set of built-in clauses is just a set of known theorems in clausal
 form.  Any formula that is subsumed by a built-in clause is thus a theorem.
 If the set of built-in theorems is reasonably small, this little theorem
 prover is fast.  ACL2 uses the ``built-in clause check'' in four places: (1)
 at the top of the iteration in the prover &mdash; thus if a built-in clause is
 generated as a subgoal it will be recognized when that goal is considered, (2)
 within the simplifier so that no built-in clause is ever generated by
 simplification, (3) as a filter on the clauses generated to prove the
 termination of recursively @(tsee defun)'d functions and (4) as a filter on
 the clauses generated to verify the guards of a function.</p>

 <p>The latter two uses are the ones that most often motivate an extension to
 the set of built-in clauses.  Frequently a given formalization problem
 requires the definition of many functions which require virtually identical
 termination and/or guard proofs.  These proofs can be short-circuited by
 extending the set of built-in clauses to contain the most general forms of the
 clauses generated by the definitional schemes in use.</p>

 <p>The attentive user might have noticed that there are some recursive
 schemes, e.g., recursion by @(tsee cdr) after testing @(tsee consp), that ACL2
 just seems to ``know'' are ok, while for others it generates measure clauses
 to prove.  Actually, it always generates measure clauses but then filters out
 any that pass the built-in clause check.  When ACL2 is initialized, the clause
 justifying @(tsee cdr) recursion after a @(tsee consp) test is added to the
 set of built-in clauses.  (That clause is @('c2') above.)</p>

 <p>Note that only a subsumption check is made; no rewriting or simplification
 is done.  Thus, if we want the system to ``know'' that @(tsee cdr) recursion
 is ok after a negative @(tsee atom) test (which, by the definition of @(tsee
 atom), is the same as a @(tsee consp) test), we have to build in a second
 clause.  The subsumption algorithm does not ``know'' about commutative
 functions.  Thus, for predictability, we have built in commuted versions of
 each clause involving commutative functions.  For example, we build in
 both</p>

 @({
  {(not (integerp x))
   (< 0 x)
   (= x 0)
   (< (acl2-count (+ -1 x)) (acl2-count x))}
 })

 <p>and the commuted version</p>

 @({
  {(not (integerp x))
   (< 0 x)
   (= 0 x)
   (< (acl2-count (+ -1 x)) (acl2-count x))}
 })

 <p>so that the user need not worry whether to write @('(= x 0)') or @('(= 0
 x)') in definitions.</p>

 <p>@(':built-in-clause') rules added by the user can be enabled and
 disabled.</p>")

(defxdoc butlast
  :parents (lists acl2-built-ins)
  :short "All but a final segment of a list"
  :long "<p>@('(Butlast l n)') is the list obtained by removing the last @('n')
 elements from the true list @('l').  The following is a theorem
 (though it takes some effort, including lemmas, to get ACL2 to prove it).</p>

 @({
  (implies (and (integerp n)
                (<= 0 n)
                (true-listp l))
           (equal (length (butlast l n))
                  (if (< n (length l))
                      (- (length l) n)
                    0)))
 })

 <p>For related functions, see @(see take) and see @(see nthcdr).</p>

 <p>The @(see guard) for @('(butlast l n)') requires that @('n') is a
 nonnegative integer and @('lst') is a true list.</p>

 <p>@('Butlast') is a Common Lisp function.  See any Common Lisp documentation
 for more information.  Note: In Common Lisp the second argument of
 @('butlast') is optional, but in ACL2 it is required.</p>

 @(def butlast)")

(defxdoc caaaar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee caaar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc caaadr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee caadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc caaar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee caar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc caadar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cadar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc caaddr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee caddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc caadr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc caar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee car)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cadaar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cdaar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cadadr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cdadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cadar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cdar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc caddar
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cddar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cadddr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cdddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc caddr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cadr
  :parents (conses acl2-built-ins)
  :short "@(tsee car) of the @(tsee cdr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc calling-ld-in-bad-contexts
  :parents (ld)
  :short "Errors caused by calling @(tsee ld) in inappropriate contexts"
  :long "<p>The macro @(tsee ld) was designed to be called directly in the
 top-level ACL2 loop, although there may be a few occasions for calling it from
 functions.  ACL2 cannot cope with invocations of @(tsee ld) during the process
 of loading a compiled file for a book, so this is an error.</p>

 <p>To see how that can happen, consider the following book, where file
 @('const.lsp') contains the single form @('(defconst *foo* '(a b))').</p>

 @({
    (in-package \"ACL2\")
    (defttag t)
    (progn! (ld \"const.lsp\"))
 })

 <p>An attempt to certify this book will cause an error, but that particular
 error can be avoided, as discussed below.  If the book is certified, however,
 with production of a corresponding compiled file (which is the default
 behavior for @(tsee certify-book)), then any subsequent call of @(tsee
 include-book) that loads this compiled file will cause an error.  Again, this
 error is necessary because of how ACL2 is designed; specifically, this @(tsee
 ld) call would interfere with tracking of constant definitions when loading
 the compiled file for the book.</p>

 <p>Because including such a book (with a compiled file) causes an error, then
 as a courtesy to the user, ACL2 arranges that the certification will fail
 (thus avoiding a surprise later when trying to include the book).  The error
 in that case will look as follows.</p>

 @({
    ACL2 Error in LD:  It is illegal to call LD in this context.  See DOC
    calling-ld-in-bad-contexts.
 })

 <p>If you really think it is OK to avoid this error, you can get around it by
 setting @(see state) global variable @('ld-okp') to t: @('(assign ld-okp t)').
 You can then certify the book in the example above, but you will still not be
 able to include it with a compiled file.</p>")

(defxdoc canonical-pathname
  :parents (programming-with-state acl2-built-ins)
  :short "The true absolute filename, with soft links resolved"
  :long "<p>For the name @('fname') of a file, the form @('(Canonical-pathname
 fname nil state)') evaluates to a Unix-style absolute filename representing
 the same file as @('fname'), but generally without any use of soft links in
 the name.  (Below, we explain the qualifier ``generally''.)  If however the
 file indicated by @('fname') does not exist, @('(canonical-pathname fname nil
 state)') is @('nil').  Thus, @('canonical-pathname') can be used as one would
 use the raw Lisp function @('probe-file').</p>

 <p>The specification of @('(Canonical-pathname fname dir-p state)') when
 @('dir-p') is not @('nil') is similar, except that if the specified file
 exists but is not a directory, then the result is @('nil').</p>

 <p>The function @('canonical-pathname') has a guard of @('t'), though the
 second argument must be the ACL2 @(tsee state).  This function is introduced
 with the following properties.</p>

 @({
  (defthm canonical-pathname-is-idempotent
    (equal (canonical-pathname (canonical-pathname x dir-p state) dir-p state)
           (canonical-pathname x dir-p state)))
  (defthm canonical-pathname-type
    (or (equal (canonical-pathname x dir-p state) nil)
        (stringp (canonical-pathname x dir-p state)))
    :rule-classes :type-prescription)
 })

 <p>We use the qualifier ``generally'', above, because there is no guarantee
 that the filename will be canonical without soft links, though we expect this
 to be true in practice.  ACL2 attempts to compute the desired result and then
 checks that the input and result have the same Common Lisp ``@('truename')''.
 This check is expected to succeed, but if it fails then the input string is
 returned unchanged, and to be conservative, the value returned is @('nil') in
 this case if @('dir-p') is true.</p>")

(defxdoc car
  :parents (conses acl2-built-ins)
  :short "Returns the first element of a non-empty list, else @('nil')"
  :long "<p>Completion Axiom (@('completion-of-car')):</p>

 @({
  (equal (car x)
         (cond
          ((consp x)
           (car x))
          (t nil)))
 })

 <p>@(see Guard):</p>

 @({
  (or (consp x) (equal x nil))
 })

 <p>Notice that in the ACL2 logic, @('car') returns @('nil') for every @(see
 atom).</p>")

(defxdoc case
  :parents (basics acl2-built-ins)
  :short "Conditional based on if-then-else using @(tsee eql)"
  :long "@({
  Example Form:
  (case typ
    ((:character foo)
     (open file-name :direction :output))
    (bar (open-for-bar file-name))
    (otherwise
     (my-error \"Illegal.\")))
 })

 <p>is the same as</p>

 @({
  (cond ((member typ '(:character foo))
         (open file-name :direction :output))
        ((eql typ 'bar)
         (open-for-bar file-name))
        (t (my-error \"Illegal.\")))
 })

 <p>which in turn is the same as</p>

 @({
  (if (member typ '(:character foo))
      (open file-name :direction :output)
      (if (eql typ 'bar)
          (open-for-bar file-name)
          (my-error \"Illegal.\")))
 })

 <p>Notice the quotations that appear in the example above: @(''(:character
 foo)') and @(''bar').  Indeed, a @('case') expression expands to a @(tsee
 cond) expression in which each tested form is quoted, and @(tsee eql) is used
 as the test.</p>

 @({
  General Forms:
  (case expr
    (x1 val-1)
    ...
    (xk val-k)
    (otherwise val-k+1))

  (case expr
    (x1 val-1)
    ...
    (xk val-k)
    (t val-k+1))

  (case expr
    (x1 val-1)
    ...
    (xk val-k))
 })

 <p>where each @('xi') is either @(tsee eqlablep) or a true list of @(tsee
 eqlablep) objects.  The final @('otherwise') or @('t') case is optional.</p>

 <p>@('Case') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>")

(defxdoc case-match
  :parents (basics acl2-built-ins)
  :short "Pattern matching or destructuring"
  :long "@({
  General Form:
  (case-match x
    (pat1 dcl1 body1)
    ...
    (patk dclk bodyk))
 })

 <p>where @('x') is a variable symbol, the @('pati') are structural patterns as
 described below, the @('dcli') are optional @(tsee declare) forms and the
 @('bodyi') are terms.  Return the value(s) of the @('bodyi') corresponding to
 the first @('pati') matching @('x'), or @('nil') if none matches.</p>

 <p>Pattern Language:<br></br>

 With the few special exceptions described below, matching requires that the
 @(tsee cons) structure of @('x') be isomorphic to that of the pattern, down to
 the @(see atom)s in the pattern.  Non-symbol @(see atom)s in the pattern match
 only themselves.  Symbols in the pattern denote variables which match anything
 and which are bound by a successful match to the corresponding substructure of
 @('x').  Variables that occur more than once must match the same (@(tsee
 EQUAL)) structure in every occurrence.</p>

 @({
  Exceptions:
  &               Matches anything and is not bound.  Repeated
                    occurrences of & in a pattern may match different
                    structures.
  nil, t, *sym*   These symbols cannot be bound and match only their
                    global values.
  !sym            where sym is a symbol that is already bound in the
                    context of the case-match, matches only the
                    current binding of sym.
  'obj            Matches only itself.
 })

 <p>Some examples are shown below.</p>

 <p>Below we show some sample patterns and examples of things they match and do
 not match.</p>

 @({
  pattern       matches         non-matches
  (x y y)       (ABC 3 3)       (ABC 3 4)    ; 3 is not 4
  (fn x . rst)  (P (A I) B C)   (ABC)        ; NIL is not (x . rst)
                (J (A I))                    ; rst matches nil
  ('fn (g x) 3) (FN (H 4) 3)    (GN (G X) 3) ; 'fn matches only itself
  (& t & !x)    ((A) T (B) (C))              ; provided x is '(C)
 })

 <p>Consider the two binary trees that contain three leaves.  They might be
 described as @('(x . (y . z))') and @('((x . y) . z)'), where @('x'), @('y'),
 and @('z') are atomic.  Suppose we wished to recognize those trees.  The
 following @('case-match') would do:</p>

 @({
  (case-match tree
    ((x . (y . z))
     (and (atom x) (atom y) (atom z)))
    (((x . y) . z)
     (and (atom x) (atom y) (atom z))))
 })

 <p>Suppose we wished to recognize such trees where all three tips are
 identical.  Suppose further we wish to return the tip if the tree is one of
 those recognized ones and to return the number @('7') otherwise.</p>

 @({
  (case-match tree
    ((x . (x . x))
     (if (atom x) x 7))
    (((x . x) . x)
     (if (atom x) x 7))
    (& 7))
 })

 <p>Note that @('case-match') returns @('nil') if no @('pati') matches.  Thus
 if we must return @('7') in that case, we have to add as the final pattern the
 @('&'), which always matches anything.</p>")

(defxdoc case-split
  :parents (rewrite linear type-prescription definition meta forward-chaining)
  :short "Like force but immediately splits the top-level goal on the hypothesis"
  :long "<p>@('Case-split') is a variant of @(tsee force), which has similar
 special treatment in hypotheses of rules for the same @(see rule-classes) as
 for @('force') (see @(see force)).  This treatment takes place for rule
 classes @(':')@(tsee rewrite), @(':')@(tsee linear), @(':')@(tsee
 type-prescription), @(':')@(tsee definition), @(':')@(tsee meta) (actually in
 that case, the result of evaluating the hypothesis metafunction call), and
 @(':')@(tsee forward-chaining).</p>

 <p>When a hypothesis of a conditional rule (of one of the classes listed
 above) has the form @('(case-split hyp)') it is logically equivalent to
 @('hyp').  However it affects the application of the rule generated as
 follows: if ACL2 attempts to apply the rule but cannot establish that the
 required instance of @('hyp') holds in the current context, it considers the
 hypothesis true anyhow, but (assuming all hypotheses are seen to be true and
 the rule is applied) creates a subgoal in which that instance of @('hyp') is
 assumed false.  (There are exceptions, noted below.)</p>

 <p>For example, given the rule</p>

 @({
  (defthm p1->p2
    (implies (case-split (p1 x))
             (p2 x)))
 })

 <p>then an attempt to prove</p>

 @({
  (implies (p3 x) (p2 (car x)))
 })

 <p>can give rise to a single subgoal:</p>

 @({
  (IMPLIES (AND (NOT (P1 (CAR X))) (P3 X))
           (P2 (CAR X))).
 })

 <p>Unlike @(tsee force), @('case-split') does not delay the ``false case'' to
 a forcing round but tackles it more or less immediately.</p>

 <p>The special ``split'' treatment of @('case-split') can be disabled by
 disabling forcing: see @(see force) for a discussion of disabling forcing, and
 also see @(see disable-forcing).  Finally, we should mention that the rewriter
 is never willing to split when there is an @(tsee if) term present in the goal
 being simplified.  Since @(tsee and) terms and @(tsee or) terms are merely
 abbreviations for @(tsee if) terms, they also prevent splitting.  Note that
 @(tsee if) terms are ultimately eliminated using the ordinary flow of the
 proof (but see @(see set-case-split-limitations)), so @('case-split') will
 ultimately function as intended.</p>

 <p>When in the interactive @(see proof-builder), @('case-split') behaves like
 @('force').</p>

 @(def case-split)")

(defxdoc case-split-limitations
  :parents (miscellaneous)
  :short "Limiting the number of immediate subgoals"
  :long "@({
  Examples:
  ACL2 !>(case-split-limitations (w state))
  (500 100)
 })

 <p>With the setting above, which is the default, @('clausify') will not try
 subsumption/replacement if more than 500 clauses are involved.  Furthermore,
 the simplifier, as it sweeps over a clause, will inhibit further case splits
 when it has accumulated 100 subgoals.  To implement this inhibition, ACL2
 refuses to rewrite subsequent literals, although it continues to split on any
 @('IF') calls in those literals.</p>

 <p>The following example illustrates how the latter restriction &mdash;
 specifically, not rewriting subsequent literals to avoid further case splits
 &mdash; can work.  We define a (rather nonsensical) function whose body
 introduces several cases.</p>

 @({
 (defun f1 (a b c)
   (if a
       (if b (equal c 0) (equal c 1))
     (if b (equal c 2) (equal c 3))))

 (set-case-split-limitations '(500 10))

 (set-gag-mode nil)

 (thm (or (equal (f1 a b c) xxx)
          (equal (f1 d e f) yyy)
          (equal (f1 g h i) zzz))
      :hints ((\"Goal\" :in-theory (disable f1))
              (\"Goal'\" :in-theory (enable f1)))
      :otf-flg t)
 })

 <p>We show the output below.  The simplification of the original goal to Goal'
 replaces the original goal, which is the clause (i.e., disjunction) consisting
 of the single literal (i.e., term) shown above, to the clause consisting of
 three literals, namely, the list:</p>

 @({
 ; Goal', as a clause (disjunction of three literals)
 ((EQUAL (F1 A B C) XXX)
  (EQUAL (F1 D E F) YYY)
  (EQUAL (F1 G H I) ZZZ))
 })

 <p>That simplification is reflected in the value printed (as an implication)
 for Goal' in the output, below.  If we omit the call of @(tsee
 set-case-split-limitations) above, then we get 64 cases, from opening up the
 calls of @('f1') and splitting on the variables @('a'), @('b'), @('d'),
 @('e'), @('g'), and @('h').  But with the limit of 10 provided by
 set-case-split-limitations above, fewer cases are generated because rewriting
 of literals is inhibited, as explained below.  Here is the first part of the
 output for that limit of 10.</p>

 @({
 [Note:  A hint was supplied for our processing of the goal above.
 Thanks!]

 This simplifies, using trivial observations, to

 [Note:  A hint was supplied for our processing of the goal below.
 Thanks!]

 Goal'
 (IMPLIES (AND (NOT (EQUAL (F1 A B C) XXX))
               (NOT (EQUAL (F1 D E F) YYY)))
          (EQUAL (F1 G H I) ZZZ)).

 This simplifies, using the :definition F1 (if-intro), to the following
 thirteen conjectures.

 Subgoal 13
 (IMPLIES (AND A B (NOT (EQUAL (EQUAL C 0) XXX))
               (NOT (EQUAL (F1 D E F) YYY)))
          (EQUAL (F1 G H I) ZZZ)).
 })

 <p>Why, though, are there 13 cases, even though the limit was specified as 10?
 Initially, the first literal @('(EQUAL (F1 A B C) XXX)') was rewritten,
 splitting into four cases; and for each of those cases, the second literal was
 rewritten, splitting further; and so on.  However, the first time more than 10
 cases were generated was when there were 10 cases generated so far and a
 literal generated four cases &mdash; then since that one literal generated
 four cases, 4-1 = 3 cases were added to the 10 already generated.  From that
 point on, further rewriting of literals did not take place.</p>

 <p>In short: the first time a literal splits into enough cases so that the
 accumulated number of cases exceeds the limit, rewriting stops &mdash; but
 that last split can put us significantly past the limit specified.</p>

 <p>See @(see set-case-split-limitations) for a more general discussion.</p>")

(defxdoc cbd
  :parents (books-reference programming-with-state acl2-built-ins)
  :short "Connected book directory string"
  :long "@({
  Example:
  ACL2 !>:cbd
  \"/usr/home/smith/\"
 })

 <p>The connected book directory is a nonempty string that specifies a
 directory as an absolute pathname.  (See @(see pathname) for a discussion of
 file naming conventions.)  When @(tsee include-book) is given a relative book
 name it elaborates it into a full book name, essentially by appending the
 connected book directory string to the left and @('\".lisp\"') to the right.
 (For details, see @(see book-name) and also see @(see full-book-name).)
 Similarly, @(tsee ld) elaborates relative pathnames into full pathnames using
 the connected book directory string.  (The effect of the @('cbd') on @('ld')
 carries over to utilities that invoke @('ld') as well, notably, @(tsee
 rebuild).)  Furthermore, @(tsee include-book) and @(tsee ld) temporarily set
 the connected book directory to the directory string of the resulting full
 pathname so that references to files in the same directory may omit the
 directory.  See @(see set-cbd) for how to set the connected book directory
 string.</p>

 @({
  General Form:
  (cbd)
 })

 <p>This is a macro that expands into a term involving the single free variable
 @(tsee state).  It returns the connected book directory string.</p>

 <p>The connected book directory (henceforth called the ``@('cbd')'') is used
 by @(tsee include-book) to elaborate the supplied book name into a full book
 name (see @(see full-book-name)); similarly for @(tsee ld).  For example, if
 the @('cbd') is @('\"/usr/home/smith/\"') then the elaboration of the @(see
 book-name) @('\"project/task-1/arith\"') (to the @('\".lisp\"') extension) is
 @('\"/usr/home/smith/project/task-1/arith.lisp\"').  That @(see
 full-book-name) is what @(see include-book) opens to read the source text for
 the book.</p>

 <p>The @('cbd') may be changed using @(tsee set-cbd) (see @(see set-cbd)).
 Furthermore, during the processing of the @(see events) in a book, @(tsee
 include-book) sets the @('cbd') to be the directory string of the @(see
 full-book-name) of the book; similarly for @(tsee ld).  Thus, if the @('cbd')
 is @('\"/usr/home/smith/\"') then during the processing of @(see events)
 by</p>

 @({
  (include-book \"project/task-1/arith\")
 })

 <p>the @('cbd') will be set to @('\"/usr/home/smith/project/task-1/\"').  Note
 that if @('\"arith\"') recursively includes a sub-book, say @('\"naturals\"'),
 that resides on the same directory, the @(tsee include-book) event for it may
 omit the specification of that directory.  For example, @('\"arith\"') might
 contain the event</p>

 @({
    (include-book \"naturals\").
 })

 <p>In general, suppose we have a superior book and several inferior @(see
 books) which are included by @(see events) in the superior book.  Any inferior
 book residing on the same directory as the superior book may be referenced in
 the superior without specification of the directory.</p>

 <p>We call this a ``relative'' as opposed to ``absolute'' naming.  The use of
 relative naming is preferred because it permits @(see books) (and their
 accompanying inferiors) to be moved between directories while maintaining
 their @(see certificate)s and utility.  Certified @(see books) that reference
 inferiors by absolute file names are unusable (and rendered uncertified) if
 the inferiors are moved to new directories.</p>

 <p><i>Technical Note and a Challenge to Users:</i></p>

 <p>After elaborating the book name to a full book name, @(tsee include-book)
 opens a channel to the file to process the @(see events) in it.  In some host
 Common Lisps, the actual file opened depends upon a notion of ``connected
 directory'' similar to our connected book directory.  Our intention in always
 elaborating book names into absolute filename strings (see @(see pathname) for
 terminology) is to circumvent the sensitivity to the connected directory.  But
 we may have insufficient control over this since the ultimate file naming
 conventions are determined by the host operating system rather than Common
 Lisp (though, we do check that the operating system ``appears'' to be one that
 we ``know'' about).  Here is a question, which we'll pose assuming that we
 have an operating system that calls itself ``Unix.''  Suppose we have a file
 name, filename, that begins with a slash, e.g., @('\"/usr/home/smith/...\"').
 Consider two successive invocations of CLTL's</p>

 @({
  (open filename :direction :input)
 })

 <p>separated only by a change to the operating system's notion of connected
 directory.  Must these two invocations produce streams to the same file?  A
 candidate string might be something like
 @('\"/usr/home/smith/*/usr/local/src/foo.lisp\"') which includes some
 operating system-specific special character to mean ``here insert the
 connected directory'' or, more generally, ``here make the name dependent on
 some non-ACL2 aspect of the host's state.''  If such ``tricky'' name strings
 beginning with a slash exist, then we have failed to isolate ACL2 adequately
 from the operating system's file naming conventions.  Once upon a time, ACL2
 did not insist that the @('cbd') begin with a slash and that allowed the
 string @('\"foo.lisp\"') to be tricky because if one were connected to
 @('\"/usr/home/smith/\"') then with the empty @('cbd') @('\"foo.lisp\"') is a
 full book name that names the same file as @('\"/usr/home/smith/foo.lisp\"').
 If the actual file one reads is determined by the operating system's state
 then it is possible for ACL2 to have two distinct ``full book names'' for the
 same file, the ``real'' name and the ``tricky'' name.  This can cause ACL2 to
 include the same book twice, not recognizing the second one as
 redundant.</p>")

(defxdoc ccl-updates
  :parents (hons-and-memoization)
  :short "Updating Clozure Common Lisp (CCL)"
  :long "<p>Those who use ACL2 built on CCL, especially those who make
 compute-intensive use of ACL2's @(see hons-enabled) features, are advised to
 to stay plugged into the ``trunk'' or ``bleeding edge'' of CCL development.
 This is very easy to do by typing a few commands to a shell, for example
 standing above the target directory as follows, provided one has @('svn')
 working.</p>

 @({
   For linux:

     rm -rf ccl
     svn co http://svn.clozure.com/publicsvn/openmcl/trunk/linuxx8664/ccl

   For an x86 Macintosh running the Darwin OS:

     svn co http://svn.clozure.com/publicsvn/openmcl/trunk/darwinx8664/ccl

   To keep up to date, you may find it sufficient to do:

     cd ccl
     svn update

   Whether obtaining a fresh CCL or just updating, finally issue these
   commands.

     ./lx86cl64
     (rebuild-ccl :full t)
     (quit)
     ./lx86cl64
     (rebuild-ccl :full t)
     (quit)
 })")

(defxdoc cdaaar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee caaar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cdaadr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee caadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cdaar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee caar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cdadar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cadar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cdaddr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee caddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cdadr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cdar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee car)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cddaar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cdaar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cddadr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cdadr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cddar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cdar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cdddar
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cddar)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cddddr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cdddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cdddr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cddr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cddr
  :parents (conses acl2-built-ins)
  :short "@(tsee cdr) of the @(tsee cdr)"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc cdr
  :parents (conses acl2-built-ins)
  :short "Returns the second element of a @(tsee cons) pair, else @('nil')"
  :long "<p>Completion Axiom (@('completion-of-cdr')):</p>

 @({
  (equal (cdr x)
         (cond
          ((consp x)
           (cdr x))
          (t nil)))
 })

 <p>@(see Guard):</p>

 @({
  (or (consp x) (equal x nil))
 })

 <p>Notice that in the ACL2 logic, @('cdr') returns @('nil') for every @(see
 atom).</p>")

(defxdoc ceiling
  :parents (numbers acl2-built-ins)
  :short "Division returning an integer by truncating toward positive infinity"
  :long "@({
  Example Forms:
  ACL2 !>(ceiling 14 3)
  5
  ACL2 !>(ceiling -14 3)
  -4
  ACL2 !>(ceiling 14 -3)
  -4
  ACL2 !>(ceiling -14 -3)
  5
  ACL2 !>(ceiling -15 -3)
  5
 })

 <p>@('(Ceiling i j)') is the result of taking the quotient of @('i') and
 @('j') and returning the smallest integer that is at least as great as that
 quotient.  For example, the quotient of @('-14') by @('3') is @('-4 2/3'), and
 the smallest integer at least that great is @('-4').</p>

 <p>The @(see guard) for @('(ceiling i j)') requires that @('i') and @('j') are
 rational (@(see real), in ACL2(r)) numbers and @('j') is non-zero.</p>

 <p>@('Ceiling') is a Common Lisp function.  See any Common Lisp documentation
 for more information.  However, note that unlike Common Lisp, the ACL2
 @('ceiling') function returns only a single value,</p>

 @(def ceiling)")

(defxdoc certificate
  :parents (books-tour)
  :short "A file specifying validity of a given book"
  :long "<p>A book, say @('\"arith\"'), is said to have a ``certificate'' if
 there is a file named @('\"arith.cert\"').  Certificates are created by the
 function @(tsee certify-book) and inspected by @(tsee include-book).  @(Csee
 book-hash) values are used to help ensure that certificates are legitimate and
 that the corresponding book has not been modified since certification.  But
 because the file system is insecure and book-hash values are not perfect, it
 is possible for the inclusion of a book to cause inconsistency even though the
 book carries an impeccable certificate.</p>

 <p>The certificate includes the version number of the certifying ACL2.  A book
 is considered uncertified if it is included in an ACL2 with a different @(see
 version) number.</p>

 <p>The presence of a ``valid'' certificate file for a book attests to two
 things: all of the @(see events) of the book are admissible in a certain
 extension of the initial ACL2 logic, and the non-@(tsee local) @(see events)
 of the book are independent of the @(tsee local) ones (see @(see
 local-incompatibility)).  In addition, the certificate contains the @(see
 command)s used to construct the @(see world) in which certification occurred.
 Among those @(see command)s, of course, are the @(tsee defpkg)s defining the
 packages used in the book.  When a book is included into a host @(see world),
 that @(see world) is first extended by the @(see command)s listed in the
 certificate for the book.  Unless that causes an error due to name conflicts,
 the extension ensures that all the packages used by the book are identically
 defined in the host @(see world).</p>

 <p><i>Security:</i></p>

 <p>Because the host file system is insecure, there is no way ACL2 can
 guarantee that the contents of a book remain the same as when its certificate
 was written.  That is, between the time a book is certified and the time it is
 used, it may be modified.  Furthermore, certificates can be counterfeited.
 @(csee Book-hash) values are used to help detect such problems, but provide
 imperfect security: two different files can have the same book-hash.</p>

 <p>Therefore, from the strictly logical point of view, one must consider even
 the inclusion of certified @(see books) as placing a burden on the user:</p>

 <blockquote>

 <p>The non-erroneous inclusion of a certified book is consistency preserving
 provided (a) the objects read by @(tsee include-book) from the certificate
 were the objects written there by a @(tsee certify-book) and (b) the forms
 read by @(tsee include-book) from the book itself are the forms read by the
 corresponding @(tsee certify-book).</p>

 </blockquote>

 <p>We say that a given execution of @(tsee include-book) is ``certified'' if a
 certificate file for the book is present and well-formed and the @(see
 book-hash) information contained within it supports the conclusion that the
 @(see events) read by the @(tsee include-book) are the ones checked by @(tsee
 certify-book).  When an uncertified @(tsee include-book) occurs, warnings are
 printed or errors are caused.  But even if no warning is printed, you must
 accept burdens (a) and (b) if you use @(see books).  These burdens are easier
 to live with if you protect your @(see books) so that other users cannot write
 to them, you abstain from running concurrent ACL2 jobs, and you abstain from
 counterfeiting certificates.  But even on a single user uniprocessor, you can
 shoot yourself in the foot by using the ACL2 @(see io) primitives to fabricate
 an inconsistent book and the corresponding certificate.</p>

 <p>Note that part (a) of the burden described above implies, in particular,
 that there are no guarantees when a certificate is copied.  When @(see books)
 are renamed (as by copying them), it is recommended that their certificates be
 removed and the @(see books) be recertified.  The expectation is that
 recertification will go through without a hitch if relative @(see pathname)s
 are used.  See @(see pathname), which is not on the guided tour.</p>

 <p>Certificates contain a @(see portcullis) and a @(see keep), each documented
 later in this guided tour through @(see books).  We mention here two other
 parts, which we do not document elsewhere because we view them as
 implementation details: an @('expansion-alist'), which records @(tsee
 make-event) expansions; and @('cert-data'), which contains logical information
 associated with the book.  (Those curious about @('cert-data') are invited to
 look at the ``Essay on Cert-data'' in the source code.)</p>

 <p>See @(see portcullis) to continue the guided tour through @(see
 books).</p>")

(defxdoc certify-book
  :parents (books-reference books-tour)
  :short "How to produce a @(see certificate) for a book"
  :long "<p>Also see @(see certificate) for information about the
 @('\".cert\"') file produced by @('certify-book'), in particular for
 information about the use of @(see book-hash) values to help ensure that the
 corresponding book has not been modified since certification.</p>

 @({
  Examples:
  (certify-book \"my-arith\")          ; certify in a world with 0 commands
  (certify-book \"my-arith\" 3)        ; ... in a world with 3 commands
  (certify-book \"my-arith\" ?)        ; ... in a world without checking the
                                     ;     number of commands
  (certify-book \"my-arith\" 0 nil)    ; ... without compilation
  (certify-book \"my-arith\" 0 t)      ; ... with compilation (default)
  (certify-book \"my-arith\" 0 t :ttags (foo))
                                     ; ... allowing trust tag (ttag) foo
  (certify-book \"my-arith\" 0 t :ttags :all)
                                     ; ... allowing all trust tags (ttags)
  (certify-book \"my-arith\" t)        ; ... from world of old certificate
  (certify-book \"my-arith\" 0 nil :acl2x t)
                                     ; ... writing or reading a .acl2x file

  General Form:
  (certify-book book-name
                k                       ; [default 0]
                compile-flg             ; [default t]
                :defaxioms-okp t/nil    ; [default nil]
                :skip-proofs-okp t/nil  ; [default nil]
                :ttags ttags            ; [default nil]
                :acl2x t/nil            ; [default nil]
                :ttagsx ttags           ; [default nil]
                :pcert pcert            ; [default nil]
                :write-port t/nil       ; [default t unless pcert is non-nil]
                )
 })

 <p>where @('book-name') is a book name (see @(see book-name)), @('k') is used
 to indicate your approval of the ``certification @(see world),'' and
 @('compile-flg') can control whether the book is to be compiled.  The defaults
 for @('compile-flg'), @('skip-proofs-okp'), @('acl2x'), @('write-port'), and
 @('pcert') can be affected by environment variables.  All of these arguments
 are described in detail below, except for @(':pcert').  (We assume below that
 the value of @(':pcert') is @('nil') (and environment variable
 @('ACL2_PCERT_ARG') is unset or the empty string).  For a discussion of this
 argument, see @(see provisional-certification).)</p>

 <p>Certification occurs in some logical @(see world), called the
 ``certification @(see world).''  That @(see world) must contain the @(tsee
 defpkg)s needed to read and execute the forms in the book.  The @(see
 command)s necessary to recreate that @(see world) from the ACL2 initial @(see
 world) are called the ``@(see portcullis) commands,'' and will be copied into
 the @(see certificate) created for the book.  Those @(see command)s will be
 re-executed whenever the book is included, to ensure that the appropriate
 packages (and all other names used in the certification @(see world)) are
 correctly defined.  Note that Step 1 of @('certify-book') will fail if a
 package mentioned in the book is not defined before attempting the
 certification, i.e., defined by a portcullis command in the certification
 world.  For example, suppose that your book contains the symbol @('FOO::X'),
 but the package \"FOO\" is not currently defined.  Then an error message will
 likely complain either about a missing package @('\"FOO\"'), or about a symbol
 @('FOO::X') that is ``not in any of the packages known to ACL2.''  A solution
 is to define the package \"FOO\", perhaps directly using @(tsee defpkg) or by
 including a book that defines this package, before attempting the
 certification.</p>

 <p>The certified book will be more often usable if the certification @(see
 world) is kept to a minimal extension of the ACL2 initial @(see world) (for
 example, to prevent name clashes with functions defined in other books).
 Thus, before you call @('certify-book') for the first time on a book, you may
 wish to get into the initial ACL2 @(see world) (e.g., with @(':ubt 1') or just
 starting a new version of ACL2), @(tsee defpkg) the desired packages, and then
 invoke @('certify-book').</p>

 <p>The @('k') argument to @('certify-book') must be either a nonnegative
 integer or else one of the symbols @('t') or @('?') in any package.  If @('k')
 is an integer, then it must be the number of @(see command)s that have been
 executed after the initial ACL2 @(see world) to create the @(see world) in
 which @('certify-book') was called.  One way to obtain this number is by doing
 @(':pbt :start') to see all the @(see command)s back to the first one.</p>

 <p>If @('k') is @('t') (or any symbol whose @(tsee symbol-name) is
 @('\"T\"')), it means that @('certify-book') should use the same @(see world)
 used in the last certification of this book.  @('K') may have such a value
 only if you call @('certify-book') in the initial ACL2 @(see world) and there
 is a @(see certificate) on file for the book being certified.  (Of course, the
 @(see certificate) is probably invalid.)  In this case, @('certify-book')
 reads the old @(see certificate) to obtain the @(see portcullis) @(see
 command)s and executes them to recreate the certification @(see world).</p>

 <p>Finally, @('k') may be @('?') (or any symbol whose @(tsee symbol-name) is
 @('\"?\"')), in which case there is no check made on the certification world.
 That is, if @('k') is such a value then no action related to the preceding two
 paragraphs is performed, which can be a nice convenience but at the cost of
 eliminating a potentially valuable check that the certification @(see world)
 may be as expected.</p>

 <p>We next describe the meaning of @('compile-flg') and how it defaults.  If
 explicit compilation has been suppressed by @('(set-compiler-enabled nil
 state)'), then @('compile-flg') is coerced to @('nil'); see @(see
 compilation).  Otherwise @('compile-flg') may be given the value of @('t') (or
 @(':all'), which is equivalent to @('t') except during provisional
 certification; see @(see provisional-certification)), indicating that the book
 is to be compiled, or else @('nil').  (Note that compilation initially creates
 a compiled file with a temporary file name, and then moves that temporary file
 to the final compiled file name obtained by adding a suitable extension to the
 book name.  Thus, a compiled file will appear atomically in its intended
 location.)  Finally, suppose that @('compile-flg') is not supplied (or is
 @(':default')).  If environment variable @('ACL2_COMPILE_FLG') is defined and
 not the empty string, then its value should be @('T'), @('NIL'), or @('ALL')
 after converting to upper case, in which case @('compile-flg') is considered
 to have value @('t'), @('nil'), or @(':all') (respectively).  Otherwise
 @('compile-flg') defaults to @('t').  Note that the value @(':all') is
 equivalent to @('t') except for during the Convert procedure of provisional
 certification; see @(see provisional-certification).</p>

 <p>Two keyword arguments, @(':defaxioms-okp') and @(':skip-proofs-okp'),
 determine how the system handles the inclusion of @(tsee defaxiom) events and
 @(tsee skip-proofs) events, respectively, in the book.  The value @('t')
 allows such events, but prints a warning message.  The value @('nil') causes
 an error if such an event is found.  @('Nil') is the default unless keyword
 argument @(':acl2x t') is provided and state global @(''write-acl2x') is a
 cons (see @(see set-write-acl2x)), in which case the default is @('t').</p>

 <p>The keyword argument @(':ttags') may normally be omitted.  A few
 constructs, used for example if you are building your own system based on
 ACL2, may require it.  See @(see defttag) for an explanation of this
 argument.</p>

 <p>When book @('B') is certified with value @('t') (the default, unless the
 value used for @('pcert') is non-@('nil')) for keyword argument
 @(':write-port'), a file @('B.port') is written by certification process.
 This file contains all of the @(see portcullis) @(see command)s for @('B'),
 i.e., all user commands present in the ACL2 logical @(see world) at the time
 @('certify-book') is called.  if @('B.lisp') later becomes uncertified, say
 because @(see events) from that file or an included book have been edited,
 then @('(include-book \"B\")') will consult @('B.port') to evaluate forms in
 that file before evaluating the events in @('B.lisp').  On the other hand,
 @('B.port') is ignored when including @('B') if @('B') is certified.</p>

 <p>If you use @(see guard)s, please note @('certify-book') is executed as
 though @('(set-guard-checking nil)') has been evaluated; see @(see
 set-guard-checking).  If you want guards checked, consider using @('ld')
 instead, or in addition; see @(see ld).</p>

 <p>For a general discussion of books, see @(see books).  @('Certify-book') is
 akin to what we have historically called a ``proveall'': all the forms in the
 book are ``proved'' to guarantee their admissibility.  More precisely,
 @('certify-book') (1) reads the forms in the book, confirming that the
 appropriate packages are defined in the certification @(see world); (2) does
 the full admissibility checks on each form (proving termination of recursive
 functions, proving theorems, etc.), checking as it goes that each form is an
 embedded event form (see @(see embedded-event-form)); (3) may roll back the
 @(see world) (how far? ~-[] see below) and perform an @(tsee include-book) to
 check for @(tsee local) incompatibilities (see @(see
 local-incompatibility)); (4) writes a @(see certificate) recording not only
 that the book was certified but also recording the @(see command)s necessary
 to recreate the certification @(see world) (so the appropriate packages can be
 defined when the book is included in other @(see world)s) and a @(see
 book-hash) for each of the @(see books) involved (see @(see certificate)); (5)
 compiles the book if so directed (and then loads the object file in that
 case).  The result of executing a @('certify-book') @(see command) is the
 creation of a single new event, which is actually an @(tsee include-book)
 event.  If you don't want its included @(see events) in your present @(see
 world), simply execute @(':')@(tsee ubt) @(':here') afterwards.</p>

 <p>Technical Remark.  Step 3 above mentions rolling the logical @(see world)
 back to check for local incompatibilities.  For efficiency, this retraction to
 an initial segment of the the world is skipped if a local event is not
 encountered as described below; otherwise, the world is rolled back to the
 point just before the first such event was admitted.  For this purpose, a
 relevant local event is one at the top level of the book or under a sequences
 of @(tsee progn) calls in the book.  Here, we include forms generated by
 @(tsee make-event).  But this category does not include local @(see events)
 within an @(tsee encapsulate) event, since those are ignored in the final
 processing of the @('encapsulate') event.  We also do not consider local
 events within an @(tsee include-book) event.  End of Technical Remark.</p>

 <p>A utility is provided to assist in debugging failures of @('certify-book');
 see @(see redo-flat).)</p>

 <p>@('Certify-book') requires that the default @(see defun-mode) (see @(see
 default-defun-mode)) be @(':')@(tsee logic) when certification is attempted.
 If the mode is not @(':')@(tsee logic), an error is signaled.</p>

 <p>An error will occur if @('certify-book') has to deal with any uncertified
 book other than the one on which it was called.  For example, if the book
 being certified includes another book, that sub-book must already have been
 certified; that is, that sub-book must have a valid @(see certificate)
 file.</p>

 <p>If you have a certified book that has remained unchanged for some time you
 might well not remember the appropriate @(tsee defpkg)s for it, though they
 are stored in the @(see certificate) file and (by default) also in the
 @('.port') file.  If you begin to change the book, don't throw away its @(see
 certificate) file just because it has become invalid!  It is an important
 historical document until the book is re-certified.  More important, don't
 throw away the @('.port') file, as it will provide the @(see portcullis)
 commands when including the book as an uncertified book; see @(see
 include-book).</p>

 <p>When @('certify-book') is directed to produce a compiled file, it calls the
 Common Lisp function @('compile-file') on the original source file.  This
 creates a compiled file with an extension known to ACL2, e.g., if the book is
 named @('\"my-book\"') then the source file is @('\"my-book.lisp\"') and the
 compiled file under GCL will be @('\"my-book.o\"') while under SBCL it will be
 @('\"my-book.fasl\"').  The compiled file is then loaded.  When @(tsee
 include-book) is used later on @('\"my-book\"') it will automatically load the
 compiled file, provided the compiled file has a later write date than the
 source file.  The only effect of such @(see compilation) and loading is that
 the functions defined in the book execute faster.  See @(see guard) for a
 discussion of the issues, and if you want more details about @(see books) and
 compilation, see @(see book-compiled-file).</p>

 <p>When @('certify-book') is directed not to produce a compiled file, it will
 delete any existing compiled file for the book, so as not to mislead @(tsee
 include-book) into loading the now outdated compiled file.  Otherwise,
 @('certify-book') will create a temporary ``expansion file'' to compile,
 obtained by appending the string \"@@expansion.lsp\" to the end of the book
 name.  Remark: Users may ignore that file, which is automatically deleted
 unless @(see state) global variable @(''save-expansion-file') has been set,
 presumably by a system developer, to a non-@('nil') value; see @(see
 book-compiled-file) for more information about hit issue, including the role
 of environment variable @('ACL2_SAVE_EXPANSION').</p>

 <p>After execution of a @('certify-book') form, the value of @(tsee
 acl2-defaults-table) is restored to what it was immediately before that
 @('certify-book') form was executed.  See @(see acl2-defaults-table).</p>

 <p>Those who use the relatively advanced features of trust tags (see @(see
 defttag)) and @(tsee make-event) may wish to know how to create a @(see
 certificate) file that avoids dependence on trust tags that are used only
 during @(tsee make-event) expansion.  For this, including documentation of the
 @(':acl2x') and @(':ttagsx') keyword arguments for @('certify-book'), see
 @(see set-write-acl2x).</p>

 <p>This completes the tour through the @(see documentation) of @(see
 books).</p>")

(defxdoc certify-book!
  :parents (certify-book)
  :short "A variant of @(tsee certify-book)"
  :long "@({
  Examples:
  (certify-book! \"my-arith\" 3)     ;Certify in a world with 3
                                     ; commands, starting in a world
                                     ; with at least 3 commands.
  (certify-book! \"my-arith\")       ;Certify in the initial world.

  General Form:
  (certify-book! book-name k compile-flg)
 })

 <p>where @('book-name') is a book name (see @(see book-name)), @('k') is a
 nonnegative integer used to indicate the ``certification @(see world),'' and
 @('compile-flg') indicates whether you wish to compile the (functions in the)
 book.</p>

 <p>This @(see command) is identical to @(tsee certify-book), except that the
 second argument @('k') may not be @('t') in @('certify-book!') and if @('k')
 exceeds the current @(see command) number, then an appropriate @(tsee ubt!)
 will be executed first.  See @(see certify-book) and see @(see ubt!).</p>")

(defxdoc change
  :parents (defrec acl2-built-ins)
  :short "Mutator macro for @(see defrec) structures."

  :long "<p>The @('change') macro is built into ACL2, and allows you to
 \"modify\" instances of structures that have been introduced with @(see
 defrec).  Of course, since ACL2 is applicative, the original structure is not
 actually changed&mdash;instead, a new structure is constructed, copying some
 fields from the original structure and installing new values for other
 fields.</p>

 <p>For instance, suppose we first use @(see make) to create an employee
 structure, e.g.,:</p>

 @({
    (defconst *jimmy* (make employee :name \"Jimmy\"
                                     :salary 0
                                     :position \"Unpaid Intern\")
 })

 <p>Then we can use @('change') to mutate this structure, e.g.,:</p>

 @({
     (change employee *jimmy* :salary 300000
                              :position \"Vice President\")
 })

 <p>Produces a new @('employee') structure where the @('name') is still
 \"Jimmy\", but where the @('salary') and @('position') have been updated to
 300000 and \"Vice President\", respectively.</p>

 <p>See @(see defrec) for more information.</p>")

(defxdoc char
  :parents (characters acl2-built-ins)
  :short "The @(see nth) element (zero-based) of a string"
  :long "<p>@('(Char s n)') is the @('n')th element of @('s'), zero-based.  If
 @('n') is greater than or equal to the length of @('s'), then @('char')
 returns @('nil').</p>

 <p>@('(Char s n)') has a @(see guard) that @('n') is a non-negative integer
 and @('s') is a @(tsee stringp).</p>

 <p>@('Char') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def char)")

(defxdoc char-code
  :parents (characters numbers acl2-built-ins)
  :short "The numeric code for a given character"
  :long "<p>This function maps a character to its code, for example:
  @('(char-code #\\A)') evaluates to @('65').  See @(tsee code-char) for a sort
  of inverse function, which maps a code to the corresponding character.</p>

 <p>Completion Axiom (@('completion-of-char-code')):</p>

 @({
  (equal (char-code x)
         (if (characterp x)
             (char-code x)
           0))
 })

 <p>@(see Guard) for @('(char-code x)'):</p>

 @({
  (characterp x)
 })

 <p>This function maps all non-characters to @('0').</p>")

(defxdoc char-downcase
  :parents (characters acl2-built-ins)
  :short "Turn upper-case @(see characters) into lower-case @(see characters)"
  :long "<p>@('(Char-downcase x)') is equal to @('#\\a') when @('x') is
 @('#\\A'), @('#\\b') when @('x') is @('#\\B'), ..., and @('#\\z') when @('x')
 is @('#\\Z'), and is @('x') for any other character.</p>

 <p>The @(see guard) for @('char-downcase') requires its argument to be a
 standard character (see @(see standard-char-p)).</p>

 <p>@('Char-downcase') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def char-downcase)")

(defxdoc char-equal
  :parents (characters acl2-built-ins)
  :short "Character equality without regard to case"
  :long "<p>For @(see characters) @('x') and @('y'), @('(char-equal x y)') is
 true if and only if @('x') and @('y') are the same except perhaps for their
 case.</p>

 <p>The @(see guard) on @('char-equal') requires that its arguments are both
 standard @(see characters) (see @(see standard-char-p)).</p>

 <p>@('Char-equal') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def char-equal)")

(defxdoc char-upcase
  :parents (characters acl2-built-ins)
  :short "Turn lower-case @(see characters) into upper-case @(see characters)"
  :long "<p>@('(Char-upcase x)') is equal to @('#\\A') when @('x') is
 @('#\\a'), @('#\\B') when @('x') is @('#\\b'), ..., and @('#\\Z') when @('x')
 is @('#\\z'), and is @('x') for any other character.</p>

 <p>The @(see guard) for @('char-upcase') requires its argument to be a
 standard character (see @(see standard-char-p)).</p>

 <p>@('Char-upcase') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def char-upcase)")

(defxdoc char<
  :parents (characters acl2-built-ins)
  :short "Less-than test for @(see characters)"
  :long "<p>@('(char< x y)') is true if and only if the character code of
 @('x') is less than that of @('y').  See @(see char-code).</p>

 <p>The @(see guard) for @('char<') specifies that its arguments are @(see
 characters).</p>

 <p>@('Char<') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def char<)")

(defxdoc char<=
  :parents (characters acl2-built-ins)
  :short "Less-than-or-equal test for @(see characters)"
  :long "<p>@('(char<= x y)') is true if and only if the character code of
 @('x') is less than or equal to that of @('y').  See @(see char-code).</p>

 <p>The @(see guard) for @('char<=') specifies that its arguments are @(see
 characters).</p>

 <p>@('Char<=') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def char<=)")

(defxdoc char>
  :parents (characters acl2-built-ins)
  :short "Greater-than test for @(see characters)"
  :long "<p>@('(char> x y)') is true if and only if the character code of
 @('x') is greater than that of @('y').  See @(see char-code).</p>

 <p>The @(see guard) for @('char>') specifies that its arguments are @(see
 characters).</p>

 <p>@('Char>') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def char>)")

(defxdoc char>=
  :parents (characters acl2-built-ins)
  :short "Greater-than-or-equal test for @(see characters)"
  :long "<p>@('(char>= x y)') is true if and only if the character code of
 @('x') is greater than or equal to that of @('y').  See @(see char-code).</p>

 <p>The @(see guard) for @('char>=') specifies that its arguments are @(see
 characters).</p>

 <p>@('Char>=') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def char>=)")

(defxdoc character-alistp
  :parents (characters alists acl2-built-ins)
  :short "Recognizer for association lists with characters as keys"
  :long "<p>@('(Character-alistp x)') is true if and only if @('x') is a list
 of pairs of the form @('(cons key val)') where @('key') is a @(tsee
 characterp).</p>

 @(def character-alistp)")

(defxdoc character-encoding

; The comment near the top of "PRINTING and READING" in ACL2 source file
; axioms.lisp pertains to Emacs variable save-buffer-coding-system, which is
; related to character encoding.

  :parents (io)
  :short "How bytes are parsed into characters"
  :long "<p>When the Common Lisp reader comes across bytes in a file or at the
 terminal, they are parsed into characters.  The simplest case is when each
 byte that is read is a standard character (see @(see standard-char-p)).  It is
 actually quite common that each byte that is read corresponds to a single
 character.  The parsing of bytes into characters is based on a <i>character
 encoding</i>, that is, a mapping that associates one or more bytes with each
 legal character.</p>

 <p>In order to help guarantee the portability of files (including @(see
 books)), ACL2 installs a common character encoding for reading files, often
 known as iso-8859-1 or latin-1.  For some host Lisps this character encoding
 is also used for reading from the terminal; but, sadly, this may not hold for
 all host Lisps, and may not even be possible for some of them.</p>

 <p>The use of the above encoding could in principle cause problems if one's
 editor produces files using an encoding other than iso-8859-1, at least if one
 uses non-standard characters.  In particular, the default Emacs buffer
 encoding may be utf-8.  If your file has non-standard characters, then in
 Emacs you can evaluate the form</p>

 @({
  (setq save-buffer-coding-system 'iso-8859-1)
 })

 <p>before saving the buffer into a file.  This will happen automatically for
 users who load distributed file @('emacs/emacs-acl2.el') into their Emacs
 sessions.</p>

 <p>For an example of character encodings in action, see the community book
 @('books/misc/character-encoding-test.lisp').</p>")

(defxdoc character-listp
  :parents (characters lists acl2-built-ins)
  :short "Recognizer for a true list of characters"
  :long "<p>The predicate @('character-listp') tests whether its argument is a
 true list of @(see characters).</p>

 @(def character-listp)")

(defxdoc characterp
  :parents (characters acl2-built-ins)
  :short "Recognizer for @(see characters)"
  :long "<p>@('(characterp x)') is true if and only if @('x') is a
  character.</p>")

(defxdoc characters
  :parents (programming)
  :short "Characters in ACL2 and operations on them"
  :long "<p>ACL2 accepts 256 distinct characters, which are the characters
 obtained by applying the function @(tsee code-char) to each integer from
 @('0') to @('255').  Among these, Common Lisp designates certain ones as
 <i>standard characters</i>, namely those of the form @('(code-char n)') where
 @('n') is from @('33') to @('126'), together with @('#\\Newline') and
 @('#\\Space').  The actual standard characters may be viewed by evaluating the
 @(tsee defconst) @('*standard-chars*').</p>

 <p>To be more precise, Common Lisp does not specify the precise relationship
 between @(tsee code-char) and the standard characters.  However, we check that
 the underlying Common Lisp implementation uses a particular relationship that
 extends the usual ASCII coding of characters.  We also check that Space, Tab,
 Newline, Page, Rubout, and Return correspond to characters with respective
 @(tsee char-code)s @('32'), @('9'), @('10'), @('12'), @('127'), and
 @('13').</p>

 <p>@(tsee Code-char) has an inverse, @(tsee char-code).  Thus, when @(tsee
 char-code) is applied to an ACL2 character, @('c'), it returns a number @('n')
 between @('0') and @('255') inclusive such that @('(code-char n)') =
 @('c').</p>

 <p>The preceding paragraph implies that there is only one ACL2 character with
 a given character code.  CLTL allows for ``attributes'' for characters, which
 could allow distinct characters with the same code, but ACL2 does not allow
 this.</p>

 <p><i>The Character Reader</i></p>

 <p>ACL2 supports the `@('#\\')' notation for characters provided by Common
 Lisp, with some restrictions.  First of all, for every character @('c'), the
 notation</p>

 @({
  #\\c
 })

 <p>may be used to denote the character object @('c').  That is, the user may
 type in this notation and ACL2 will read it as denoting the character object
 @('c').  In this case, the character immediately following @('c') must be one
 of the following ``terminating characters'': a Tab, a Newline, a Page
 character, a space, or one of the characters:</p>

 @({
  \"  '  (  )  ;  `  ,
 })

 <p>Other than the notation above, ACL2 accepts alternate notation for five
 characters.</p>

 @({
  #\\Space
  #\\Tab
  #\\Newline
  #\\Page
  #\\Rubout
  #\\Return
 })

 <p>Again, in each of these cases the next character must be from among the set
 of ``terminating characters'' described in the single-character case.  Our
 implementation is consistent with IS0-8859, even though we don't provide
 @('#\\') syntax for entering characters other than that described above.</p>

 <p>Finally, we note that it is our intention that any object printed by ACL2's
 top-level-loop may be read back into ACL2.  Please notify the implementors if
 you find a counterexample to this claim.</p>")

(defxdoc check-vars-not-free
  :parents (macros)
  :short "Avoid variable capture in macro calls"
  :long "<p>@('Check-vars-not-free') is a macro that is useful for avoiding
 capture of variables in macro calls.  We explain using a running example,
 after which we give a precise explanation (at the end of this documentation
 topic).  These definitions are rather contrived but are designed to illustrate
 how @('check-vars-not-free') can be useful.</p>

 @({
 (defmacro has-length (x n)
   `(let ((k (len ,x)))
      (equal k ,n)))
 (defun f1 (u v)
   (and (natp v)
        (has-length u (* 2 v))))
 (defun f2 (lst k)
   (and (natp k)
        (has-length lst (* 2 k))))
 })

 <p>One might expect @('f1') and @('f2') to be the same function, since the
 only change seems to be from the choices of formal parameters.  However,
 consider these evaluations.</p>

 @({
 ACL2 !>(f1 '(a b c d e f) 3)
 T
 ACL2 !>(f2 '(a b c d e f) 3)
 NIL
 ACL2 !>
 })

 <p>The problem becomes clear if we expand the macro call in the body of
 @('f2').</p>

 @({
 ACL2 !>:trans1 (has-length lst (* 2 k))
  (LET ((K (LEN LST))) (EQUAL K (* 2 K)))
 ACL2 !>
 })

 <p>We see that when expanding the call of the macro @('has-length') in the
 body of @('f2'), the substitution of @('(* 2 k)') for @(',n') causes @('k') to
 be``captured'' by the binding of @('k') to @('(len lst)').</p>

 <p>The macro @('check-vars-not-free') is designed to enforce that no such
 capture takes place.  An improved definition of @('has-length') is as
 follows, since it insists that the variable @('k') must not appear in the term
 that replaces @(',n').</p>

 @({
 (defmacro has-length (x n)
   `(let ((k (len ,x)))
      (equal k (check-vars-not-free (k) ,n))))
 })

 <p>Now, the attempt to define @('f2') as above causes an error.</p>

 @({
 ACL2 !>(defun f2 (lst k)
    (and (natp k)
         (has-length lst (* 2 k))))


 ACL2 Error in ( DEFUN F2 ...):  CHECK-VARS-NOT-FREE failed:
 It is forbidden to use K in (BINARY-* '2 K).  Note:  this error occurred
 in the context (CHECK-VARS-NOT-FREE (K) (* 2 K)).


 Summary
 Form:  ( DEFUN F2 ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

 ACL2 Error in ( DEFUN F2 ...):  See :DOC failure.

 ******** FAILED ********
 ACL2 !>
 })

 <p>The error message shows that the check performed by
 @('check-vars-not-free') has failed, because the variable @('k') occurs in the
 expression @('(* 2 k)').  More precisely, what is checked is that @('k') does
 not occur in the translation to a @(see term) of the expression @('(* 2 k)'),
 namely, @('(binary-* '2 k)').</p>

 <p>The general form of a call of @('check-vars-not-free') is</p>

 @({
 (check-vars-not-free (var_1 ... var_n) expr)
 })

 <p>where @('var_1'), ..., @('var_n') are variables and @('expr') is an
 expression.  This call is equivalent to @('expr') &mdash; indeed, there is no
 effect on the code generated when using this call in place of @('expr')
 &mdash; but ACL2 requires that the indicated variables do not occur free in
 the translation of @('expr') to a term.</p>")

(defxdoc checkpoint-summary-limit
  :parents (set-gag-mode)
  :short "Control printing of key checkpoints upon a proof's failure"
  :long "<p>See @(see set-checkpoint-summary-limit) for a discussion of the
 checkpoint-summary-limit.  Evaluation of the form
 @('(checkpoint-summary-limit)') produces the current checkpoint-summary-limit,
 and can be invoked with the keyword hack (see @(see keyword-commands)).  For
 example:</p>

 @({
 ACL2 !>:checkpoint-summary-limit
 (NIL . 3)
 ACL2 !>
 })")

(defxdoc checksum
  :parents (certificate)
  :short "Assigning ``often unique'' integers to files and objects"
  :long "<p>See @(see book-hash) for a discussion of how ACL2 can use checksums
 (though not by default) to increase security in the @(see books)
 mechanism.</p>

 <p>A <i>checksum</i> is an integer in some fixed range computed from the
 printed representation of an object, e.g., the sum, modulo @('2**32'), of the
 ascii codes of all the @(see characters) in the printed representation.</p>

 <p>Ideally, you would like the checksum of an object to be uniquely associated
 with that object, like a fingerprint.  It could then be used as a convenient
 way to recognize the object in the future: you could remember the
 checksum (which is relatively small) and when an object is presented to you
 and alleged to be the special one you could compute its checksum and see if
 indeed it was.  Alas, there are many more objects than checksums (after all,
 each checksum is an object, and then there's @('t')).  So you try to design a
 checksum algorithm that maps similar looking objects far apart, in the hopes
 that corruptions and counterfeits &mdash; which appear to be similar to the
 object &mdash; have different checksums.  Nevertheless, the best you can do is
 a many-to-one map.  If an object with a different checksum is presented, you
 can be positive it is not the special object.  But if an object with the same
 checksum is presented, you have no grounds for positive identification.</p>

 <p>The basic checksum algorithm in ACL2 is called @('check-sum-obj'), which
 computes the checksum of an ACL2 object.  Roughly speaking, we scan the print
 representation of the object and, for each character encountered, we multiply
 the ascii code of the character times its position in the stream (modulo a
 certain prime) and then add (modulo a certain prime) that into the running
 sum.  This is inaccurate in many senses (for example, we don't always use the
 ascii code and we see numbers as though they were printed in base 127) but
 indicates the basic idea.</p>")

(defxdoc checkpoint-forced-goals
  :parents (proof-tree)
  :short "Cause forcing goals to be checkpointed in proof trees"
  :long "@({
  Example forms:
  (checkpoint-forced-goals t)
  (checkpoint-forced-goals nil)
 })

 <p>Also see @(see proof-tree).</p>

 <p>By default, goals are not marked as checkpoints by a proof tree display (as
 described elsewhere; see @(see proof-tree)) merely because they @(see force)
 some hypotheses, thus possibly contributing to a forcing round.  However, some
 users may want such behavior, which will occur once the command
 @('(checkpoint-forced-goals') @('t')) has been executed.  To return to the
 default behavior, use the command @('(checkpoint-forced-goals nil)').</p>")

(defxdoc clause-identifier
  :parents (goal-spec)
  :short "The internal form of a @(see goal-spec)"
  :long "<p>To each goal-spec, @('str'), there corresponds a clause-identifier
 produced by @('(parse-clause-id str)').  For example,</p>

 @({
  (parse-clause-id \"[2]Subgoal *4.5.6/7.8.9'''\")
 })

 <p>returns @('((2 4 5 6) (7 8 9) . 3)').</p>

 <p>The function @('string-for-tilde-@-clause-id-phrase') inverts
 @('parse-clause-id') in the sense that given a clause identifier it returns
 the corresponding goal-spec.</p>

 <p>As noted in the documentation for @(see goal-spec), each clause printed in
 the theorem prover's proof attempt is identified by a name.  When these names
 are represented as strings they are called ``goal specs.''  Such strings are
 used to specify where in the proof attempt a given hint is to be applied.  The
 function @('parse-clause-id') converts goal-specs into clause identifiers,
 which are cons-trees containing natural numbers.</p>

 <p>Examples of goal-specs and their corresponding clause identifiers are shown
 below.</p>

 @({
               parse-clause-id
                     -->

  \"Goal\"                       ((0) NIL . 0)
  \"Subgoal 3.2.1'\"             ((0) (3 2 1) . 1)
  \"[2]Subgoal *4.5.6/7.8.9'''\" ((2 4 5 6) (7 8 9) . 3)

                     <--
        string-for-tilde-@-clause-id-phrase
 })

 <p>The caar of a clause id specifies the forcing round, the cdar specifies the
 goal being proved by induction, the cadr specifies the particular subgoal, and
 the cddr is the number of primes in that subgoal.</p>

 <p>Internally, the system maintains clause ids, not goal-specs.  The system
 prints clause ids in the form shown by goal-specs.  When a goal-spec is used
 in a hint, it is parsed (before the proof attempt begins) into a clause id.
 During the proof attempt, the system watches for the clause id and uses the
 corresponding hint when the id arises.  (Because of the expense of creating
 and garbage collecting a lot of strings, this design is more efficient than
 the alternative.)</p>")

(defxdoc clause-processor
  :parents (rule-classes)
  :short "Make or apply a @(':clause-processor') rule (goal-level simplifier)"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 <p>We will introduce clause-processor rules by way of the following example.
 But note that the clause-processor utility is more general than this example
 may suggest; for example, the second argument of @('evl0') in the hypothesis
 need not be the same as its second argument in the conclusion.</p>

 @({
  ; Example (which we'll return to, below):
  (defthm correctness-of-note-fact-clause-processor
    (implies (and (pseudo-term-listp cl)
                  (alistp a)
                  (evl0 (conjoin-clauses
                         (note-fact-clause-processor cl term))
                        a))
             (evl0 (disjoin cl) a))
    :rule-classes :clause-processor)
 })

 <p>We begin this documentation with an introduction, focusing on the example
 above, and then conclude with a detailed general discussion of
 clause-processor rules.  You might find it most useful simply to look at the
 examples in community books directory @('books/clause-processors/'); see file
 @('Readme.lsp') in that directory.</p>

 <p>Also see @(see define-trusted-clause-processor) for documentation of an
 analogous utility that does not require the clause-processor to be proved
 correct.  But please read the present documentation before reading about that
 utility.  Both utilities designate functions as ``clause-processors''.  Such
 functions must be executable &mdash; hence not constrained by virtue of being
 introduced in the @(see signature) of an @(tsee encapsulate) &mdash; and must
 respect @(see stobj) and output arity restrictions.  For example, something
 like @('(car (mv ...))') is illegal; also see @(see signature).</p>

 <h4>INTRODUCTION</h4>

 <p>A @(':clause-processor') rule installs a simplifier at the level of goals,
 where a goal is represented as a <i>clause</i>: a list of @(see term)s that is
 implicitly viewed as a disjunction (the application of @(tsee OR)).  For
 example, if ACL2 prints a goal in the form @('(implies (and p q) r)'), then
 the clause might be the one-element list containing the internal
 representation of this term &mdash; @('(implies (if p q 'nil) r)') &mdash; but
 more likely, the corresponding clause is @('((not p) (not q) r)').  Note that
 the members of a clause are <i>translated</i> terms; see @(see term) and
 @(tsee termp).  For example, they do not contain calls of the macro @('AND'),
 and constants are quoted.  The result of running a clause-processor must be a
 list of legal clauses; see @(see meta) for a discussion of translated terms,
 and for related discussion about ``forbidden'' function symbols, @(see
 set-skip-meta-termp-checks).</p>

 <p>The recognizer for a clause is the function @(tsee term-listp) and the
 recognizer for a list of clauses is @(tsee term-list-listp).</p>

 <p>Note that clause-processor simplifiers are similar to metafunctions, and
 similar efficiency considerations apply.  See @(see meta), in particular the
 discussion on how to ``make a metafunction maximally efficient.''</p>

 <p>Unlike rules of class @(':')@(tsee meta), rules of class
 @(':clause-processor') must be applied by explicit @(':clause-processor')
 @(see hints); they are not applied automatically (unless by way of computed
 hints; see @(see computed-hints)).  But @(':clause-processor') rules can be
 useful in situations for which it is more convenient to code a simplifier that
 manipulates the entire goal clause rather than individual subterms of terms in
 the clause.</p>

 <p>We begin with a simple illustrative example: a clause-processor that
 assumes an alleged fact (named @('term') in the example) and creates a
 separate goal to prove that fact.  We can extend the hypotheses of the current
 goal (named @('cl') in the example) with a term by adding the negation of that
 term to the clause (disjunctive) representation of that goal.  So the
 following returns a list of two clauses: the result of adding @('term') as a
 hypothesis to the input clause, as just described, and a second clause
 consisting only of that term.  This list of two clauses can be viewed as the
 conjunction of the first clause and the second clause (where again, each
 clause is viewed as a disjunction).</p>

 @({
  (defun note-fact-clause-processor (cl term)
    (declare (xargs :guard t)) ; optional, for better efficiency
    (list (cons (list 'not term)
                cl)
          (list term)))
 })

 <p>As with @(':')@(tsee meta) rules, we need to introduce a suitable
 evaluator; see @(see defevaluator) if you want details.  Since we expect to
 reason about the function @(tsee NOT), because of its role in
 @('note-fact-clause-processor') as defined above, we include @('NOT') in the
 set of functions known to this evaluator.  We also include @('IF'), as is
 often a good idea.</p>

 @({
  (defevaluator evl0 evl0-list
    ((not x) (if x y z)))
 })

 <p>ACL2 can now prove the following theorem automatically.  (This is the
 example displayed at the outset of this @(see documentation) topic.)  Of
 course, @(':clause-processor') rules about clause-processor functions less
 trivial than @('note-fact-clause-processor') may require lemmas to be proved
 first!  The function @('disjoin') takes a clause and returns its disjunction
 (the result of applying @(tsee OR) to its members), and @('conjoin-clauses')
 applies @('disjoin') to every element of a given list of clauses and then
 conjoins (applies @('AND')) to the corresponding list of resulting terms.</p>

 @({
  (defthm correctness-of-note-fact-clause-processor
    (implies (and (pseudo-term-listp cl)
                  (alistp a)
                  (evl0 (conjoin-clauses
                         (note-fact-clause-processor cl term))
                        a))
             (evl0 (disjoin cl) a))
    :rule-classes :clause-processor)
 })

 <p>Now let us submit a silly but illustrative example theorem to ACL2, to show
 how a corresponding @(':clause-processor') hint is applied.  The hint says to
 apply the clause-processor function, @('note-fact-clause-processor'), to the
 current goal clause and a ``user hint'' as the second argument of that
 function, in this case @('(equal a a)').  Thus, a specific variable,
 @('clause'), is always bound to the current goal clause for the evaluation of
 the @(':clause-processor') hint, to produce a list of clauses.  Since two
 subgoals are created below, we know that this list contained two clauses.
 Indeed, these are the clauses returned when @('note-fact-clause-processor') is
 applied to two arguments: the current clause, which is the one-element list
 @('((equal (car (cons x y)) x))'), and the user hint, @('(equal a a)').</p>

 @({
  ACL2 !>(thm (equal (car (cons x y))
                     x)
              :hints
              ((\"Goal\"
                :clause-processor
                (note-fact-clause-processor clause '(equal a a)))))

  [Note:  A hint was supplied for our processing of the goal above.
  Thanks!]

  We now apply the verified :CLAUSE-PROCESSOR function NOTE-FACT-CLAUSE-
  PROCESSOR to produce two new subgoals.

  Subgoal 2
  (IMPLIES (EQUAL A A)
           (EQUAL (CAR (CONS X Y)) X)).

  But we reduce the conjecture to T, by the :executable-counterpart of
  IF and the simple :rewrite rule CAR-CONS.

  Subgoal 1
  (EQUAL A A).

  But we reduce the conjecture to T, by primitive type reasoning.

  Q.E.D.

  Summary
  Form:  ( THM ...)
  Rules: ((:EXECUTABLE-COUNTERPART IF)
          (:EXECUTABLE-COUNTERPART NOT)
          (:FAKE-RUNE-FOR-TYPE-SET NIL)
          (:REWRITE CAR-CONS))
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

  Proof succeeded.
  ACL2 !>
 })

 <p>That concludes our introduction to clause-processor rules and hints.  We
 turn now to detailed documentation.</p>

 <h4>DETAILED DOCUMENTATION</h4>

 <p>The @(see signature) of a clause-processor function, @('CL-PROC'), must
 have one of the following forms.  Here, each @('st_i') is a @(see stobj)
 (possibly @(tsee state)) while the other parameters and results are not stobjs
 (see @(see stobj)).  Note that there need not be input stobjs in [3] &mdash;
 i.e., @('k') can be 0 &mdash; and even if there are, there need not be output
 stobjs.</p>

 @({
  [1]  ((CL-PROC cl) => cl-list)

  [2]  ((CL-PROC cl hint) => cl-list)

  [3]  ((CL-PROC cl hint st_1 ... st_k) => (mv erp cl-list st_i1 ... st_in))
 })

 <p>We call @('cl-list') the <i>clauses-result</i>.  In [3], we think of the
 first component of the result as an error flag.  Indeed, a proof will
 instantly abort if that error flag is not @('nil').</p>

 <p>We next discuss the legal forms of @(':clause-processor') rules, followed
 below by a discussion of @(':clause-processor') @(see hints).  In the
 discussion below, we use lower-case names to represent specific symbols, for
 example @('implies'), and also to represent @(see stobj) names; and we use
 upper-case names to represent arbitrary pieces of syntax (which we will
 describe), for example, @('CL').</p>

 <p>If a @(':')@(tsee rule-classes) specification includes
 @(':clause-processor'), then the corresponding term must have the following
 form.  (Additional ``meta-extract'' hypotheses, not shown or discussed below,
 may be included as desired in order to use facts from the logical @(tsee
 world) to help prove the rule; see @(see meta-extract) for explanation of this
 advanced feature.)</p>

 @({
  ; General Form (omitting possible meta-extract hypotheses)
  (implies (and (pseudo-term-listp CL)
                (alistp A)
                (EVL (conjoin-clauses <CL-LIST>)
                      B))
           (EVL (disjoin CL) A))
 })

 <p>Here @('EVL') is a known evaluator; @('CL') and @('A') are distinct
 non-stobj variables; and @('<CL-LIST>') is an expression representing the
 clauses returned by the clause-processor function @('CL-PROC'), whose form
 depends on the @(see signature) of that function, as follows.  Typically
 @('B') is @('A'), but it can be any term (useful when generalization is
 occurring; see the example ``Test generalizing alist'' in community book
 @('books/clause-processors/basic-examples.lisp')).  For cases [1] and [2]
 above, @('<CL-LIST>') is of the form @('(CL-PROC CL)') or @('(CL-PROC CL
 HINT)'), respectively, where in the latter case @('HINT') is a non-stobj
 variable distinct from the variables @('CL') and @('A').  For case [3],
 @('<CL-LIST>') is of the form</p>

 @({
  (clauses-result (CL-PROC CL HINT st_1 ... st_k))
 })

 <p>where the @('st_i') are the specific stobj names mentioned in [3].
 Logically, @('clauses-result') returns the @(tsee cadr) if the @(tsee car) is
 @('NIL'), and otherwise (for the error case) returns a list containing the
 empty (false) clause.  So in the non-error case, @('clauses-result') picks out
 the second result, denoted @('cl-list') in [3] above, and in the error case
 the implication above trivially holds.</p>

 <p>In the above theorem, we are asked to prove @('(EVL (disjoin CL) A)')
 assuming that the conjunction of all clauses produced by the clause processor
 evaluates to a non-@('nil') value under some alist @('B').  In fact, we can
 choose @('B') so as to allow us to assume evaluations of the generated clauses
 over many different alists.  This technique is discussed in the community book
 @('books/clause-processors/multi-env-trick.lisp'), which introduces some
 macros that may be helpful in accomplishing proofs of this type.</p>

 <p>The clause-processor function, @('CL'), must have a guard that ACL2 can
 trivially prove from the hypotheses that the first argument of @('CL') is
 known to be a @('pseudo-term-listp') and any @(see stobj) arguments are
 assumed to satisfy their stobj predicates.</p>

 <p>Next we specify the legal forms for @(':clause-processor') @(see hints).
 The basic form is @(':clause-processor TERM'), such that the translation of
 @('TERM') to a legal ACL2 term yields a call of a clause-processor function
 @('(CL-PROC clause)') or @('(CL-PROC clause HINT ...)'), where @('HINT') is a
 term whose only non-stobj free variable (if any) is the symbol, @('clause').
 Note that the first argument of the call is literally the variable,
 @('clause').  Recall that at the time the :clause-processor hint is applied to
 the clausal form @('CL') of the current subgoal, @('clause') is bound to
 @('CL'); moreover, any stobj names will be bound to the corresponding
 stobjs.</p>

 <p>But there are two additional general forms for @(':clause-processor')
 hints, which may viewed as abbreviations for the basic form discussed above.
 The first additional general form, which we call the ``@(':function') form'',
 includes the following two classes of expressions.</p>

 @({
 :clause-processor (:function F)
 :clause-processor (:function F :hint HINT)
 })

 <p>The first of these @(':function') forms abbreviates the following hint,
 where either @('F') is a macro-alias for the function symbol @('CL-PROC') (see
 @(see add-macro-alias)), and otherwise @('CL-PROC') is just the function
 symbol @('F').</p>

 @({
 :clause-processor (CL-PROC clause)
 })

 <p>Similarly the second of the @(':function') forms above abbreviates the
 following, where @('CL-PROC') is as above and the output signature of
 @('CL-PROC') is @('(nil nil st_1 ... st_k)').</p>

 @({
 :clause-processor (CL-PROC clause HINT st_1 ... st_k)
 })

 <p>Besides the ``@(':function') form'', there is one more additional general
 form for @(':clause-processor') hint: a symbol, as follows.</p>

 @({
 :clause-processor F
 })

 <p>This expands to a basic form as follows, depending on @('F').</p>

 <ul>

 <li>If @('F') is a macro with one required argument or a function symbol with
 one argument:<br/>
 @(':clause-processor (F clause)')</li>

 <li>If @('F') is a macro with two required arguments or a function symbol with
 two arguments:<br/>
 @(':clause-processor (F clause nil)')</li>

 <li>If @('F') is a function symbol with inputs of the form [3] above, that is,
 with input signature @('(nil nil st_1 ... st_k)'):<br/>
 @(':clause-processor (F clause nil st_1 ... st_k)')</li>

 </ul>

 <p>For examples of these syntactic forms, see community book
 @('books/clause-processors/basic-examples.lisp')).  We turn now to discussion
 of when a @(':clause-processor') hint causes an abort.</p>

 <p>A @(':clause-processor') hint causes the proof to abort if the
 clauses-result is not a list of clauses, i.e., a list of (translated) @(see
 term) lists in the current logical @(see world).  This test is done explicitly
 every time a clause processor is run unless a @(':')@(tsee
 well-formedness-guarantee) has been provided with the @(':clause-processor')
 rule or @(tsee set-skip-meta-termp-checks) has been used with an active trust
 tag to skip the check at the user's risk.</p>

 <p>The proof also aborts when the clause-processor function returns at least
 two values and the first value returned &mdash; the ``@('erp')'' value from
 case [3] above &mdash; is not @('nil').  In that case, @('erp') is used for
 printing an error message as follows: if it is a string, then that string is
 printed; but if it is a non-empty true list whose first element is a string,
 then it is printed as though by @('(fmt ~@0 (list (cons #\\0 erp)) ...)') (see
 @(see fmt)).  Otherwise, a non-@('nil') @('erp') value causes a generic error
 message to be printed.</p>

 <p>If there is no error as above, but the @('CL-PROC') call returns a clause
 list whose single element is equal to the input clause, then the hint is
 ignored since we are left with the goal with which we started.  In that case,
 the other prover processes are then applied as usual (see @(see
 hints-and-the-waterfall)).</p>

 <p>You can see all current @(':clause-processor') rules by issuing the
 following command: @('(print-clause-processor-rules)').</p>

 <p>The following paper discusses ACL2 clause-processors at a high level
 suitable for a non-ACL2 audience:</p>

 <blockquote>

 <p>M. Kaufmann, J S. Moore, S. Ray, and E. Reeber, ``Integrating External
 Deduction Tools with ACL2.''  <i>Journal of Applied Logic</i> (Special Issue:
 Empirically Successful Computerized Reasoning), Volume 7, Issue 1, March 2009,
 pp. 3&ndash;25.  Also published online (DOI @('10.1016/j.jal.2007.07.002')).
 Preliminary version in: Proceedings of the 6th International Workshop on the
 Implementation of Logics (IWIL 2006) (C. Benzmueller, B. Fischer, and
 G. Sutcliffe, editors), <a href='http://ceur-ws.org/Vol-212/'>CEUR Workshop
 Proceedings Vol. 212</a>, Phnom Penh, Cambodia, pp. 7&ndash;26, November
 2006.</p></blockquote>

 ")

(defxdoc clear-hash-tables
  :parents (memoize) ; skip programming as parent, since this is deprecated
  :short "Deprecated feature"
  :long "<p>Deprecated.  Calls @(tsee clear-memoize-tables) and then @(tsee
 hons-clear) or @(tsee hons-wash), whichever makes sense for the underlying
 Common Lisp.</p>")

(defxdoc clear-memoize-statistics
  :parents (memoize)
  :short "Clears all profiling info displayed by @('(')@(tsee
  memoize-summary)@(')')"
  :long "<p>Logically, this function just returns @('nil').  It clears all
 profiling info displayed by @('(')@(tsee memoize-summary)@(')')</p>

 @(def clear-memoize-statistics)")

(defxdoc clear-memoize-table
  :parents (memoize)
  :short "Forget values remembered for the given function"
  :long "<p>This function returns its argument, @('fn'), unchanged.  The values
 memoized for @('fn') are forgotten.</p>

 @(def clear-memoize-table)")

(defxdoc clear-memoize-tables
  :parents (memoize)
  :short "Forget values remembered for all the memoized functions"
  :long "<p>@('Clear-memoize-tables') is a logical no-op.  All memoized values
 are forgotten.  It returns @('nil'), invoking @(tsee clear-memoize-table) for
 each memoized function.</p>

 @(def clear-memoize-tables)")

(defxdoc close-trace-file
  :parents (trace)
  :short "Stop redirecting trace output to a file"
  :long "@({
  General Form:
  (close-trace-file) ; trace output is no longer redirected to a file
 })

 <p>Output from @(tsee trace$) normally goes to the screen, or more precisely,
 @(tsee standard-co).  It can be redirected to a file; see @(see
 open-trace-file).  Use @('close-trace-file') to redirect trace output to
 @(tsee standard-co).</p>")

(defxdoc code-char
  :parents (characters numbers acl2-built-ins)
  :short "The character corresponding to a given numeric code"
  :long "<p>This function maps a numeric code to the corresponding character,
  for example: @('(code-char 65)') evaluates to @('#\\A').  See @(tsee
  char-code) for a sort of inverse function, which maps a character to its
  code.</p>

 <p>Completion Axiom (@('completion-of-code-char')):</p>

 @({
  (equal (code-char x)
         (if (and (integerp x)
                  (>= x 0)
                  (< x 256))
             (code-char x)
           (code-char 0)))
 })

 <p>@(see Guard) for @('(code-char x)'):</p>

 @({
  (and (integerp x)
       (>= x 0)
       (< x 256))
 })

 <p>ACL2 supports 8-bit @(see characters).  Inputs not between @('0') and
 @('255') are treated as @('0').</p>")

(defxdoc coerce

; Jared Davis has written a faster version of coercing a character list to a
; string, which is displayed just below.  But we (the ACL2 authors) have
; decided not to try to meddle with the underlying Lisp implementation of
; coerce (though on 2/27/09 Bob Boyer temporarily added a patch from Gary Byers
; to hons-raw.lisp to speed this up for CCL).  Jared adds (6/30/09) that CCL
; now handles coerce efficiently, both to strings and to lists.

;  (defun my-coerce (chars)
;    (let* ((length (the integer (length (the list chars))))
;           (str    (the vector (make-string (the integer length))))
;           (i      (the integer 0)))
;      (loop for char in chars
;            do
;            (setf (aref (the vector str) (the integer i))
;                  (the character char))
;            (incf (the integer i)))
;      str))

  :parents (strings characters acl2-built-ins)
  :short "Coerce a character list to a string and a string to a list"
  :long "<p>Completion Axiom (@('completion-of-coerce')):</p>

 @({
  (equal (coerce x y)
         (cond
          ((equal y 'list)
           (if (stringp x)
               (coerce x 'list)
             nil))
          (t
           (coerce (make-character-list x) 'string))))
 })

 <p>@(see Guard) for @('(coerce x y)'):</p>

 @({
  (if (equal y 'list)
      (stringp x)
    (if (equal y 'string)
        (character-listp x)
      nil))
 })

 <p>Also see community book @('books/misc/fast-coerce.lisp'), contributed by
 Jared Davis, for a version of @('coerce') that may be faster for Common Lisp
 implementations other than CCL 1.3 or later, if the second argument is
 @(''list') (for coercing a string to a list).</p>

 <h4>Logical Note</h4>

 <p>The function @('coerce') can be viewed as the constructor for strings.  As
 discussed in Section 7 of \"<a
 href='http://www.cs.utexas.edu/users/moore/publications/km97a.pdf'>A Precise
 Description of the ACL2 Logic</a>\" (Matt Kaufmann and J Moore, April, 1998),
 a string may be built by coercing its list of characters: for example,
 @('\"abc\"') is @('(coerce '(#\\a #\\b #\\c) 'string)').  More precisely,
 @('\"abc\"') is an abbreviation for @('(coerce '(#\\a #\\b #\\c) 'string)'),
 where even more pedantically, @(''(#\\a #\\b #\\c)') is an abbreviation for
 @('(cons '#\\a (cons '#\\b (cons '#\\c 'nil)))').</p>")

(defxdoc command
  :parents (history)
  :short "Forms you type at the top-level, but..."
  :long "<p>...the word ``command'' usually refers to a top-level form whose
 evaluation produces a new logical @(see world).</p>

 @({
  Typical commands are:
  (defun foo (x) (cons x x))
  (defthm consp-foo (consp (foo x)))
  (defrec pair (hd . tl) nil)
 })

 <p>The first two forms are examples of commands that are in fact primitive
 @(see events).  See @(see events).  @('Defrec'), on the other hand, is a macro
 that expands into a @(tsee progn) of several primitive @(see events).  In
 general, a @(see world) extending command generates one or more @(see
 events).</p>

 <p>Both @(see events) and commands leave landmarks on the @(see world) that
 enable us to determine how the given @(see world) was created from the
 previous one.  Most of your interactions will occur at the command level,
 i.e., you type commands, you print previous commands, and you undo back
 through commands.  Commands are denoted by command descriptors.  See @(see
 command-descriptor).</p>")

(defxdoc command-descriptor
  :parents (history)
  :short "An object describing a particular @(see command) typed by the user"
  :long "@({
  Examples:

  :max      ; the command most recently typed by the user
  :x        ; synonymous with :max
  (:x -1)   ; the command before the most recent one
  (:x -2)   ; the command before that
  :x-2      ; synonymous with (:x -2)
  5         ; the fifth command typed by the user
  1         ; the first command typed by the user
  0         ; the last command of the system initialization
  -1        ; the next-to-last initialization command
  :min      ; the first command of the initialization
  :start    ; the last command of the initial ACL2 logical world
  fn        ; the command that introduced the logical name fn
  (:search (defmacro foo-bar))
            ; the first command encountered in a search from :max to
            ; 0 that either contains defmacro and foo-bar in the
            ; command form or contains defmacro and foo-bar in some
            ; event within its block.
 })

 <p>The recorded @(see history) of your interactions with the top-level ACL2
 @(see command) loop is marked by the @(see command)s you typed that changed
 the logical @(see world).  Each such @(see command) generated one or more
 @(see events), since the only way for you to change the logical @(see world)
 is to execute an event function.  See @(see command) and see @(see events).
 We divide @(see history) into ``@(see command) blocks,'' grouping together
 each @(see world) changing @(see command) and its @(see events).  A ``@(see
 command) descriptor'' is an object that can be used to describe a particular
 @(see command) in the @(see history) of the ongoing session.</p>

 <p>Each @(see command) is assigned a unique integer called its ``@(see
 command) number'' which indicates the @(see command)'s position in the
 chronological ordering of all of the @(see command)s ever executed in this
 session (including those executed to initialize the system).  We assign the
 number 1 to the first @(see command) you type to ACL2.  We assign 2 to the
 second and so on.  The non-positive integers are assigned to ``prehistoric''
 @(see command)s, i.e., the @(see command)s used to initialize the ACL2 system:
 0 is the last @(see command) of the initialization, -1 is the one before that,
 etc.</p>

 <p>The legal @(see command) descriptors are described below.  We use @('n') to
 denote any integer, @('sym') to denote any logical name (see @(see
 logical-name)), and @('cd') to denote, recursively, any @(see command)
 descriptor.</p>

 @({
   command                   command
  descriptor                described

  :max   -- the most recently executed command (i.e., the one with
            the largest command number)
  :x     -- synonymous with :max
  :x-k   -- synonymous with (:x -k), if k is an integer and k>0
  :min   -- the earliest command (i.e., the one with the smallest
            command number and hence the first command of the system
            initialization)
  :start -- the last command when ACL2 starts up
  n      -- command number n  (If n is not in the
            range :min<=n<=:max, n is replaced by the nearest of :min
            and :max.)
  sym    -- the command that introduced the logical name sym
  (cd n) -- the command whose number is n plus the command number of
            the command described by cd
  (:search pat cd1 cd2)
            In this command descriptor, pat must be either an atom or
            a true list of atoms and cd1 and cd2 must be command
            descriptors.  We search the interval from cd1 through cd2
            for the first command that matches pat.  Note that if cd1
            occurs chronologically after cd2, the search is
            ``backwards'' through history while if cd1 occurs
            chronologically before cd2, the search is ``forwards''.  A
            backwards search will find the most recent match; a
            forward search will find the chronologically earliest
            match.  A command matches pat if either the command form
            itself or one of the events in the block contains pat (or
            all of the atoms in pat if pat is a list).
  (:search pat)
            the command found by (:search pat :max 0), i.e., the most
            recent command matching pat that was part of the user's
            session, not part of the system initialization.
 })")

(defxdoc command-line
  :parents (interfacing-tools)
  :short "Handling of command-line arguments when ACL2 is invoked"
  :long "<p>You may provide command-line arguments when invoking ACL2, which
 are passed to the host Lisp.  For more information on this topic, along with a
 discussion of how to save an ACL2 executable that avoids passing command-line
 arguments to the host Lisp, see @(see save-exec).</p>")

(defxdoc common-lisp
  :parents (about-acl2)
  :short "Relation to Common Lisp, including deviations from the spec"
  :long "<p>ACL2 is a logic, a theorem prover, and a programming language based
 on Common Lisp.  A connection with Common Lisp is established with guards (see
 @(see guard)).</p>

 <p>However, here we document potential deviations from Common Lisp semantics
 even in the presence of verified guards.  Our view is that these deviations
 are extremely unlikely to manifest; indeed, as of this writing we are unaware
 of any cases in which these issues arise in practice.  However, we feel
 obligated to acknowledge their possibility, which could result in surprises
 during evaluation or even proof.</p>

 <p>The Common Lisp spec allows certain predicates to return what it calls
 ``generalized Booleans,'' which are really arbitrary values that are to be
 viewed as either @('nil') or non-@('nil').  However, in ACL2 these functions
 are assumed to return @('nil') or @('t').  For details, see @(see
 generalized-booleans).</p>

 <p>The execution of forms with @(':')@(tsee program) mode functions can result
 in calls of functions on arguments that do not satisfy their @(see guard)s.
 In practice, this simply causes hard Lisp errors.  But in principle one could
 imagine a damaged Lisp image that operates incorrectly.  See @(see
 defun-mode-caveat).</p>

 <p>The Common Lisp spec, specifically
 Section @(`(:raw (clhs  \"Body/03_bbc.htm\" \"Section 3.2.2.3\"))`)
 of the @(`(:raw (clhs \"Front\" \"Common Lisp Hyperspec\"))`),
 allows for undefined results when a function is ``multiply defined'' in a
 compiled file.  ACL2 allows redundant @(tsee defun)s in a book, and in general
 @(see books) are compiled by @('certify-book') (but see @(see certify-book)
 and see @(see compilation) for how to control such compilation).  Moreover,
 ACL2 provides a redefinition capability (see @(see ld-redefinition-action) and
 see @(see redef)), and the above section also allows for undefined results
 when a function is defined in a compiled file and then redefined,
 presumably (for example) because of inlining.</p>")

(defxdoc community-books
  :parents (books)
  :short "Libraries of ACL2 @(see books) developed by the ACL2 community."

  :long "<p>ACL2 @(see books) are files of ACL2 @(see events) like definitions
 and theorems.</p>

 <p>The ACL2 <b>Community Books</b> are the canonical set of open-source books
 for ACL2, developed since the early 1990s by members of the ACL2 community.
 They include libraries for reasoning in many domains, macro libraries for more
 quickly writing and documenting code, interfacing tools for connecting ACL2 to
 other systems, productivity tools for better proof automation and debugging,
 and specialty libraries for areas like hardware verification.</p>

 <p>From the <a href='https://github.com/acl2/acl2/'>github ACL2 project</a> web
 site you can:</p>

 <ul>
 <li>Download the Community Books;</li>
 <li>Learn how to contribute books to the ACL2 community; and</li>
 <li>Obtain updates between ACL2 releases.</li>
 </ul>

 <p>See @(see git-quick-start) for information about how to download the
 ``bleeding edge'' ACL2 system and community books.</p>")

(defxdoc comp
  :parents (compilation events acl2-built-ins)
  :short "Compile some ACL2 functions"
  :long "<p>NOTE: @('Comp') is a no-op if explicit compilation is suppressed;
 see @(see compilation).  The documentation here assumes that this is not the
 case.  See @(see evaluation) for background on executable-counterpart and
 submitted functions.</p>

 @({
  Examples:
  :comp t          ; compile all uncompiled ACL2 functions
  (comp t)         ; same as above, but can be put into a book
  (comp :exec)     ; compile all uncompiled executable-counterpart definitions
  :comp foo        ; compile the defined function foo (both its submitted and
                   ; executable-counterpart functions)
  :comp (:raw foo) ; compile the submitted function for the defined function foo
                   ; but not the corresponding executable-counterpart
  :comp (foo bar)  ; compile the defined functions foo and bar
  :comp (foo (:raw bar))  ; compile the defined functions foo and bar, but for
                          ; bar do not compile the executable-counterpart

  General Form:
  :comp specifier
  where specifier is one of the following:

    t                     compile all user-defined ACL2 functions that are
                            currently uncompiled (redefined built-in functions
                            are not recompiled)
    :exec                 same as t, except that only executable-counterparts
                            are compiled (see below), not submitted definitions
    :raw                  same as t, except that only submitted definitions are
                            compiled, not executable-counterparts
    (name-1 ... name-k)   a non-empty list of names of functions defined by
                            DEFUN in ACL2, except that each name-i can be of
                            the form (:raw sym) or (:exec sym), where sym is
                          the name of such a function
    name                  same as (name)
 })

 <p>When you define a function in ACL2, you are really causing two definitions
 to be made ``under the hood'' in Common Lisp: the definition is submitted
 explicitly to raw Lisp, but so is a corresponding executable-counterpart; see
 @(see evaluation).  If guards have not been verified, then only the
 executable-counterpart will be evaluated; see @(see evaluation) and see @(see
 guards-and-evaluation), in particular the section titled ``Guards and
 evaluation V: efficiency issues''.</p>

 <p>Thus, if you are not verifying @(see guard)s and you want the benefit of
 Lisp compilation for speed and space efficiency, then you may want to place
 the form @('(comp :exec)') in your @(see books).</p>

 <p>Generally it is not necessary to place the form @('(comp t)'), or the form
 @('(comp :raw)'), in a book, because @(tsee certify-book) compiles the raw
 Lisp definitions anyhow, by default.  But you may wish to put @('(comp t)') or
 @('(comp fn1 fn2 ... fnk)') in a book when such a form precedes expensive
 calls of functions, for example for proofs involving calls of functions on
 large constants, or to support computationally expensive macroexpansion.</p>

 <p>As suggested by the examples above, if a function specifier is of the form
 @('(:raw fn)'), then @('fn') will be compiled in raw Common Lisp but its
 corresponding executable-counterpart definition will not be compiled; and for
 @('(:exec fn)'), it's the other way around.</p>

 <p>The use of @(':comp') may create various files whose names start with
 ``@('TMP*')'', but it then deletes them.  If you want to save these files,
 evaluate @('(assign keep-tmp-files t)').</p>

 <p>Also see @(see set-compile-fns) for a way to compile each function as it is
 defined.  But note that @('set-compile-fns') is ignored during @(tsee
 include-book).</p>

 <p>Note that if functions are traced (see @(see trace$)), then @('comp') will
 first untrace the functions that are to be compiled, then will do the
 compile(s), and finally will re-trace the functions that it untraced (using
 their original trace specs).  In particular, if you have traced a function and
 then you compile it using @(':comp'), the resulting traced function will be
 compiled as well unless you specified @(':compile nil') in your trace spec;
 and after you untrace the function it will definitely run compiled.</p>

 <p>We conclude with a technical remark only for those who use trust tags to
 write raw Lisp code.  @(':Comp') generally creates files to compile unless it
 is given a single function to compile.  Those files contain the ACL2
 definitions of all functions to compile, omitting those in the lists obtained
 by evaluating the forms @('(@ logic-fns-with-raw-code)') and @('(@
 program-fns-with-raw-code)').  @(':Comp') skips compilation for functions that
 are already compiled, as is typically the case when you redefine functions in
 raw Lisp using @(see include-raw).  But if you define interpreted (as opposed
 to compiled) functions with raw Lisp code, say by using trust tags (see @(see
 defttag)) and @(tsee progn!), then you are advised to add all such symbols to
 one of the lists stored in the two @(see state) globals above: to
 @('logic-fns-with-raw-code') if the function symbol is in @(':')@(tsee logic)
 mode, else to @('program-fns-with-raw-code').  Then, instead of the
 corresponding ACL2 definition (without raw Lisp code) being written to a file,
 the function symbol will be passed directly to the Lisp @('compile') function.
 Note that the above two state globals are both untouchable, so you may need to
 deal with that before modifying them, for example as follows (also see @(see
 remove-untouchable)).</p>

 @({
  (defttag t)
  (state-global-let*
   ((temp-touchable-vars t set-temp-touchable-vars))
   (progn! (f-put-global 'logic-fns-with-raw-code
                         (cons 'my-fn (@ logic-fns-with-raw-code))
                         state)))
 })")

(defxdoc comp-gcl
  :parents (compilation acl2-built-ins)
  :short "Compile some ACL2 functions leaving .c and .h files"
  :long "<p>@('Comp-gcl') is for use by experts who want to examine the results
 of GCL compilation, and it may only be used with ACL2 implementations built on
 top of GCL.  It takes exactly the same arguments as @(tsee comp), and has the
 same basic functionality (see @(see comp)), but has two additional effects.
 First, files @('\"TMP.lisp\"') and @('\"TMP1.lisp\"') are always created, even
 when a single function is specified.  Second, @('comp-gcl') always leaves
 files @('\"TMP.c\"'), @('\"TMP.h\"'), @('\"TMP1.c\"'), and @('\"TMP1.h\"')
 when compilation is complete.</p>")

(defxdoc compilation
  :parents (programming)
  :short "Compiling ACL2 functions"
  :long "<p>ACL2 has several mechanisms to speed up the evaluation of function
 calls by <i>compiling</i> functions: see @(see comp), see @(see
 set-compile-fns), and see @(see certify-book).  The intention is that
 compilation never changes the value returned by a function call, though it
 could cause the call to succeed rather than fail, for example by avoiding a
 stack overflow.</p>

 <p>The @(tsee state) global variable @(''compiler-enabled') is set
 automatically when the system is built, and may depend on the underlying Lisp
 implementation.  (In order to disable the compiler at build time, which will
 defeat the speed-up but usually be pretty harmless when the host Lisp is CCL
 or SBCL, see the discussion of @('ACL2_COMPILER_DISABLED') in distributed file
 @('GNUmakefile').)  The value of @(''compiler-enabled'), as returned by @('(@
 compiler-enabled)'), can be @('t'), @(':books'), or @('nil').  If the value is
 @('nil'), then @(tsee include-book) and @(tsee certify-book) coerce their
 arguments @(':load-compile-file') and @('compile-flg') arguments
 (respectively) to @('nil').  Otherwise, the value is @(':books') or @('t') and
 there is no such coercion; but if the value is not @('t'), then @(tsee comp)
 and @(tsee set-compile-fns) are no-ops, which is probably desirable for Lisps
 such as CCL and SBCL that compile on-the-fly even when the compiler is not
 explicitly invoked.</p>

 <p>However, you may have reason to want to change the above (default)
 behavior.  To enable compilation by default for @(tsee certify-book) and
 @(tsee include-book) but not for @(tsee comp) or @(tsee set-compile-fns):</p>

 @({
  (set-compiler-enabled :books state)
 })

 <p>To enable compilation not only as above but also for @(tsee comp) and
 @(tsee set-compile-fns):</p>

 @({
  (set-compiler-enabled t state)
 })

 <p>To suppress compilation and loading of compiled files by @(tsee
 include-book) (for example, if you get a raw Lisp error such as ``Wrong FASL
 version''):</p>

 @({
  (set-compiler-enabled nil state)
 })

 <p>Remark for users of @(tsee make-event).  If @('set-compiler-enabled') is
 invoked during @('make-event') expansion, its effect on @(tsee state) global
 variable @(''compiler-enabled') will persist after evaluation completes for
 that @('make-event') form.  So for example, one might use the following idiom
 in a book so that for all books included on behalf of a given @(tsee
 include-book) form, no compiled files are loaded, but (optionally) no such
 effect takes place for later @('include-book') forms in that book.</p>

 @({
  (make-event
   (pprogn (f-put-global 'saved-compiler-enabled (@ compiler-enabled) state)
           (set-compiler-enabled nil state)
           (value '(value-triple nil)))
   :check-expansion t)
  (include-book \"my-book\")
  ; optional
  (make-event
   (pprogn (set-compiler-enabled (@ saved-compiler-enabled) state)
           (value '(value-triple nil)))
   :check-expansion t)
 })

 <p>Upon completion of an invocation of @(tsee include-book) or @(tsee
 certify-book), the value of @(tsee state) global variable
 @(''compiler-enabled') is restored to the value it had immediately before that
 invocation.</p>

 <p>See @(see book-compiled-file) for more discussion about compilation and
 @(see books).</p>

 <p>We close with a discussion of a feature that allows control over the
 loading of @('.port') files in close analogy to how loading of compiled files
 is controlled by @('set-compiler-enabled'), as described above.
 (See @(see uncertified-books) for a discussion of @('.port') files.)  A @(see
 state) global variable, @(''port-file-enabled') exists for this purpose, and
 it is set as follows.</p>

 @({
  (set-port-file-enabled t state)   ; permit loading of .port files (default)
  (set-port-file-enabled nil state) ; skip loading of .port files
 })

 <p>Just as described above for state global @('compiler-enabled'), the value
 of @(''port-file-enabled') persists after @(tsee make-event) expansion and is
 restored after @(tsee certify-book) and @(tsee include-book).  The idiom
 displayed above, for avoiding loading of compiled files, can be modified or
 extended in the obvious way to avoid loading of @('.port') files.</p>")

(defxdoc compiling-acl2p
  :parents (parallelism)
  :short "Compiling ACL2(p)"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).  See @(see parallelism-tutorial) for an introduction to parallel
 programming in ACL2.</p>

 <p>You can build an experimental version of ACL2 that supports parallel
 execution in the following host Common Lisp implementations:</p>

 <blockquote><p>* CCL (OpenMCL)</p>

 <p>* Lispworks 6.0</p>

 <p>* SBCL with threads (feature @(':sb-thread'))</p></blockquote>

 <p>The command below will compile ACL2 to support parallel execution,
 including parallel execution during proofs.  Any non-empty string may be used
 in place of @('t'), and the value of @('LISP') (shown here as @('ccl')) is any
 Lisp executable on which one can build ACL2(p) (see @(see parallelism)).</p>

 @({
  make ACL2_PAR=t LISP=ccl
 })

 <p>So for example, to make an executable image and also documentation (which
 will appear in subdirectories @('doc/EMACS') and @('doc/HTML')), using the
 Lisp executable @('ccl'):</p>

 @({
  make large DOC ACL2_PAR=t LISP=ccl
 })")

(defxdoc complex
  :parents (numbers acl2-built-ins)
  :short "Create an ACL2 number"
  :long "@({
  Examples:
  (complex x 3) ; x + 3i, where i is the principal square root of -1
  (complex x y) ; x + yi
  (complex x 0) ; same as x, for rational numbers x
 })

 <p>The function @('complex') takes two rational number arguments and returns
 an ACL2 number.  This number will be of type @('(complex rational)') [as
 defined in the Common Lisp language], except that if the second argument is
 zero, then @('complex') returns its first argument.  The function @(tsee
 complex-rationalp) is a recognizer for complex rational numbers, i.e. for ACL2
 numbers that are not rational numbers.</p>

 <p>The reader macro @('#C') (which is the same as @('#c')) provides a
 convenient way for typing in complex numbers.  For explicit rational numbers
 @('x') and @('y'), @('#C(x y)') is read to the same value as @('(complex x
 y)').</p>

 <p>The functions @(tsee realpart) and @(tsee imagpart) return the real and
 imaginary parts (respectively) of a complex (possibly rational) number.  So
 for example, @('(realpart #C(3 4)) = 3'), @('(imagpart #C(3 4)) = 4'),
 @('(realpart 3/4) = 3/4'), and @('(imagpart 3/4) = 0').</p>

 <p>The following built-in axiom may be useful for reasoning about complex
 numbers.</p>

 @({
  (defaxiom complex-definition
    (implies (and (real/rationalp x)
                  (real/rationalp y))
             (equal (complex x y)
                    (+ x (* #c(0 1) y))))
    :rule-classes nil)
 })

 <p>A completion axiom that shows what @('complex') returns on arguments
 violating its @(see guard) (which says that both arguments are rational
 numbers) is the following, named @('completion-of-complex').</p>

 @({
  (equal (complex x y)
         (complex (if (rationalp x) x 0)
                  (if (rationalp y) y 0)))
 })")

(defxdoc complex-rationalp
  :parents (numbers acl2-built-ins)
  :short "Recognizes complex rational numbers"
  :long "@({
  Examples:
  (complex-rationalp 3)       ; nil, as 3 is rational, not complex rational
  (complex-rationalp #c(3 0)) ; nil, since #c(3 0) is the same as 3
  (complex-rationalp t)       ; nil
  (complex-rationalp #c(3 1)) ; t, as #c(3 1) is the complex number 3 + i
 })

 <p>See @(see complex) for more about complex rationals in ACL2.</p>")

(defxdoc complex/complex-rationalp
  :parents (numbers acl2-built-ins)
  :short "Recognizer for complex numbers"
  :long "<p>For most ACL2 users, this is a macro abbreviating
 @('complex-rationalp'); see @(see complex-rationalp).  In ACL2(r) (see @(see
 real)), a complex number @('x') may have irrational real and imaginary parts.
 This macro abbreviates the predicate @('complexp') in ACL2(r), which holds for
 such @('x').  Most ACL2 users can ignore this macro and use @(tsee
 complex-rationalp) instead.  Some community books use
 @('complex/complex-rationalp') so that they are suitable for ACL2(r) as
 well.</p>")

(defxdoc compound-recognizer
  :parents (rule-classes)
  :short "Make a rule used by the typing mechanism"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 @({
  Examples:
  (defthm alistp-implies-true-listp-compound-recognizer
    (implies (alistp x)                 ; When (alistp x) is assumed true, add
             (true-listp x))            ; the additional hypothesis that x is
    :rule-classes :compound-recognizer) ; of primitive type true-listp.

  (defthm natp-compound-recognizer      ; See discussion below.
    (equal (natp x)
           (and (integerp x)
                (<= 0 x)))
    :rule-classes :compound-recognizer)
 })

 <p>Before presenting the General Forms, we start with a motivating example:
 the second @(tsee defthm) form above, which provides a nice example of a
 @(':compound-recognizer') rule that is built into ACL2.  To see how this rule
 might be useful, consider the following (admittedly very simple) @(see
 events).</p>

 @({
  (defun triple (x)
    (* 3 x))

  (defthm triple-preserves-integerp
    (implies (integerp x)
             (integerp (triple x))))

  (in-theory (disable triple natp))
 })

 <p>If the above @(':compound-recognizer') rule is disabled, then the following
 trivial theorem fails as shown; we explain below.</p>

 @({
  (thm (implies (natp x)
                (integerp (triple x)))
    :hints ((\"Goal\" :in-theory (disable natp-compound-recognizer))))
 })

 <p>The problem is that when ACL2 tries to rewrite the term @('(integerp
 (triple x))') using the @(':')@(tsee rewrite) rule
 @('triple-preserves-integerp'), it needs to rewrite the hypothesis
 @('(integerp x)') to @('t'), but instead what is known is @('(natp x)').  If
 we remove the hint, then the proof succeeds because the above
 @(':compound-recognizer') rule tells ACL2 that when assuming @('(natp x)') to
 be true, it should actually assume both @('(integerp x)') and @('(<= 0 x)') to
 be true.</p>

 @({
  General Forms:
  (implies (fn x) concl)               ; (1)
  (implies (not (fn x)) concl)         ; (2)
  (and (implies (fn x) concl1)         ; (3)
       (implies (not (fn x)) concl2))
  (if (fn x) concl1 concl2)            ; (4)
  (iff (fn x) concl)                   ; (5)
  (equal (fn x) concl)                 ; (6)
 })

 <p>where @('fn') is a Boolean valued function of one argument, @('x') is a
 variable symbol, and the system can deduce some restriction on the primitive
 type of @('x') from the assumption that @('concl') holds.  The last
 restriction is vague but one way to understand it is to strengthen it a little
 to ``and @('concl') is a non-tautological disjunction of the primitive type
 recognizers listed below.''</p>

 <p>The primitive ACL2 types and a suitable primitive recognizing expression
 for each are listed below.</p>

 @({
    type                suitable primitive recognizer

    zero                    (equal x 0)
    one                     (equal x 1)
    negative integers       (and (integerp x) (< x 0))
    positive integers > 1   (and (integerp x) (> x 1))
    negative ratio          (and (rationalp x)
                                 (not (integerp x))
                                 (< x 0))
    positive ratio          (and (rationalp x)
                                 (not (integerp x))
                                 (> x 0))
    complex rational        (complex-rationalp x)
    nil                     (equal x nil)
    t                       (equal x t)
    other symbols           (and (symbolp x)
                                 (not (equal x nil))
                                 (not (equal x t)))
    proper conses           (and (consp x)
                                 (true-listp x))
    improper conses         (and (consp x)
                                 (not (true-listp x)))
    strings                 (stringp x)
    characters              (characterp x)
 })

 <p>Thus, since the naturals comprise the types @('zero'), @('one'), and
 @('positive integers > 1'), a suitable @('concl') to recognize the naturals
 would be</p>

 @({
    (or (equal x 0)
        (equal x 1)
        (and (integerp x) (> x 1)))
 })

 <p>However, it turns out that we also permit @('(and (integerp x) (>= x 0))'),
 i.e. @('concl') doesn't literally need to be formed as a direct disjunction of
 terms from the table above.</p>

 <p>Similarly, the true-lists could be specified by</p>

 @({
    (or (equal x nil)
        (and (consp x)
             (true-listp x)))
 })

 <p>but we in fact allow @('(true-listp x)') as well.  When time permits we
 will document more fully what is allowed or implement a macro that permits
 direct specification of the desired type in terms of the primitives.</p>

 <p>There are essentially four forms of @(':compound-recognizer') rules, as the
 forms labeled (3) and (4) above are equivalent, as are those labeled (5) and
 (6).  We explain how such rules are used by considering the individual
 forms.</p>

 <p>Consider form (1), @('(implies (fn x) concl)').  The effect of such a rule
 is that when the rewriter assumes @('(fn x)') true, as it would while diving
 through @('(if (fn x) xxx ...)') to rewrite @('xxx'), it restricts the type of
 @('x') as specified by @('concl').  For example, if @('concl') is the term
 @('(integerp x)'), then when rewriting @('xxx'), @('x') will be assumed to be
 an integer.  However, when assuming @('(fn x)') false, as necessary in @('(if
 (fn x) ... xxx)'), the rule permits no additional assumptions about the type
 of @('x').  For example, if @('fn') is @('primep'), i.e., the predicate that
 recognizes prime numbers, then @('(implies (primep x) (and (integerp x) (>= x
 0)))') is a compound recognizer rule of the first form.  When @('(primep x)')
 is assumed true, the rewriter gains the additional information that @('x') is
 a natural number.  When @('(primep x)') is assumed false, no additional
 information is gained &mdash; since @('x') may be a non-prime natural or may
 not even be a natural.</p>

 <p>Form (2) is the symmetric case, when assuming @('(fn x)') false permits
 type restrictions on @('x') but assuming @('(fn x)') true permits no such
 restrictions.  For example, if we defined @('exprp') to be the recognizer for
 well-formed expressions for some language in which all symbols, numbers,
 character objects and strings were well-formed &mdash; e.g., the
 well-formedness rules only put restrictions on expressions represented by
 @(tsee consp)s &mdash; then the theorem @('(implies (not (exprp x)) (consp
 x))') is a rule of the second form.  Assuming @('(exprp x)') true tells us
 nothing about the type of @('x'); assuming it false tells us @('x') is a
 @(tsee consp).</p>

 <p>Forms (3) and (4), which are really equivalent, address themselves to the
 case where one type may be deduced from @('(fn x)') and a generally unrelated
 type may be deduced from its negation.  If we modified the expression
 recognizer above so that character objects are illegal, then rules of the
 forms (3) and (4) are</p>

 @({
  (and (implies (exprp x) (not (characterp x)))
       (implies (not (exprp x)) (or (consp x) (characterp x)))).
  (if (exprp x)
      (not (characterp x))
    (or (consp x) (characterp x)))
 })

 <p>Finally, rules of forms (5) and (6) address the case where @('fn')
 recognizes all and only the objects whose type is described.  In these cases,
 @('fn') is really just a new name for some ``compound recognizers.''  The
 classic example is @('(booleanp x)'), which is just a handy combination of two
 primitive types:</p>

 @({
  (iff (booleanp x) (or (equal x t) (equal x nil))).
 })

 <p>Often it is best to disable @('fn') after proving that it is a compound
 recognizer, since otherwise the term @('(fn x)') will be expanded and thus
 disappear.</p>

 <p>Every time you prove a new compound recognizer rule about @('fn') it
 overrides all previously proved compound recognizer rules about @('fn').
 Thus, if you want to establish the type implied by @('(fn x)') and you want to
 establish the type implied by @('(not (fn x))'), you must prove a compound
 recognizer rule of the third, fourth, fifth, or sixth forms.  Proving a rule
 of the first form followed by one of the second only leaves the second fact in
 the database.</p>

 <p>Compound recognizer rules can be disabled with the effect that older rules
 about @('fn'), if any, are exposed.</p>

 <p>If you prove more than one compound recognizer rule for a function, you may
 see a <b>warning</b> message to the effect that the new rule is not as
 ``restrictive'' as the old.  That is, the new rules do not give the rewriter
 strictly more type information than it already had.  The new rule is stored
 anyway, overriding the old, if enabled.  You may be playing subtle games with
 enabling or rewriting.  But two other interpretations are more likely, we
 think.  One is that you have forgotten about an earlier rule and should merely
 print it out to make sure it says what you intend, and then discard your new
 rule.  The other is that you meant to give the system more information and the
 system has simply been unable to extract the intended type information from
 the term you placed in the conclusion of the new rule.  Given our lack of
 specificity in saying how type information is extracted from rules, you can
 hardly blame yourself for this problem.  Sorry.  If you suspect you've been
 burned this way, you should rephrase the new rule in terms of the primitive
 recognizing expressions above and see if the warning is still given.  It would
 also be helpful to let us see your example so we can consider it as we
 redesign this stuff.</p>

 <p>Compound recognizer rules are similar to @(':')@(tsee forward-chaining)
 rules in that the system deduces new information from the act of assuming
 something true or false.  If a compound recognizer rule were stored as a
 forward chaining rule it would have essentially the same effect as described,
 when it has any effect at all.  The important point is that @(':')@(tsee
 forward-chaining) rules, because of their more general and expensive form, are
 used ``at the top level'' of the simplification process: we forward chain from
 assumptions in the goal being proved.  But compound recognizer rules are built
 in at the bottom-most level of the simplifier, where type reasoning is
 done.</p>

 <p>All that said, compound recognizer rules are a rather fancy, specialized
 mechanism.  It may be more appropriate to create @(':')@(tsee
 forward-chaining) rules instead of @(':compound-recognizer') rules.</p>")

(defxdoc compress1
  :parents (arrays acl2-built-ins)
  :short "Remove irrelevant pairs from a 1-dimensional array"
  :long "@({
  Example Form:
  (compress1 'delta1 a)

  General Form:
  (compress1 name alist)
 })

 <p>where @('name') is a symbol and @('alist') is a 1-dimensional array,
 generally named @('name').  See @(see arrays) for details.  Logically
 speaking, this function removes irrelevant pairs from @('alist'), possibly
 shortening it.  The function returns a new array, @('alist''), with the same
 @(tsee header) (including name and dimension) as @('alist'), that, under
 @(tsee aref1), is everywhere equal to @('alist').  That is, @('(aref1 name
 alist' i)') is @('(aref1 name alist i)'), for all legal indices @('i').
 @('Alist'') may be shorter than @('alist') and the non-irrelevant pairs may
 occur in a different order than in @('alist').</p>

 <p>Practically speaking, this function plays an important role in the
 efficient implementation of @(tsee aref1).  In addition to creating the new
 array, @('alist''), @('compress1') makes that array the ``semantic value'' of
 @('name') and allocates a raw lisp array to @('name').  For each legal index,
 @('i'), that raw lisp array contains @('(aref1 name alist' i)') in slot
 @('i').  Thus, subsequent @(tsee aref1) operations can be executed in
 virtually constant time provided they are given @('name') and the @('alist'')
 returned by the most recently executed @('compress1') or @(tsee aset1) on
 @('name').  See @(see arrays).</p>

 <p>In general, @('compress1') returns an alist whose @(tsee cdr) is an
 association list whose keys are nonnegative integers in ascending order.
 However, if the @(tsee header) specifies an @(':order') of @('>') then the
 keys will occur in descending order, and if the @(':order') is @(':none') or
 @('nil') then the keys will not be sorted, i.e., @('compress1') is logically
 the identity function (though it still attaches an array under the hood).
 Note however that a @(tsee compress1) call is replaced by a hard error if the
 header specifies an @(':order') of @(':none') or @('nil') and the array's
 length exceeds the @(tsee maximum-length) field of its @(tsee header).</p>

 @(def compress1)")

(defxdoc compress2
  :parents (arrays acl2-built-ins)
  :short "Remove irrelevant pairs from a 2-dimensional array"
  :long "@({
  Example Form:
  (compress2 'delta1 a)

  General Form:
  (compress2 name alist)
 })

 <p>where @('name') is a symbol and @('alist') is a 2-dimensional array,
 generally named @('name').  See @(see arrays) for details.  Logically
 speaking, this function removes irrelevant pairs from @('alist'), possibly
 shortening it.  The function returns a new array, @('alist''), with the same
 @(tsee header) (including name and dimension) as @('alist'), that, under
 @(tsee aref2), is everywhere equal to @('alist').  That is, @('(aref2 name
 alist' i j)') is @('(aref2 name alist i j)'), for all legal indices @('i') and
 @('j').  @('Alist'') may be shorter than @('alist') and the non-irrelevant
 pairs may occur in a different order in @('alist'') than in @('alist').</p>

 <p>Practically speaking, this function plays an important role in the
 efficient implementation of @(tsee aref2).  In addition to creating the new
 array, @('alist''), @('compress2') makes that array the ``semantic value'' of
 @('name') and allocates a raw lisp array to @('name').  For all legal indices,
 @('i') and @('j'), that raw lisp array contains @('(aref2 name alist' i j)')
 in slot @('i'),@('j').  Thus, subsequent @(tsee aref2) operations can be
 executed in virtually constant time provided they are given @('name') and the
 @('alist'') returned by the most recently executed @('compress2') or @(tsee
 aset2) on @('name').  See @(see arrays).</p>

 @(def compress2)")

(defxdoc computed-hints
  :parents (hints)
  :short "Computing advice to the theorem proving process"
  :long "@({
  General Form of :hints:
  (hint1 hint2 ... hintk)
 })

 <p>Each element, hinti, must be either a common hint or a computed hint.</p>

 <p>A common hint is of the form</p>

 @({
  (goal-spec :key1 val1 ... :keyn valn)
 })

 <p>where @('goal-spec') is as specified in @(see goal-spec) and each
 @(':keyi') and @('vali') is as specified in @(see hints).  Among the ``common
 hints'' we include both the primitive hints and user-defined custom keyword
 hints (see @(see custom-keyword-hints)).</p>

 <p>A computed hint may be a function symbol, @('fn'), of three, four or seven
 arguments.  Otherwise, a computed hint is a term with the following
 properties:</p>

 <p>(a) the only free variables allowed in the term are @('ID'), @('CLAUSE'),
 @('WORLD'), @('STABLE-UNDER-SIMPLIFICATIONP'), @('HIST'), @('PSPV'), @('CTX'),
 and @(tsee STATE);</p>

 <p>(b) the output signature of the term is either @('(MV * * STATE)'), which
 is to be treated as an error triple (see below), or is @('*'), denoting a
 single non-@(see stobj) value; and</p>

 <p>(c) in the former case of (b) above, the term is single-threaded in @(tsee
 STATE).</p>

 <p>If a computed hint is a function symbol @('fn'), whose arity n is therefore
 three, four, or seven, then it is treated as the term resulting from applying
 that @('fn') to the first n variables shown in (a) above.  Notice that it must
 then return a single non-@(see stobj) value, not an error triple, since
 @('state') is not one of the first seven variables shown in (a).</p>

 <p>Note: Error triples are an ACL2 idiom for implementing ``errors''; see
 @(see error-triple).  If a computation returns @('(mv erp val state)') in a
 context in which ACL2 is respecting the error triple convention (see @(see
 ld-error-triples) and see @(see ld-error-action)), then an error is deemed to
 have occurred if @('erp') is non-@('nil').  The computation is expected to
 have printed an appropriate error message to @(tsee state) and further
 computation is aborted.  On the other hand, if a computation returns an error
 triple in which @('erp') is nil, then ``value'' of the computation is taken to
 be the second component, @('val'), of the triple (along with the possibly
 modified @(tsee state)), and computation continues.  For more information
 about programming with error triples, see @(see programming-with-state).</p>

 <p>The function symbol cases are treated as abbreviations of the term @('(fn
 ID CLAUSE WORLD)'), @('(fn ID CLAUSE WORLD STABLE-UNDER-SIMPLIFICATIONP)'), or
 @('(fn ID CLAUSE WORLD STABLE-UNDER-SIMPLIFICATIONP HIST PSPV CTX)') as
 appropriate for the arity of @('fn').  (Note that this tells you which
 argument of @('fn') is which.)  Moreover, in these cases the value returned
 must be a single ordinary (non-@(see stobj)) value, not an error triple.  In
 the discussion below we assume all computed hints are of the term form.
 Indeed, we almost assume all computed hints are of the 3 and 4 argument forms.
 We only comment briefly on the 7 argument form in @(see
 using-computed-hints-8).</p>

 <p>The semantics of a computed hint term is as follows.  On every subgoal, the
 term is evaluated in an environment in which the variables mentioned in (a)
 above are bound to context-sensitive values explained below.  Either the
 computed hint signals an error, in which the proof attempt aborts, or else it
 returns a value, @('val') and a new state, @(tsee state).  Any changes to
 those parts of @(tsee state) that affect logical soundness are undone; more
 specifically, the values of symbols (sometimes called ``state global
 variables'') in the list @('*protected-system-state-globals*') in the global
 table of the state (see @(see state)) are restored when changed during
 evaluation.  The value, @('val'), of a non-erroneous computed hint calculation
 is either @('nil'), which means the computed hint did not apply to the subgoal
 in question, or it is an alternating list of @(':keyi vali') pairs as
 specified in @(see hints).  With one exception, those new hints are applied to
 the given subgoal as though the user had typed them explicitly.</p>

 <p>The exception is that the first keyword in the returned @('val') is allowed
 to be @(':COMPUTED-HINT-REPLACEMENT').  Its value should be @('nil'), @('t'),
 or a list of terms.  If this keyword is not present, the default value of
 @('nil') is provided.  We explain @(':COMPUTED-HINT-REPLACEMENT') below.</p>

 <p>The evaluation of a hint term is done with guard checking turned off (see
 @(see set-guard-checking)); e.g., the form @('(car 23)') in a computed hint
 returns @('nil') as per the axioms.</p>

 <p>When a non-@('nil') value is returned, the keyword/value pairs (other than
 the optional @(':COMPUTED-HINT-REPLACEMENT')) are used as the hint for the
 subgoal in question.  Thus, your job as the programmer of computed hints is
 either to cause an error, typically by invoking @(tsee er), or to return a
 non-erroneous value triple whose value is the list of keys and values you
 would have typed had you supplied a common hint for the subgoal. (In
 particular, any theory expressions in it are evaluated with respect to the
 global current-theory, not whatever theory is active at the subgoal in
 question.)  If the generated list of keywords and values is illegal, an error
 will be signaled and the proof attempt will be aborted.</p>

 <p>The purpose of the @(':COMPUTED-HINT-REPLACEMENT') keyword and its value,
 @('chr'), is to change the list of hints.  If @('chr') is @('nil'), then the
 computed hint which was applied is removed from the list of hints that is
 passed down to the children of the subgoal in question.  This is the default.
 If @('chr') is @('t'), then the computed hint is left in the list of hints.
 This means that the same computed hint may act on the children of the subgoal.
 Otherwise, @('chr') must be a list of terms, each of which is treated as a
 computed hint.  The computed hint which was applied is deleted from the list
 of hints and the computed hints in @('chr') are added to the list of hints
 passed to the children of the subgoal.  The ability to generate new computed
 hints and pass them down allows strange and wonderful behavior.  Notice that
 certain hints, for example @(':in-theory') and @(':expand') hints, which
 appear in the computed hint will continue to take effect even when @('chr') is
 @('nil').  This might give one the false impression that a removed computed
 hint still hangs around.  See @(see hints-and-the-waterfall) for a more
 detailed discussion about how @(':in-theory') and other hints are handled in
 the waterfall.</p>

 <p>For these purposes, the goals produced by induction and the top-level goals
 of forcing rounds are not considered children; all original hints are
 available to them.</p>

 <p>Only the first hint applicable to a goal, as specified in the user-supplied
 list of @(':hints') followed by the @(tsee default-hints-table), will be
 applied to that goal.  (For an advanced exception, see @(see
 override-hints).)</p>

 <p>It remains only to describe the bindings of the free variables.</p>

 <p>Suppose the theorem prover is working on some clause, clause, named by some
 @(tsee goal-spec), e.g., \"Subgoal *1/2'''\" in some logical world, world.
 Corresponding to the printed @('goal-spec') is an internal data structure
 called a ``clause identifier'' id.  See @(see clause-identifier).</p>

 <p>In the case of a common hint, the hint applies if the goal-spec of the hint
 is the same as the goal-spec of the clause in question.</p>

 <p>In the case of a computed hint, the variable @('ID') is bound to the clause
 id, the variable @('CLAUSE') is bound to the (translated form of the) clause,
 and the variable @('WORLD') is bound to the current ACL2 world.  The variable
 @('STABLE-UNDER-SIMPLIFICATIONP') is bound to @('t') or @('nil').  It is bound
 to @('t') only if the clause is known to be stable under simplification.  That
 is, the simplifier has been applied to the clause and did not change it.  Such
 a clause is sometimes known as a ``simplification checkpoint.''  It is
 frequently useful to inject hints (e.g., to enable a rule or provide a
 @(':use') hint) only when the goal in question has stabilized.  If a hint is
 provided, the processing of the clause starts over with simplification.</p>

 <p>As for @('CTX') and @(tsee STATE), they are provided so that you can pass
 them to the @(tsee er) macro to print error messages.  We recommend not
 writing computed hints that otherwise change @(tsee STATE)!</p>

 <p>The remaining variables, @('HIST') and @('PSPV') are not documented yet.
 Only users familiar with the internals of ACL2 are likely to need them or
 understand their values.</p>

 <p>For some instruction about how to use computed hints, see @(see
 using-computed-hints).</p>")

(defxdoc concatenate
  :parents (lists strings acl2-built-ins)
  :short "Concatenate lists or strings together"
  :long "@({
  Examples:
  (concatenate 'string \"ab\" \"cd\" \"ef\")     ; equals \"abcdef\"
  (concatenate 'string \"ab\")               ; equals \"ab\"
  (concatenate 'list '(a b) '(c d) '(e f)) ; equals '(a b c d e f)
  (concatenate 'list)                      ; equals nil

  General Form:
  (concatenate result-type x1 x2 ... xn)
 })

 <p>where @('n >= 0') and either: @('result-type') is @(''')@(tsee string) and
 each @('xi') is a string; or @('result-type') is @(''')@(tsee list) and each
 @('xi') is a true list.  @('Concatenate') simply concatenates its arguments to
 form the result string or list.  Also see @(see append) and see @(see
 string-append).  (The latter immediately generates a call to @('concatenate')
 when applied to strings.)</p>

 <p>Note: We do *not* try to comply with the Lisp language's insistence that
 @('concatenate') copies its arguments.  Not only are we in an applicative
 setting, where this issue shouldn't matter for the logic, but also we do not
 actually modify the underlying lisp implementation of @('concatenate'); we
 merely provide a definition for it.</p>

 <p>@('Concatenate') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def concatenate)")

(defxdoc cond
  :parents (basics acl2-built-ins)
  :short "Conditional based on if-then-else"
  :long "<p>@('Cond') is the construct for IF, THEN, ELSE IF, ...  The test is
 against @('nil').  The argument list for @('cond') is a list of ``clauses'',
 each of which is a list.  In ACL2, clauses must have length 1 or 2.</p>

 <p>@('Cond') is a Common Lisp macro.  See any Common Lisp documentation for
 more information.</p>

 @(def cond)
 @(def cond-macro)")

(defxdoc congruence
  :parents (rule-classes)
  :short "The relations to maintain while simplifying arguments"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes
 and how they are used to build rules from formulas.  An example @(':')@(tsee
 corollary) formula from which a rule of class @(':congruence') might be built,
 assuming that @('set-equal') is a known @(see equivalence) relation, is:</p>

 @({
  Example:
  (defthm set-equal-implies-iff-memb-2
    (implies (set-equal x y)
             (iff (memb e x) (memb e y)))
    :rule-classes :congruence)
 })

 <p>Also see @(see defcong) and see @(see equivalence).</p>

 <p>NOTE: This topic discusses so-called ``classic'' congruence rules.  A more
 general class of rules, so-called ``patterned'' congruence rules, is
 supported.  We discuss only classic congruence rules below; for a discussion
 of patterned congruence rules, first read the present topic and then see @(see
 patterned-congruence).</p>

 @({
  General Form:
  (implies (equiv1 xk xk-equiv)
           (equiv2 (fn x1... xk       ...xn)
                   (fn x1... xk-equiv ...xn)))
 })

 <p>where @('equiv1') and @('equiv2') are known equivalence relations, @('fn')
 is an @('n-ary') function symbol other than @('if'), and the @('xi') and
 @('xk-equiv') are all distinct variables.  The effect of such a rule is to
 record that the @('equiv2')-equivalence of @('fn')-expressions can be
 maintained if, while rewriting the @('kth') argument position,
 @('equiv1')-equivalence is maintained.  See @(see equivalence) for a general
 discussion of the issues.  We say that @('equiv2'), above, is the ``outside
 equivalence'' in the rule and @('equiv1') is the ``inside equivalence for the
 @('k')th argument.''</p>

 <p>The macro form @('(defcong equiv1 equiv2 (fn x1 ... x1) k)') is an
 abbreviation for a @(tsee defthm) of rule-class @(':congruence') that attempts
 to establish that @('equiv2') is maintained by maintaining @('equiv1') in
 @('fn')'s @('k')th argument.  The @(tsee defcong) macro automatically
 generates the general formula shown above.  See @(see defcong).</p>

 <p>The @('memb') example above tells us that @('(memb e x)') is
 propositionally equivalent to @('(memb e y)'), provided @('x') and @('y') are
 @('set-equal').  The outside equivalence is @(tsee iff) and the inside
 equivalence for the second argument is @('set-equal').  If we see a @('memb')
 expression in a propositional context, e.g., as a literal of a clause or test
 of an @(tsee if) (but not, for example, as an argument to @(tsee cons)), we
 can rewrite its second argument maintaining @('set-equality').  For example, a
 rule stating the commutativity of @(tsee append) (modulo set-equality) could
 be applied in this context.  Since equality is a refinement of all equivalence
 relations, all equality rules are always available.  See @(see
 refinement).</p>

 <p>All known congruence rules about a given outside equivalence and @('fn')
 can be used independently.  That is, consider two congruence rules with the
 same outside equivalence, @('equiv'), and about the same function @('fn').
 Suppose one says that @('equiv1') is the inside equivalence for the first
 argument and the other says @('equiv2') is the inside equivalence for the
 second argument.  Then @('(fn a b)') is @('equiv') <tt>(fn a' b')</tt>
 provided @('a') is @('equiv1') to @('a'') and @('b') is @('equiv2') to
 @('b'').  This is an easy consequence of the transitivity of @('equiv').  It
 permits you to think independently about the inside equivalences.</p>

 <p>Furthermore, it is possible that more than one inside equivalence for a
 given argument slot will maintain a given outside equivalence.  For example,
 @('(length a)') is equal to <tt>(length a')</tt> if @('a') and @('a'') are
 related either by @('list-equal') or by @(tsee string-equal).  You may prove
 two (or more) congruence rules for the same slot of a function.  The result is
 that the system uses a new, ``generated'' equivalence relation for that slot
 with the result that rules of both (or all) kinds are available while
 rewriting.</p>

 <p>Congruence rules can be @(see disable)d.  For example, if you have two
 different inside equivalences for a given argument position and you find that
 the @(':')@(tsee rewrite) rules for one are unexpectedly preventing the
 application of the desired rule, you can disable the rule that introduced the
 unwanted inside equivalence.</p>

 <p><b>NOTE</b> however that unlike other rules, the tracking of congruence
 rules is incomplete.  Specifically: when congruence rules are used by the
 rewriter as it descends through terms, to maintain the generated equivalence
 relation used for rewriting, ACL2 does not track the congruence rules that are
 used, even though it is relevant that they are all @(see enable)d.  Congruence
 rules that are used only in this way will therefore not appear in the
 summary.</p>

 <p><i>Remark on Replacing IFF by EQUAL.</i> You may encounter a warning
 suggesting that a congruence rule ``can be strengthened by replacing the
 second equivalence relation, IFF, by EQUAL.''  Suppose for example that this
 warning occurs when you submit the following rule:</p>

 @({
  (defcong equiv1 iff (fn x y) 2)
 })

 <p>which is shorthand for the following:</p>

 @({
  (defthm equiv1-implies-iff-fn-2
         (implies (equiv1 y y-equiv)
                  (iff (fn x y) (fn x y-equiv)))
         :rule-classes (:congruence))
 })

 <p>The warning is telling you that ACL2 was able to deduce that @('fn') always
 returns a Boolean, and hence a trivial but useful consequence is obtained by
 replacing @(tsee iff) by @(tsee equal) &mdash;</p>

 @({
  (defcong equiv1 equal (fn x y) 2)
 })

 <p>&mdash; which is shorthand for the following:</p>

 @({
  (defthm equiv1-implies-equal-fn-2
         (implies (equiv1 y y-equiv)
                  (equal (fn x y) (fn x y-equiv)))
         :rule-classes (:congruence))
 })

 <p>If you have difficulty proving the latter directly, you can derive it from
 the former by giving a suitable hint, minimally as follows.</p>

 @({
  (defcong equiv1 equal (fn x y) 2
    :hints ((\"Goal\"
             :use equiv1-implies-iff-fn-2
             :in-theory
             (union-theories '((:type-prescription fn))
                             (theory 'minimal-theory)))))
 })

 <p>By heeding this warning, you may avoid unnecessary @(tsee double-rewrite)
 warnings later.  We now explain why, but see @(see double-rewrite) for
 relevant background material.</p>

 <p>For example, suppose you have proved the ``@('iff')'' version of the
 congruence rule above, and later you submit the following rewrite rule.</p>

 @({
  (defthm equal-list-perm
    (implies (equiv1 x y)
             (fn x y)))
 })

 <p>Since @('fn') is known to return a Boolean, ACL2 performs an optimization
 that stores this rule as though it were the following.</p>

 @({
  (defthm equal-list-perm
    (implies (equiv1 x y)
             (equal (fn x y) t)))
 })

 <p>Thus, if ACL2's rewriter sees a term @('(fn a b)') in a context where the
 equivalence relation @(tsee iff) is not being maintained, then it cannot use
 rule @('equiv1-implies-iff-fn-2'), so it rewrites argument @('a') without the
 benefit of knowing that it suffices to maintain @('equiv1'); and then it
 caches the result.  When ACL2 subsequently attempts to relieve the hypothesis
 @('(equiv1 x y)'), it will rewrite @('x') simply by returning the rewritten
 value of @('a') from the result cache.  This is unfortunate if @('a') could
 have been rewritten more completely under maintenance of the equivalence
 relation @('equiv1') &mdash; which is legal in the hypothesis since @('a') is
 an argument of @('equiv1'), which is an @(see equivalence) relation.  The user
 who observes the warning from rule @('equiv1-implies-iff-fn-2'), and replaces
 it with @('equiv1-implies-equal-fn-2'), will avoid this unfortunate
 case.</p>")

(defxdoc conjugate
  :parents (numbers acl2-built-ins)
  :short "Complex number conjugate"
  :long "<p>@('Conjugate') takes an ACL2 number as an argument, and returns its
 complex conjugate (i.e., the result of negating its imaginary part.).</p>

 <p>@('Conjugate') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def conjugate)")

(defxdoc cons
  :parents (conses acl2-built-ins)
  :short "Pair and list constructor"
  :long "<p>@('(cons x y)') is a pair whose first component is @('x') and
 second component is @('y').  If @('y') is a list, then @('(cons x y)') is a
 list that has an additional element @('x') on the front.</p>")

(defxdoc cons-subtrees
  :parents (fast-alists acl2-built-ins)
  :short "Build a fast alist whose keys are the subtrees of X"
  :long "<p>@('(cons-subtrees x nil)') builds a fast alist that associates each
subtree of X with T, without duplication.</p>

 @(def cons-subtrees)")

(defxdoc cons-with-hint
  :parents (conses acl2-built-ins)
  :short "Alternative to @(tsee cons) that tries to avoid consing when a
 suitable @('cons') structure is provided as a hint."

  :long "<p>This is a special purpose function that is intended to help with
 reducing the memory usage of functions that modify existing cons tree
 structures.  Also see @(see hons) for a way to share @(see cons) structures;
 however, @('cons-with-hint') is likely much cheaper than @('hons') and hence
 can be useful for reducing consing without the overhead of @('hons').</p>

 <p>Logically @('(cons x y hint)') is just @('(cons x y)'); @('hint') is
 completely irrelevant and ignored.  We generally expect that
 @('cons-with-hint') will just be left @(see enable)d, so you should never have
 to reason about it.</p>

 <p>But @('cons-with-hint') has a special raw Common Lisp definition that tries
 to avoid consing by using your @('hint').  Specifically: if @('hint') is the
 cons @('(x . y)'), then @('hint') is returned without creating a new cons.
 Equality checking against @('x') and @('y') is done using @(tsee eql), which
 makes it a fast but incomplete check for equality.</p>

 <p>What good is this?  A fairly common operation in ACL2 is to ``change'' an
 existing data structure by consing together a new structure that is similar to
 it, but perhaps with some subtrees replaced.  In many cases, some portion of
 the structure does not need to change.</p>

 <p>For instance, consider a function like @(tsee remove-equal), which updates
 a list by removing all copies of some element from it.  The definition of
 @('remove-equal') is as follows:</p>

 @(def remove-equal)

 <p>You can see that if @('l') doesn't have any copies of @('x'), this function
 will essentially make a fresh copy of the whole list @('x').  That could waste
 a lot of memory when @('x') is long.  It is easy to write a new version of
 @('remove-equal') that uses @('cons-with-hint'):</p>

 @({
 (defun remove-equal-with-hint (x l)
   (declare (xargs :guard (true-listp l)))
   (mbe :logic (remove-equal x l)
        :exec (cond ((endp l) nil)
                    ((equal x (car l))
                     (remove-equal-with-hint x (cdr l)))
                    (t
                     (cons-with-hint (car l)
                                     (remove-equal-with-hint x (cdr l))
                                     l)))))
 })

 <p>This new version avoids consing in the case that we are not dropping an
 element.  For example, at the time of this writing, we found the following
 memory usages on our copy of ACL2 built on CCL:</p>

 @({
 :q

 ;; 16 MB of memory allocated
 (let ((list (make-list 1000 :initial-element 0)))
   (time (loop for i from 1 to 1000 do (remove-equal i list))))

 ;; 0 MB of memory allocated
 (let ((list (make-list 1000 :initial-element 0)))
   (time (loop for i from 1 to 1000 do (remove-equal-with-hint i list))))
 })

 <p>This memory usage is not very surprising when you consider that the list
 does not change when no removal takes place.  For example (still in raw
 Lisp):</p>

 @({
 ? (let ((x '(a b c d e))) (eq x (remove-equal-with-hint 3 x)))
 T
 ?
 })

 <p>Note that ACL2 asks Lisp to inline calls of @('cons-with-hint'), so there
 will likely be no function call overhead for using @('cons-with-hint').</p>")

(defxdoc conservativity-of-defchoose
  :parents (defchoose)
  :short "Proof of conservativity of @(tsee defchoose)"
  :long "<p>This documentation topic provides underlying theory.  It is of
 theoretical interest only; it has no relationship to the effective use of
 ACL2.</p>

 <p>The argument below for the conservativity of @(see defchoose) replaces the
 terse and somewhat misleading reference to a forcing argument in Appendix B of
 the paper by ACL2 authors Kaufmann and Moore, ``Structured Theory Development
 for a Mechanized Logic'' (Journal of Automated Reasoning 26, no. 2 (2001),
 pp. 161&ndash;203).</p>

 <p>Our basic idea is to take a (countable) first-order structure for ACL2,
 M, together with a function symbol, f, introduced by @(see defchoose), and
 find a way to expand M with an interpretation of f (without changing the
 universe of M) so that e0-induction continues to hold in the expansion.  A
 remark at the end of this documentation topic shows why care is necessary.  A
 concept called ``forcing'', originally introduced by Paul Cohen for set
 theory, has long since been adapted by logicians (in a simplified form) to
 model theory.  This simplified model-theoretic forcing provides the means for
 making our careful expansion.</p>

 <p>The forcing argument presented below is intended to be completely
 self-contained for those familiar with basic first-order logic and ACL2; in
 particular, see @(see defchoose).  No background in forcing (model-theoretic
 or otherwise) is expected, though we do expect a rudimentary background in
 first-order logic and familiarity with the following.</p>

 <p>Preliminaries.  We write s[p&lt;-p0] to denote the result of extending or
 modifying the assignment s by binding p to p0.  Now let A be a subset of the
 universe U of a first-order structure M.  A is said to be ``first-order
 definable with parameters'' in M if for some formula phi, variable x, and
 assignment s binding the free variables of phi except perhaps for x, A = {a
 \\in U: M |= phi[s[x&lt;-a]]}.  Note that we are writing ``\\in'' to denote
 set membership.  Finally, we indicate the end of a proof (or of a theorem
 statement, when the proof is omitted) with the symbol ``-|''.</p>

 <p>We gratefully acknowledge very helpful feedback from John Cowles, who found
 several errors in a draft of this note and suggested the exercises.  We also
 thank Ruben Gamboa for helpful feedback, and we thank Jim Schmerl for an
 observation that led us directly to this proof in the first place.</p>

 <p>We are given a consistent first-order theory T, extending the ACL2
 ground-zero theory, that satisfies the e0-induction scheme.  We wish to show
 that the extension of T by the following arbitrary defchoose event is
 conservative, where g is a new function symbol.</p>

 @({
       (defchoose g <bound-vars> <free-vars> <body>)
 })

 <p>Note that by ``the extension of T'' here we mean the extension of T by not
 only the new defchoose axiom displayed just below, but also the addition of
 e0-induction axioms for formulas in the expanded language obtained by
 including the new defchoose function symbol, g.</p>

 @({
       <body> -> (LET <bound-vars> = g(<free-vars>) in <body>)
 })

 <p>By definition of conservativity, since proofs are finite, it clearly
 suffices to consider an arbitrary finite subset of T.  Then by the
 completeness, soundness, and downward Lowenheim-Skolem theorems of first-order
 logic, it suffices to show that an arbitrary countable model of T can be
 expanded (i.e., by interpreting the new symbol g without changing the universe
 of the model) to a model of the corresponding defchoose axiom above, in which
 all e0-induction axioms hold in the language of that model (i.e., the expanded
 language).</p>

 <p>Below, we will carry out a so-called <i>forcing</i> construction, which
 allows us to expand any countable model M of T to a model M[G] for the
 expanded language that satisfies e0-induction (in the expanded language) and
 also satisfies the axiom displayed above, generated from the defchoose event.
 The ideas in this argument are standard in model theory; no novelty is claimed
 here.</p>

 <p>Fix a countable model M of a theory T that satisfies e0-induction for its
 countable language and extends the ACL2 ground-zero theory.  Also fix the
 above defchoose axiom, where g is not in the language of T.</p>

 <p>We start by defining a partial order P as follows.  Let Nb and Nf be the
 lengths of &lt;bound-vars&gt; and &lt;free-vars&gt;, respectively.  P consists
 of all fn in M such that the following formula is true in M.  Roughly
 speaking, it says that fn is a finite function that witnesses, on its domain,
 the requirement above for g.</p>

 @({
         alistp(fn) &
         no-duplicatesp-equal(strip-cars(fn)) &
         (forall <bound-vars>, <free-vars> .
            (member-equal(cons(<free-vars>,<bound-vars>), fn) ->
             (length(<bound-vars>) = Nb &
              length(<free-vars>)  = Nf &
              ((exists <bound-vars> . <body>) ->
               (LET <bound-vars> = g(<free-vars>) in <body>)))))
 })

 <p>P is ordered by subset, i.e., we say that p2 <i>extends</i> p1 if p1 is a
 subset (not necessarily proper) of p2 (more precisely, M |=
 subsetp-equal(p1,p2)).</p>

 <p>Remark.  The original argument in Appendix B of the aforementioned paper
 can essentially be salvaged, as we now show.  The key observation is that the
 particular choice of P is nearly irrelevant for the argument that follows
 below.  In particular, we can instead define P to consist of finite one-one
 functions with domain contained in the set of natural numbers.  More
 precisely, consider the following definitions.</p>

 @({
       (defun function-p (fn)
         (and (alistp fn)
              (no-duplicatesp-equal (strip-cars fn))))

       (defun nat-function-p (x)
         (and (function-p x)
              (nat-listp (strip-cars x))))
 })

 <p>and define an inverse function on alists as follows.</p>

 @({
       (defun inverse (fn)
         (if (endp fn)
             nil
           (cons (cons (cdar fn) (caar fn))
                 (inverse (cdr fn)))))
 })

 <p>Then P may instead be defined to consist of those fn for which
 nat-function-p(fn) &amp; function-p(inverse(fn)).  With this alternate
 definition of P, the argument below then goes through virtually unchanged, and
 we get an expansion M[G] of M in which there is a definable enumeration of the
 universe.  The conservativity of defchoose then follows easily because the
 function being introduced can be defined explicitly using that enumeration
 (namely, always pick the least witness in the sense of the enumeration).</p>

 <p>End of Remark.</p>

 <p>Next we present the relevant forcing concepts from model theory.</p>

 <p>A <i>dense</i> subset of P is a subset D of P such that for every p \\in P,
 there is d \\in D such that d extends p.  A subset G of P is <i>generic</i>
 with respect to a collection Ds of dense subsets of P, also written ``G is
 Ds-generic,'' if G is closed under subset (if p2 \\in G and p2 extends p1 then
 p1 \\in G), G is pairwise compatible (the union-equal of any two elements of G
 is in G), and every set in Ds has non-empty intersection with G.</p>

 <p>For p \\in P, we say that a subset D of P is <i>dense beyond</i> p if for
 all p1 extending p there exists p2 extending p1 such that p2 \\in D.  This
 notion makes sense even for D not a subset of P if we treat elements of D not
 in P as nil.</p>

 <p>Proposition 1.  For any partial order P and countable collection Ds of
 dense subsets of P, there is a Ds-generic subset of P.</p>

 <p>Proof.  Let Ds = {D0,D1,D2,...}.  Define a sequence &lt;p_0,p_1,...&gt;
 such that for all i, p_i \\in Di and p_(i+1) extends p_i.  Let G = {p \\in P:
 for some i, pi extends p}.  Then G is Ds-generic. -|</p>

 <p>Note that P is first-order definable (with parameters) in M.  Let Df be the
 set of dense subsets of P that are first-order definable (with parameters) in
 M.  A standard argument shows there are only countably many first-order
 definitions with parameters in a countable model M whose language is countable
 &mdash; for example, we can Goedel number all terms and then all formulas
 &mdash; hence, Df is countable.</p>

 <p>By Proposition 1, let G be Df-generic.  Notice that for any list x of
 length Nf in M, the set of elements f of P for which x is in the domain of f
 is dense and first-order definable.  We may thus define a function g0 as
 follows: g0(x_1,...,x_Nf) = y if there is some element of G containing the
 pair ((x_1 ... x_Nf) . y).  It is easy to see that g0 is a total function on
 M.  Let L be the language of T and let L[g] be the union of L with a set
 containing a single new function symbol, g.  Let M[G] be the expansion of M to
 L[g] obtained by interpreting g to be g0 (see also Proposition 5 below).</p>

 <p>So now we have fixed M, P, Df, G, and g0, where G is Df-generic.</p>

 <p>Proposition 2.  Let Df be the set of dense subsets of P that are
 first-order definable (with parameters) in M.  Suppose that p \\in G and D
 \\in Df.  Then for some q \\in G extending p, q \\in D.</p>

 <p>Proof.  Let D0 be the set of p' \\in D that either extend p or have no
 extension in D that extends p.  We leave it as a straightforward exercise to
 show that D0 is dense, and D0 is clearly first-order definable (with
 parameters) in M.  So by genericity of G, we may pick q \\in D0 such that q
 \\in G.  Thus q \\in D.  By definition of generic, some extension q1 of both p
 and q belongs to G.  Pick q2 \\in D extending q1; thus q has an extension in D
 that extends p (namely, q2), so by definition of D0, q extends p. -|</p>

 <p>Definition of forcing.  Let phi(x1,...,xk) be a first-order formula in L[g]
 and let p \\in P.  We define a formula of L, denoted ``p ||- phi'' (``p forces
 phi''), by recursion on phi (in the metatheory) as follows.  (Here, we view
 ``or'' and ``forall'' as abbreviations.)</p>

 <blockquote><p>If phi is atomic, then let phi'(A) be the result of replacing,
   inside-out, each subterm of the form g(x_1,...,x_Nb) with the term (cdr
   (assoc-equal (list x_1 ... x_Nb) A)), where A is neither p nor a variable
   occurring in phi.  Then p ||- phi is defined as follows: ``The set {A \\in
   P: A extends p and phi'(A)} is dense beyond p''.  That is, p ||- phi is the
   following formula:</p>

 @({
      (forall p1 \\in P extending p)
       (exists p2 \\in P extending p1) phi'(p2).
 })

 <p>p ||- ~phi is: (forall p' \\in P extending p) ~(p' ||- phi)</p>

 <p>p ||- phi_1 &amp; phi_2 is: (p ||- phi_1) &amp; (p ||- phi_2)</p>

 <p>p ||- (exists x) phi is: (exists x) (p ||- phi)</p></blockquote>

 <p>We will need the following definition later.</p>

 <p>Definition.  p ||-w phi (p <i>weakly forces</i> phi) is an abbreviation for
 p ||- ~~phi.</p>

 <p>The following exercises were suggested by John Cowles as a means for
 gaining familiarity with the definition of forcing.</p>

 <p>Exercise 1. Consider the formula (phi_1 OR phi_2) as an abbreviation for
 ~(~phi_1 &amp; ~phi_2), Show that p ||- (phi_1 OR phi_2) is equivalent to the
 following.</p>

 @({
       (forall p' \\in P extending p) (exists p'' \\in P extending p')
        ((p'' ||- phi_1) OR (p'' ||- phi_2))
 })

 <p>Exercise 2. Consider the formula (forall x)phi as an abbreviation for
 ~(exists x)~phi, Show that p ||- (forall x)phi is equivalent to the
 following.</p>

 @({
       (forall x)
        (forall p1 \\in P extending p)
         (exists p2 \\in P extending p1) (p2 ||- phi).
 })

 <p>Exercise 3. Prove that p ||-w phi is equivalent to the following.</p>

 @({
       (forall p' \\in P extending p)
        (exists p'' \\in P extending p') (p'' ||- phi).
 })

 <p>Exercise 4. Let phi be a formula of L[g].  Prove: M |= (p ||-
      phi)[s[p&lt;-p0]] implies M |= (p ||-w phi)[s[p&lt;-p0]].</p>

 <p>Exercise 5. Let phi be a formula of L[g].  Prove: M |= (p ||-
      ~phi)[s[p&lt;-p0]] iff M |= (p ||-w ~phi)[s[p&lt;-p0]].</p>

 <p>[End of exercises.]</p>

 <p>The definition of forcing stipulates how to view ``p ||- phi(x1,...,xk)''
 as a new formula theta(p,x1,...,xk).  That is, ``||-'' transforms formulas, so
 for any first-order formula phi, ``p ||- phi'' is just another first-order
 formula.  That observation shows that a formula such as ((p ||- phi) OR (p ||-
 ~phi)) is really just another first-order formula.  The following proposition
 thus follows easily.</p>

 <p>Proposition 3. For any formula phi of L[g], {p0: M |= ((p ||- phi) OR (p
 ||- ~phi))[s[p&lt;-p0]]]} is a dense subset of P, which (since it is
 first-order definable with parameters in M) intersects G. -|</p>

 <p>The following proposition is easily proved by a structural induction on
 phi, and is left to the reader.</p>

 <p>Proposition 4. Let phi be a formula of L[g].  Suppose p0 \\in P, p1
 \\in P,<br/>

 M |= (p ||- phi)[s[p&lt;-p0]],<br/>

 and p1 extends p0.  Then<br/>

 M |= (p ||- phi)[s[p&lt;-p1]]. -|</p>

 <p>We will also need the following.</p>

 <p>Proposition 5. The following is dense for any finite set S of Nf-tuples: {p
 \\in P: for some &lt;x_1 ... x_Nf&gt; \\in S, (list x_1 ... x_Nf) \\in
 strip-cars(p)}.  Thus, the function g0 is a total function. -|</p>

 <p>The next lemma tells us that the sentences true in M[G] are those that are
 forced by an element of G.</p>

 <p>Truth Lemma.  Let phi be a formula in L[g], let s be an assignment to the
 free variables of phi, and let p be a variable not in the domain of s.  Then
 M[G] |= phi[s] iff for some p0 \\in G, M |= (p ||- phi)[s[p&lt;-p0]].</p>

 <p>Proof.  The proof is by induction on the structure of phi.  First suppose
 phi is atomic.  Let D* be the set of elements p0 \\in P such that every
 assoc-equal evaluation from the definition of forcing phi returns a pair when
 A is bound to p0.  (Intuitively, this means that p0 is a sufficiently large
 approximation from any G containing p0 to make sense of phi in M[G].)  We make
 the following claim.</p>

 @({
  (*)   For all p0 \\in G such that p0 \\in D*,
        M[G] |= phi[s] iff M |= (p ||- phi)[s[p<-p0]].
 })

 <p>To prove the claim, fix p0 in both G and D*, and recall the function g0
 constructed from G in the definition of M[G].  Suppose that t_1, ..., t_Nf are
 terms and g(t_1, ..., t_Nf) is a subterm of phi.  Then s assigns a value in M
 to each of the t_i.  Let a_i be the value assigned by s to t_i.  Then g0(a_1,
 ..., a_Nf) = (cdr (assoc-equal (list a_1 ... a_Nf) p0)), as the assoc-equal is
 a pair (since p0 \\in D*) and has the indicated value (because p0 \\in G).  It
 follows by the definition of formula phi' in the definition of forcing:</p>

 @({
       M[G] |= phi[s]  iff  M |= phi'(p)[s[p<-p0]]
 })

 <p>Moreover, because p0 \\in D* it is clear that this holds if p0 is replaced
 by an arbitrary extension of p0.  Then (*) easily follows.</p>

 <p>By Proposition 5, D* is dense, so there is some p0 in the intersection of
 D* and G.  The forward direction of the conclusion then follows by (*).  The
 reverse direction is clear from (*) by application of Proposition 2 to D* and
 Proposition 4.</p>

 <p>Next, suppose M[G] |= ~phi[x].  Then it is not the case that M[G] |= phi,
 so by the inductive hypothesis, there is no p0 \\in G for which M |= (p ||-
 phi)[s[p&lt;-p0]].  By Proposition 3, there is p0 \\in G for which M |= (p ||-
 ~phi)[s[p&lt;-p0]].  For the other direction, suppose it is not the case that
 M[G] |= ~phi[s].  So M[G] |= phi[s], and by the inductive hypothesis, there is
 p0 \\in G for which M |= (p ||- phi)[s[p&lt;-p0]].  It follows that there is
 no p1 \\in G for which M |= (p ||- ~phi)[s[p&lt;-p1]], since from such p1 we
 can find a common extension p2 of p0 and p1 (since G is generic), and since p2
 extends p0 then by Proposition 4, M |= (p ||- phi)[s[p&lt;-p2]], contradicting
 (by definition of forcing) M |= (p ||- ~phi)[s[p&lt;-p1]] since p2 extends
 p1.</p>

 <p>The case (phi_1 &amp; phi_2) follows easily from the inductive hypothesis.
 For the forward direction, apply Proposition 4 and the observation that by
 genericity, if p0 \\in G and p1 \\in G then p0 and p1 they have a common
 extension in G.</p>

 <p>Finally, the case (exists x) phi follows trivially from the inductive
 hypothesis. -|</p>

 <p>Truth Lemma Corollary.  The Truth Lemma holds with ||-w replacing ||-.</p>

 <p>Proof.  This is clear by applying the Truth Lemma to ~~phi. -|</p>

 <p>Here is our main theorem.  Recall that all first-order theories in our ACL2
 context satisfy the e0-induction scheme.</p>

 <p>Theorem.  M[G] satisfies e0-induction.</p>

 <p>Proof.  We consider an arbitrary instance of e0-induction in L[g], stated
 using a strict well-founded relation &lt;| and a formula phi.  We write phi(y)
 to indicate that y may be among the free variables of phi, and phi(y&lt;-x) to
 denote the result of substituting x for y in phi.</p>

 @({
    theta:   (forall y) [((forall x <| y) phi(y<-x)) -> phi(y)]
          -> (forall y) phi(y)
 })

 <p>Our goal is to prove that theta holds in M[G].</p>

 <p>Below, we abuse notation by leaving assignments implicit and by writing ``p
 ||- phi(y0)'' to signify that the formula (p ||- phi(y)) is true in M under
 the extension of the explicit assignment that binds y to y0.  We believe that
 the intended meaning will be clear.</p>

 <p>Consider the following set D.</p>

 @({
    D = {p \\in P: either p ||-w phi(y0) for all y0,
                  or else
                  for some y0, p ||- ~phi(y0) and
                               for all y1 <| y0 p ||-w phi(y1)}.
 })

 <p>The set D is clearly first-order definable (with parameters) in M.  We
 claim that D is a dense subset of P.  For suppose p0 \\in P; we find p1 \\in D
 extending p0, as follows.  If p0 ||-w phi(y0) for all y0, then we may take p1
 to be p0.  Otherwise, by definition of ||-w and ||-, there is some y0 such
 that for some extension p0' of p0, p0' ||- ~phi(y0).  Pick a &lt;|-minimal
 such y0, and correspondingly pick p1 so that p1 extends p0 and p1 ||-
 ~phi(y0).  In order to show that p1 \\in D, it remains to show that for all y1
 &lt;| y0, p1 ||-w phi(y1), i.e., there is no q extending p1 such that q ||-
 ~phi(y1).  This is indeed the case since otherwise q and y1 would contradict
 the &lt;|-minimality of y0.</p>

 <p>Applying the genericity of G and just-proved density of D, pick p0 \\in G
 such that p0 \\in D.  If p0 ||-w phi(y0) for all y0, then by the Truth Lemma
 Corollary, M[G] |= phi(y0) for all y0, and thus M[G] |= theta.  Otherwise,
 since p0 \\in D we may choose y0 such that p0 ||- ~phi(y0) and for all y1
 &lt;| y0, p0 ||-w phi(y1).  By the Truth Lemma and its corollary, since p0
 \\in G we have:</p>

 @({
  (1)   M[G] |= ~phi(y0).
  (2)   For all y1 <| y0, M[G] |= phi(y1).
 })

 <p>It follows that the antecedent of theta is false in M[G], as witnessed by y
 = y0; thus M[G] |= theta. -|</p>

 <p>Remark.  We close by returning, as promised above, to the question of why
 so much care is necessary in constructing an expansion of M.  We assume
 familiarity here with the notion of a ``non-standard'' natural number of M,
 i.e., one that is greater than the interpretation of any term that has the
 form (+ 1 1 1 ... 1).  Here is a very simple example that illustrates the need
 for some care.  Consider the following event, which introduces a function foo
 with the following property: for all x, if natp(x) then natp(foo(x)).</p>

 @({
       (defchoose foo (y) (x)
         (implies (natp x) (natp y)))
 })

 <p>Certainly we can build a model of the above property from a model M of the
 ground-zero theory, by interpreting foo so that for all x for which M
 satisfies natp(x), foo(x) is also a natp in M.  But suppose we start with a
 non-standard model M of the ground-zero theory, and we happen to define foo(x)
 to be 1 for all non-standard natural numbers x and 0 for all other x.  The
 resulting expansion of M will not satisfy the e0-induction scheme or even the
 ordinary natural number induction scheme: foo(0)=0 holds in that expansion as
 does the implication foo(n)=0 =&gt; foo(n+1)=0 for every natural number n of
 M, standard or not; and yet foo(k)=0 fails for every non-standard natural
 number k of M.</p>")

(defxdoc conses
  :parents (programming)
  :short "A <b>cons</b> is an ordered pair.  In ACL2, data structures like
 @(see lists), @(see alists), etc., are made up of conses.")

(defxdoc consp
  :parents (conses acl2-built-ins)
  :short "Recognizer for @(see cons) pairs"
  :long "<p>@('(consp x)') is true if and only if @('x') is a @(see cons)
 pair.</p>")

(defxdoc constraint
  :parents (encapsulate)
  :short "Restrictions on certain functions introduced in @(tsee encapsulate) @(see events)"
  :long "<p>Suppose that a given theorem, @('thm'), is to be functionally
 instantiated using a given functional substitution, @('alist').  (See @(see
 lemma-instance), or for an example, see @(see
 functional-instantiation-example).)  What is the set of proof obligations
 generated?  It is the set obtained by applying @('alist') to all terms,
 @('tm'), such that (a) @('tm') mentions some function symbol in the domain of
 @('alist'), and (b) either (i) @('tm') is the ``constraint'' (see below) on a
 function symbol ancestral in @('thm') or in some @(tsee defaxiom) or (ii)
 @('tm') is the body of a @(tsee defaxiom).  Here, a function symbol is
 ``ancestral'' in @('thm') if either it occurs in @('thm'), or it occurs in the
 definition of some function symbol that occurs in @('thm'), and so on.</p>

 <p>The remainder of this note explains what we mean by ``constraint'' in the
 words above.  For a utility that obtains the constraint for a given function
 symbol, see @(see constraint-info).</p>

 <p>In a certain sense, function symbols are introduced in essentially two
 ways.  The most common way is to use @(tsee defun) (or when there is mutual
 recursion, @(tsee mutual-recursion) or @(tsee defuns)).  There is also a
 mechanism for introducing ``witness functions''; see @(see defchoose).  The
 documentation for these @(see events) describes the axioms they introduce,
 which we will call here their ``definitional axioms.''  These definitional
 axioms are generally the constraints on the function symbols that these axioms
 introduce.</p>

 <p>However, when a function symbol is introduced in the scope of an @(tsee
 encapsulate) event, its constraints may differ from the definitional axioms
 introduced for it.  For example, suppose that a function's definition is
 @(tsee local) to the @(tsee encapsulate); that is, suppose the function is
 introduced in the @(see signature) of the @(tsee encapsulate).  Then its
 constraints include, at the least, those non-@(tsee local) theorems and
 definitions in the @(tsee encapsulate) that mention the function symbol.</p>

 <p>Actually, it will follow from the discussion below that if the @(see
 signature) is empty for an @(tsee encapsulate), then the constraint on each of
 its new function symbols is exactly the definitional axiom introduced for it.
 Intuitively, we view such @('encapsulates') just as we view @(tsee
 include-book) @(see events).  But the general case, where the @(see signature)
 is not empty, is more complicated.</p>

 <p>In the discussion that follows we describe in detail exactly which
 constraints are associated with which function symbols that are introduced in
 the scope of an @(tsee encapsulate) event.  In order to simplify the
 exposition we make two cuts at it.  In the first cut we present an
 over-simplified explanation that nevertheless captures the main ideas.  In the
 second cut we complete our explanation by explaining how we view certain @(see
 events) as being ``lifted'' out of the @(tsee encapsulate), resulting in a
 possibly smaller @(tsee encapsulate), which becomes the target of the
 algorithm described in the first cut.</p>

 <p>At the end of this note we present an example showing why a more naive
 approach is unsound.</p>

 <p>Finally, before we start our ``first cut,'' we note that any information
 you want ``exported'' outside an @(tsee encapsulate) event must be there as an
 explicit definition or theorem.  For example, even if a function @('foo') has
 output type @('(mv t t)') in its @(see signature), the system will not know
 @('(true-listp (foo x))') merely on account of this information.  Thus, if you
 are using functions like @('foo') (constrained @(tsee mv) functions), then you
 may find it useful to prove (inside the @('encapsulate'), to be exported) a
 @(':')@(tsee type-prescription) rule for the constrained function, for
 example, the @(':')@(tsee type-prescription) rule @('(true-listp (foo
 x))').</p>

 <p><i>First cut at constraint-assigning algorithm.</i> Consider the set of
 formulas introduced by all @(see events) in the scope of an @(tsee
 encapsulate):</p>

 <ul>

 <li>for every @(tsee defthm) and @(tsee defaxiom) event, include its formula
 as well as the formulas of all its corollaries;</li>

 <li>for every @(tsee defun) event, include the formula that equates the body
 with the application of the function applied to the formals;</li>

 <li>for every @('defchoose') event, include the axiom that it adds (see @(see
 defchoose));</li>

 <li>and so on, including axioms added by @(tsee defpkg) and (recursively) any
 subsidiary @('encapsulate') events.</li>

 </ul>

 <p>Then quite simply, all such formulas are conjoined, and each function
 symbol introduced by the @(tsee encapsulate) is assigned that conjunction as
 its constraint.</p>

 <p>Clearly this is a rather severe algorithm.  Let us consider two possible
 optimizations in an informal manner before presenting our second cut.</p>

 <p>Consider the (rather artificial) event below.  The function @('before1')
 does not refer at all, even indirectly, to the locally-introduced function
 @('sig-fn'), so it is unfortunate to saddle it with constraints about
 @('sig-fn').</p>

 @({
  (encapsulate
   (((sig-fn *) => *))

   (defun before1 (x)
     (if (consp x)
         (before1 (cdr x))
       x))

   (local (defun sig-fn (x) (cons x x)))

   (defthm sig-fn-prop
     (consp (sig-fn x)))
   )
 })

 <p>We would like to imagine moving the definition of @('before1') to just in
 front of this @(tsee encapsulate), as follows.</p>

 @({
  (defun before1 (x)
    (if (consp x)
        (before1 (cdr x))
      x))

  (encapsulate
   (((sig-fn *) => *))

   (local (defun sig-fn (x) (cons x x)))

   (defthm sig-fn-prop
     (consp (sig-fn x)))
   )
 })

 <p>Thus, we will only assign the constraint @('(consp (sig-fn x))'), from the
 theorem @('sig-fn-prop'), to the function @('sig-fn'), not to the function
 @('before1').</p>

 <p>More generally, suppose an event in an @(tsee encapsulate) event does not
 mention any function symbol in the @(see signature) of the @(tsee
 encapsulate), nor any function symbol that mentions any such function symbol,
 and so on.  (We might say that no function symbol from the @(see signature) is
 an ``ancestor'' of any function symbol occurring in the event.)  Then we
 imagine moving the event, so that it appears in front of the @(tsee
 encapsulate).  We don't actually move it, but we pretend we do when it comes
 time to assign constraints.  Thus, such definitions only introduce
 definitional axioms as the constraints on the function symbols being defined.
 In the example above, the event @('sig-fn-prop') introduces no constraints on
 function @('before1').</p>

 <p>Once this first optimization is performed, we have in mind a set of
 ``constrained functions.''  These are the functions introduced in the @(tsee
 encapsulate) that would remain after moving some of them in front, as
 indicated above.  Consider the collection of all formulas introduced by the
 @(tsee encapsulate), except the definitional axioms, that mention these
 constrained functions.  So for example, in the event below, no such formula
 mentions the function symbol @('after1').</p>

 @({
  (encapsulate
   (((sig-fn *) => *))

   (local (defun sig-fn (x) (cons x x)))

   (defthm sig-fn-prop
     (consp (sig-fn x)))

   (defun after1 (x)
     (sig-fn x))
   )
 })

 <p>We can see that there is really no harm in imagining that we move the
 definition of @('after1') out of the @(tsee encapsulate), to just after the
 @(tsee encapsulate).</p>

 <p>Many subtle aspects of this rearrangement process have been omitted.  For
 example, suppose the function @('fn') uses @('sig-fn'), the latter being a
 function in the signature of the encapsulation.  Suppose a formula about
 @('fn') is proved in the encapsulation.  Then from the discussion above
 @('fn') is among the constrained functions of the encapsulate: it cannot be
 moved before the encapsulate and it cannot be moved after the encapsulation.
 But why is @('fn') constrained?  The reason is that the theorem proved about
 @('fn') may impose or express constraints on @('sig-fn').  That is, the
 theorem proved about @('fn') may depend upon properties of the witness used
 for @('sig-fn').  Here is a simple example:</p>

 @({
  (encapsulate
   (((sig-fn *) => *))

   (local (defun sig-fn (x) (declare (ignore x)) 0))

   (defun fn (lst)
     (if (endp lst)
         t
         (and (integerp (sig-fn (car lst)))
              (fn (cdr lst)))))

   (defthm fn-always-true
     (fn lst)))
 })

 <p>In this example, there are no @(tsee defthm) events that mention
 @('sig-fn') explicitly.  One might therefore conclude that it is completely
 unconstrained.  But the witness we chose for it always returns an integer.
 The function @('fn') uses @('sig-fn') and we prove that @('fn') always returns
 true.  Of course, the proof of this theorem depends upon the properties of the
 witness for @('sig-fn'), even though those properties were not explicitly
 ``called out'' in theorems proved about @('sig-fn').  It would be unsound to
 move @('fn-always-true') after the encapsulate.  It would also be unsound to
 constrain @('sig-fn') to satisfy just @('fn-always-true') without including in
 the constraint the relation between @('sig-fn') and @('fn').  Hence both
 @('sig-fn') and @('fn') are constrained by this encapsulation and the
 constraint imposed on each is the same and states the relation between the two
 as characterized by the equation defining @('fn') as well as the property that
 @('fn') always returns true.  Suppose, later, one proved a theorem about
 @('sig-fn') and wished to functionally instantiate it.  Then one must also
 functionally instantiate @('fn'), even if it is not involved in the theorem,
 because it is only through @('fn') that @('sig-fn') inherits its constrained
 properties.</p>

 <p>This is a pathological example that illustrate a trap into which one may
 easily fall: rather than identify the key properties of the constrained
 function the user has foreshadowed its intended application and constrained
 those notions.  Clearly, the user wishing to introduce the @('sig-fn') above
 would be well-advised to use the following instead:</p>

 @({
  (encapsulate
   (((sig-fn *) => *))
   (local (defun sig-fn (x) (declare (ignore x)) 0))
   (defthm integerp-sig-fn
     (integerp (sig-fn x))))

  (defun fn (lst)
    (if (endp lst)
        t
      (and (integerp (sig-fn (car lst)))
           (fn (cdr lst)))))

  (defthm fn-always-true
     (fn lst)))
 })

 <p>Note that @('sig-fn') is constrained merely to be an integer.  It is the
 only constrained function.  Now @('fn') is introduced after the encapsulation,
 as a simple function that uses @('sig-fn').  We prove that @('fn') always
 returns true, but this fact does not constrain @('sig-fn').  Future uses of
 @('sig-fn') do not have to consider @('fn') at all.</p>

 <p>Sometimes it is necessary to introduce a function such as @('fn') within
 the @('encapsulate') merely to state the key properties of the undefined
 function @('sig-fn').  But that is unusual and the user should understand that
 both functions are being constrained.</p>

 <p>Another subtle aspect of encapsulation that has been brushed over so far
 has to do with exactly how functions defined within the encapsulation use the
 signature functions.  For example, above we say ``Consider the collection of
 all formulas introduced by the encapsulate, <i>except the definitional
 axioms</i>, that mention these constrained functions.''  We seem to suggest
 that a definitional axiom which mentions a constrained function can be moved
 out of the encapsulation and considered part of the ``post-encapsulation''
 extension of the logical @(see world), if the defined function is not used in
 any non-definitional formula proved in the encapsulation.  For example, in the
 encapsulation above that constrained @('sig-fn') and introduced @('fn') within
 the encapsulation, @('fn') was constrained because we proved the formula
 @('fn-always-true') within the encapsulation.  Had we not proved
 @('fn-always-true') within the encapsulation, @('fn') could have been moved
 after the encapsulation.  But this suggests an unsound rule because whether
 such a function can be moved after the encapsulate depend on whether its
 <i>admission</i> used properties of the witnesses!  In particular, we say a
 function is ``subversive'' if any of its governing tests or the actuals in any
 recursive call involve a function in which the signature functions are
 ancestral.  See @(see infected-constraints) and see @(see
 subversive-recursions).</p>

 <p>(Aside: The definition of @('fn') in the first encapsulation above that
 defines @('fn'), i.e., the encapsulation with @('fn-always-true') inside, is
 subversive because the call of the macro @(tsee AND) expands to a call of
 @('IF') that governs a recursive call of @('fn'), in this case:</p>

 @({
  (defun fn (lst)
    (if (endp lst)
        t
        (if (integerp (sig-fn (car lst)))
            (fn (cdr lst))
          nil))).
 })

 <p>If we switch the order of conjuncts in @('fn'), then the definition of
 @('fn') is no longer subversive, but it still ``infects'' the constraint
 generated for the encapsulation, hence for @('sig-fn'), because
 @('fn-always-true') blocks the definition of @('fn') from being moved back (to
 after the encapsulation).  Also see @(see infected-constraints).  If we both
 switch the order of conjuncts and drop @('fn-always-true') from the
 encapsulation, then the definition of @('fn') is in essence moved back to
 after the encapsulation, and the constraint for @('sig-fn') no longer includes
 the definition of @('fn').  End of aside.)</p>

 <p>Another aspect we have not discussed is what happens to nested
 encapsulations when each introduces constrained functions.  We say an
 @('encapsulate') event is ``trivial'' if it introduces no constrained
 functions, i.e., if its signatures is @('nil').  Trivial encapsulations are
 just a way to wrap up a collection of events into a single event.</p>

 <p>From the foregoing discussion we see we are interested in exactly how we
 can ``rearrange'' the events in a non-trivial encapsulation &mdash; moving
 some ``before'' the encapsulation and others ``after'' the encapsulation.  We
 are also interested in which functions introduced by the encapsulation are
 ``constrained'' and what the ``constraints'' on each are.  We may summarize
 the observations above as follows, after which we conclude with a more
 elaborate example.</p>

 <p><i>Second cut at constraint-assigning algorithm.</i> First, we focus only
 on non-trivial encapsulations that neither contain nor are contained in
 non-trivial encapsulations.  (Nested non-trivial encapsulations are not
 rearranged at all: do not put anything in such a nest unless you mean for it
 to become part of the constraints generated.)  Second, in what follows we only
 consider the non-@('local') events of such an @('encapsulate'), assuming that
 they satisfy the restriction of using no locally defined function symbols
 other than the signature functions.  Given such an @('encapsulate') event,
 move, to just in front of it and in the same order, all definitions and
 theorems for which none of the signature functions is ancestral.  Now collect
 up all formulas (theorems) introduced in the @(tsee encapsulate) other than
 definitional axioms.  Add to this set any of those definitional equations that
 is either subversive or defines a function used in a formula in the set.  The
 conjunction of the resulting set of formulas is called the ``constraint'' and
 the set of all the signature functions of the @('encapsulate') together with
 all function symbols defined in the @('encapsulate') and mentioned in the
 constraint is called the ``constrained functions.''  Assign the constraint to
 each of the constrained functions.  Move, to just after the @('encapsulate'),
 the definitions of all function symbols defined in the @('encapsulate') that
 have been omitted from the constraint.</p>

 <p>Implementation note.  In the implementation we do not actually move @(see
 events), but we create constraints that pretend that we did.</p>

 <p>Here is an example illustrating our constraint-assigning algorithm.  It
 builds on the preceding examples.</p>

 @({
  (encapsulate
   (((sig-fn *) => *))

   (defun before1 (x)
     (if (consp x)
         (before1 (cdr x))
       x))

   (local (defun sig-fn (x) (cons x x)))

   (defthm sig-fn-prop
     (consp (sig-fn x)))

   (defun during (x)
     (if (consp x)
         x
       (cons (car (sig-fn x))
             17)))

   (defun before2 (x)
     (before1 x))

   (defthm before2-prop
     (atom (before2 x)))

   (defthm during-prop
     (implies (and (atom x)
                   (before2 x))
              (equal (car (during x))
                     (car (sig-fn x)))))

   (defun after1 (x)
     (sig-fn x))

   (defchoose after2 (x) (u)
     (and (< u x) (during x)))
   )
 })

 <p>Only the functions @('sig-fn') and @('during') receive extra constraints.
 The functions @('before1') and @('before2') are viewed as moving in front of
 the @(tsee encapsulate), as is the theorem @('before2-prop').  The functions
 @('after1') and @('after2') are viewed as being moved past the @(tsee
 encapsulate).  The implementation reports the following.</p>

 @({
  In addition to SIG-FN, we export AFTER2, AFTER1, BEFORE2, DURING and
  BEFORE1.

  The following constraint is associated with both of the functions DURING and
  SIG-FN:

  (AND (EQUAL (DURING X)
              (IF (CONSP X)
                  X (CONS (CAR (SIG-FN X)) 17)))
       (CONSP (SIG-FN X))
       (IMPLIES (AND (ATOM X) (BEFORE2 X))
                (EQUAL (CAR (DURING X))
                       (CAR (SIG-FN X)))))
 })

 <p>Notice that the formula @('(consp (during x))') is not a conjunct of the
 constraint.  During the first pass of the @('encapsulate'), this formula is
 stored as a @(':')@(tsee type-prescription) rule deduced during the definition
 of the function @('during').  However, the rule is not exported because of a
 rather subtle soundness issue.  (If you are interested in details, see the
 comments in source function @('putprop-type-prescription-lst').)</p>

 <p>We conclude by asking (and to a certain extent, answering) the following
 question: Isn't there an approach to assigning constraints that avoids
 over-constraining more simply than our ``second cut'' above?  Perhaps it seems
 that given an @(tsee encapsulate), we should simply assign to each locally
 defined function the theorems exported about that function.  If we adopted
 that simple approach the events below would be admissible.</p>

 @({
  (encapsulate
   (((foo *) => *))
   (local (defun foo (x) x))
   (defun bar (x)
     (foo x))
   (defthm bar-prop
     (equal (bar x) x)
     :rule-classes nil))

  (defthm foo-id
    (equal (foo x) x)
    :hints ((\"Goal\" :use bar-prop)))

  ; The following event is not admissible in ACL2.

  (defthm ouch!
    nil
    :rule-classes nil
    :hints
    ((\"Goal\" :use
      ((:functional-instance foo-id
                             (foo (lambda (x) (cons x x))))))))
 })

 <p>Under the simple approach we have in mind, @('bar') is constrained to
 satisfy both its definition and @('bar-prop') because @('bar') mentions a
 function declared in the signature list of the encapsulation.  In fact,
 @('bar') is so-constrained in the ACL2 semantics of encapsulation and the
 first two events above (the @('encapsulate') and the consequence that @('foo')
 must be the identity function) are actually admissible.  But under the simple
 approach to assigning constraints, @('foo') is unconstrained because no
 theorem about it is exported.  Under that approach, @('ouch!') is provable
 because @('foo') can be instantiated in @('foo-id') to a function other than
 the identity function.</p>

 <p>It's tempting to think we can fix this by including definitions, not just
 theorems, in constraints.  But consider the following slightly more elaborate
 example.  The problem is that we need to include as a constraint on @('foo')
 not only the definition of @('bar'), which mentions @('foo') explicitly, but
 also @('abc'), which has @('foo') as an ancestor.</p>

 @({
  (encapsulate
   (((foo *) => *))
   (local (defun foo (x) x))
   (local (defthm foo-prop
            (equal (foo x) x)))
   (defun bar (x)
     (foo x))
   (defun abc (x)
     (bar x))
   (defthm abc-prop
     (equal (abc x) x)
     :rule-classes nil))

  (defthm foo-id
    (equal (foo x) x)
    :hints ((\"Goal\" :use abc-prop)))

  ; The following event is not admissible in ACL2.

  (defthm ouch!
    nil
    :rule-classes nil
    :hints
    ((\"Goal\" :use
      ((:functional-instance foo-id
                             (foo (lambda (x) (cons x x)))
                             (bar (lambda (x) (cons x x))))))))
 })")

(defxdoc constraint-info
  :parents (system-utilities constraint)
  :short "Obtaining the @(see constraint) on a function symbol"
  :long "<p>For a function symbol, @('fn'), and a logical @(see world),
 @('wrld') &mdash; for example, the current world, @('(w state)') &mdash;
 evaluation of the form @('(constraint-info fn wrld)') returns @('(mv flg c)'),
 where @('c') is the list of @(see constraint)s on @('fn') (implicitly
 conjoined), and @('flg') is @('nil') if @('fn') is a defined function and
 otherwise is a function symbol with that same list of constraints (possibly
 @('fn') itself).  See @(see constraint) for relevant background.</p>

 <p>We illustrate with the following example.</p>

 @({
 (encapsulate
   (((f1 *) => *)
    ((f3 *) => *))
   (local (defun f1 (x) x))
   (defun f2 (x) (f1 x))
   (local (defun f3 (x) x))
   (defun f4 (x) (f3 x))
   (defthm f1-prop (equal (f1 x) (f4 x))))
 })

 <p>Then we can see the results of @('constraint-info') on each introduced
 function symbol, as follows.</p>

 @({
 ACL2 !>(let ((wrld (w state)))
           (list
            'result
            'f1 (mv-let (flg1 c1) (constraint-info 'f1 wrld) (list flg1 c1))
            'f2 (mv-let (flg2 c2) (constraint-info 'f2 wrld) (list flg2 c2))
            'f3 (mv-let (flg3 c3) (constraint-info 'f3 wrld) (list flg3 c3))
            'f4 (mv-let (flg4 c4) (constraint-info 'f4 wrld) (list flg4 c4))))
 (RESULT F1
         (F1 ((EQUAL (F4 X) (F3 X))
              (EQUAL (F1 X) (F4 X))))
         F2 (NIL (EQUAL (F2 X) (F1 X)))
         F3
         (F1 ((EQUAL (F4 X) (F3 X))
              (EQUAL (F1 X) (F4 X))))
         F4
         (F1 ((EQUAL (F4 X) (F3 X))
              (EQUAL (F1 X) (F4 X)))))
 ACL2 !>
 })

 <p>Notice that the flag (first result) for @('f2') is @('nil'), because even
 though the definition of @('f2') is lexically inside the @('encapsulate'), it
 doesn't affect the constraints because it can be safely moved to just after
 the @('encapsulate').  However, the definition of @('f4') does affect (or
 ``infect''; see @(see subversive-recursions)) the constraints: it can't be
 moved to after the @('encapsulate') because of the @('defthm') after it.</p>

 <p>Also see @(see constraint).  For more details, see comments in the
 definition of @('constraint-info') in the ACL2 source code.</p>")

(defxdoc copyright
  :parents (about-acl2)
  :short "ACL2 copyright, license, sponsorship"
  :long "<p>This topic provides information about copyright, license,
 authorship, and sponsorship of the ACL2 system.  For information about
 copyright and authorship of @(see documentation), see @(see
 documentation-copyright), which notes that there are many documentation
 authors.</p>

 <p>@(`(:raw (@ acl2-version))`) &mdash; A Computational Logic for Applicative
 Common Lisp</p>

 <p>Copyright (C) 2017, Regents of the University of Texas</p>

 <p>This version of ACL2 is a descendant of ACL2 Version 1.9, Copyright (C)
 1997 Computational Logic, Inc.  See the documentation topic NOTE-2-0.</p>

 <p>This program is free software; you can redistribute it and/or modify it
 under the terms of the LICENSE file distributed with ACL2.</p>

 <p>This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the LICENSE for more details.</p>

 <p>Written by: Matt Kaufmann and J Strother Moore<br/>
 email: Kaufmann@@cs.utexas.edu and Moore@@cs.utexas.edu<br/>
 Department of Computer Science<br/>
 University of Texas at Austin<br/>
 Austin, TX 78712 U.S.A.</p>

 <p>Please also see @(see acknowledgments).</p>")

(defxdoc corollary
  :parents (rule-classes)
  :short "The corollary formula of a @(see rune)"
  :long "<p>See @(see formula).  This is a low-level system function at the
 present time.  See @(see pr) and see @(see pr!) instead.  Also see @(see
 rule-classes) for the use of the symbol @(':corollary') in specifying a rule
 class.</p>")

(defxdoc count
  :parents (lists strings acl2-built-ins)
  :short "Count the number of occurrences of an item in a string or true-list"
  :long "@({
  Example Forms:
  (count #\\D \"DabcDefcDe\")                 ; = 3
  (count #\\D \"DabcDefcDe\" :start 1)        ; = 2
  (count #\\D \"DabcDefcDe\" :start 1 :end 5) ; = 1
  (count #\\D \"DabcDefcDe\" :start 1 :end 4) ; = 0
  (count #\\z \"DabcDefcDe\")                 ; = 0
  (count '(a b) '(17 (a b) 23 (a b) (c d)))   ; = 2

  General Form:
  (count item sequence &key start end)
 })

 <p>@('(Count item sequence)') returns the number of times @('item') occurs in
 @('sequence').  The @(see guard) for calls of @('count') (which is actually a
 macro in ACL2) specifies that @('sequence') is a string or a true-list, and
 that @('start'), which defaults to 0, and @('end'), which defaults to the
 length of @('sequence'), are valid indices into sequence.</p>

 <p>See any Common Lisp documentation for more information about @('count'),
 which is a Common Lisp utility.  At this time ACL2 does not support keyword
 arguments for @('count') other than @(':start') and @(':end'); we may add
 support for the @(':from-end') keyword upon request.</p>

 @(def count)")

(defxdoc cpu-core-count
  :parents (parallelism acl2-built-ins)
  :short "The number of cpu cores"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 <p>Unless the ACL2 executable supports parallel execution (see @(see
 parallelism)), this function returns @('(mv 1 state)').  Otherwise:</p>

 <p>@('(Cpu-core-count state)') returns @('(mv core-count state)'), where
 @('core-count') is determined as follows.  If environment variable
 @('ACL2_CORE_COUNT') has a non-empty value, then that value should represent a
 positive integer (else an error occurs), which is the returned
 @('core-count').  Otherwise, the returned @('core-count') may be obtained from
 the underlying Common Lisp implementation, else as a positive integer value
 from @(see state) global variable @(''cpu-core-count') (see @(see assign)).
 Otherwise an error occurs.</p>

 @({
  Example:
  (cpu-core-count state) ==> (mv 4 state)
 })

 <p>@('Cpu-core-count') has the following logical definition.</p>

 @(def cpu-core-count)")

(defxdoc ctx
  :parents (system-utilities)
  :short "Context object for error messages"
  :long "<p>Calls of @(tsee er), such as @('(er soft ctx ...)'), take a context
 argument, typically called @('ctx'), for the initial part of the message:
 @('\"ACL2 Error in\"').  If @('ctx') is @('nil'), only @('\"ACL2 Error:\"') is
 printed for that initial part of the message.  Otherwise, the string printed
 after @('\"in\"') depends on the form of that context, as follows.</p>

 <ul>

 <li>If @('ctx') is a symbol, print it with @(tsee fmt) using @('\"~x\"').</li>

 <li>If @('ctx') is a pair whose @('car') is a symbol, use @(tsee fmt) to print
 @('\"(~x0 ~x1 ...)\"'), with @('#\\0') and @('#\\1') bound respectively to the
 @('car') and @('cdr') of @('ctx').  <b>Exception</b>: if the @('car') is a
 member of the value of constant @('*fmt-ctx-spacers*'), then a space is
 printed after the left parenthesis.  That explains why there is a space, for
 example, in @('\"( DEFUN\"') in error messages starting with:

 @({
 ACL2 Error in ( DEFUN FOO ...):
 })</li>

 <li>Otherwise, print @('ctx') with @('fmt') using @('\"~@\"').</li>

 </ul>")

(defxdoc current-package
  :parents (ld)
  :short "The package used for reading and printing"
  :long "<p>@('Current-package') is an @(tsee ld) special (see @(see ld)).  The
 accessor is @('(current-package state)') and the updater is
 @('(set-current-package val state)'), or more conventionally, @('(in-package
 val)').  The value of @('current-package') is actually the string that names
 the package.  (Common Lisp's ``package'' objects do not exist in ACL2.)  The
 current package must be known to ACL2, i.e., it must be one of the initial
 packages or a package defined with @(tsee defpkg) by the user.</p>

 <p>When printing symbols, the package prefix is displayed if it is not the
 @('current-package') and may be optionally displayed otherwise.  Thus, if
 @('current-package') is @('\"ACL2\"') then the symbol @(''ACL2::SYMB') may be
 printed as @('SYMB') or @('ACL2::SYMB'), while @(''MY-PKG::SYMB') must be
 printed as @('MY-PKG::SYMB').  But if @('current-package') is @('\"MY-PKG\"')
 then the former symbol must be printed as @('ACL2::SYMB') while the latter may
 be printed as @('SYMB').</p>

 <p>In Common Lisp, @('current-package') also affects how objects are read from
 character streams.  Roughly speaking, read and print are inverses if the
 @('current-package') is fixed, so reading from a stream produced by printing
 an object must produce an equal object.</p>

 <p>In ACL2, the situation is more complicated because we never read objects
 from character streams, we only read them from object ``streams'' (channels).
 Logically speaking, the objects in such a channel are fixed regardless of the
 setting of @('current-package').  However, our host file systems do not
 support the idea of Lisp object files and instead only support character
 files.  So when you open an object input channel to a given (character file)
 we must somehow convert it to a list of ACL2 objects.  This is done by a
 <i>deus ex machina</i> (``a person or thing that appears or is introduced
 suddenly and unexpectedly and provides a contrived solution to an apparently
 insoluble difficulty,'' Webster's Ninth New Collegiate Dictionary).  Roughly
 speaking, the <i>deus ex machina</i> determines what sequence of calls to
 @('read-object') will occur in the future and what the @('current-package')
 will be during each of those calls, and then produces a channel containing the
 sequence of objects produced by an analogous sequence of Common Lisp reads
 with @('*current-package*') bound appropriately for each.</p>

 <p>A simple rule suffices to make sane file @(see io) possible: before you
 read an object from an object channel to a file created by printing to a
 character channel, make sure the @('current-package') at read-time is the same
 as it was at print-time.</p>")

(defxdoc current-theory
  :parents (theories theory-functions)
  :short "Currently @(see enable)d rules as of logical name"
  :long "@({
  Examples:
  (current-theory :here)
  (current-theory 'lemma3)
 })

 <p>See @(see logical-name).</p>

 @({
  General Form:
  (current-theory logical-name)
 })

 <p>Returns the current theory as it existed immediately after the introduction
 of @(tsee logical-name) provided it is evaluated in an environment in which
 the variable symbol WORLD is bound to the current ACL2 logical world, @('(w
 state)').  Thus,</p>

 @({
  ACL2 !>(current-theory :here)
 })

 <p>will cause an (unbound variable) error while</p>

 @({
  ACL2 !>(let ((world (w state))) (current-theory :here))
 })

 <p>will return the current theory in world.</p>

 <p>See @(see theories) and see @(see logical-name) for a discussion of
 theories in general and why the commonly used ``theory functions'' such as
 @('current-theory') are really macros that expand into terms involving the
 variable @('world').</p>

 <p>The theory returned by @('current-theory') is in fact the theory selected
 by the @(tsee in-theory) event most recently preceding logical name, extended
 by the rules introduced up through @(tsee logical-name).</p>

 <p>You may experience a fencepost problem in deciding which logical name to
 use.  @(tsee Deflabel) can always be used to mark unambiguously for future
 reference a particular point in the development of your theory.  The order of
 @(see events) in the vicinity of an @(tsee encapsulate) is confusing.  See
 @(see encapsulate).</p>

 <p>This ``function'' is actually a macro that expands to a term mentioning the
 single free variable @(tsee world).  When theory expressions are evaluated by
 @(tsee in-theory) or the @(':')@(tsee in-theory) hint, @(tsee world) is bound
 to the current ACL2 @(see world).</p>")

(defxdoc custom-keyword-hints
  :parents (hints)
  :short "User-defined hints"
  :long "<p>See @(see add-custom-keyword-hint) for a discussion of how advanced
 users can define their own hint keywords.  For examples, see the community
 books directory @('books/hints/'), in particular @('basic-tests.lisp').</p>")

(defxdoc cw
  :parents (io acl2-built-ins)
  :short "Print to the comment window"
  :long "<p>Example:</p>

 @({
  (cw \"The goal is ~p0 and the alist is ~x1.~%\"
      (untranslate term t nil)
      unify-subst)
 })

 <p>Logically, this expression is equivalent to @('nil').  However, it has the
 effect of first printing to the so-called ``comment window'' the @(tsee fmt)
 string as indicated.  Thus, @('cw') is like @('fmt') (see @(see fmt)) except
 in three important ways.  First, it is a macro whose calls expand to calls of
 a @(':')@(tsee logic) mode function.  Second, it neither takes nor returns the
 ACL2 @(tsee state); logically @('cw') simply returns @('nil'), although it
 prints to a <i>comment window</i> that just happens to share the terminal
 screen with the standard character output @(tsee *standard-co*).  Third, its
 @('fmt') args are positional references, so that for example</p>

 @({
  (cw \"Answers: ~p0 and ~p1\" ans1 ans2)
 })

 <p>prints in the same manner as:</p>

 @({
  (fmt \"Answers: ~p0 and ~p1\"
       (list (cons #\\0 ans1) (cons #\\1 ans2))
       *standard-co* state nil)
 })

 <p>Typically, calls of @('cw') are embedded in @(tsee prog2$) forms, e.g.,</p>

 @({
  (prog2$ (cw ...)
          (mv a b c))
 })

 <p>which has the side-effect of printing to the comment window and logically
 returning @('(mv a b c)').</p>

 @({
  General Form:
  (cw fmt-string arg1 arg2 ... argn)
 })

 <p>where n is between 0 and 9 (inclusive).  The macro uses @(tsee
 fmt-to-comment-window), passing it the column @('0') and @(see evisc-tuple)
 @('nil'), after assembling the appropriate alist binding the @(tsee fmt) vars
 #\\0 through #\\9; see @(see fmt).  If you want</p>

 @({
  (a) more than 10 vars,
  (b) vars other than the digit chars,
  (c) a different column, or
  (d) a different evisc-tuple,
 })

 <p>then call @(tsee fmt-to-comment-window) instead.</p>

 <p>Also see @(see cw!), which is useful if you want to be able to read the
 printed forms back in.</p>

 <p>Finally, we discuss another way to create formatted output that also avoids
 the need to pass in the ACL2 @(tsee state).  The idea is to use wormholes; see
 @(see wormhole).  Below is a function you can write, along with some calls,
 providing an illustration of this approach.</p>

 @({
  (defun my-fmt-to-comment-window (str alist)
    (wormhole 'my-fmt-to-comment-window
              '(lambda (whs) whs)
              (list str alist)
              '(pprogn
                (fms (car (@ wormhole-input))
                     (cadr (@ wormhole-input))
                     *standard-co*
                     state
                     nil)
                (value :q))
              :ld-verbose nil
              :ld-error-action :return ; harmless return on error
              :ld-prompt nil))

  ; A non-erroneous call:
  (my-fmt-to-comment-window \"Here is ~x0 for your inspection~%\"
                            (list (cons #\\0 'foo)))

  ; An error inside the fmt string (unbound fmt var); note that even
  ; with the error, the wormhole is exited.
  (my-fmt-to-comment-window \"Here is ~x1 for your inspection~%\"
                            (list (cons #\\0 'foo)))

  ; A guard violation in the binding; note that even with the error,
  ; the wormhole is exited.
  (my-fmt-to-comment-window \"Here is ~x0 for your inspection~%\"
                            (list (cons #\\0 (car 'foo))))
 })")

(defxdoc cw!
  :parents (io acl2-built-ins)
  :short "Print to the comment window"
  :long "<p>This is the same as @(tsee cw), except that @(tsee cw) inserts
 backslash (\\) characters when forced to print past the right margin, in order
 to make the output a bit clearer in that case.  Use @('cw!') instead if you
 want to be able to read the forms back in.</p>")

(defxdoc cw-gstack
  :parents (break-rewrite debugging)
  :short "Debug a rewriting loop or stack overflow"
  :long "<p>After @(see break-rewrite) is enabled (with @(':')@(tsee brr)@('
 t')), @('cw-gstack') can be invoked to show a stack backtrace when a proof is
 interrupted (because of control-c or because of a loop).</p>

 @({
  Example Forms:
  (cw-gstack)
  (cw-gstack :frames 10)       ; show only the top 10 frames
  (cw-gstack :frames '(1 10))  ; same as above:  show only frames 1 through 10
  (cw-gstack :frames '(10 20)) ; show only frames 10 through 20
  (cw-gstack :evisc-tuple (evisc-tuple 3 4 nil nil))
                               ; print with print-level 3 and print-length 4
  (cw-gstack :evisc-tuple nil) ; print using default ``evisceration'',
                               ;   essentially the same as just above
  (cw-gstack :evisc-tuple '(nil 3 4 (hide)))
                               ; same as just above

  General Form:
  (cw-gstack :frames frames :evisc-tuple evisc-tuple)
 })

 <p>where @(':frames') and @(':evisc-tuple') are optional, but if they are
 supplied, their values are evaluated.  The value of @('frames') should be
 either a natural number or a list of two natural numbers, the first less than
 the second; and the value of @('evisc-tuple') should be an evisc-tuple (see
 @(see evisc-tuple)).  If @(':evisc-tuple') is omitted, then substructures
 deeper than 3 are replaced by ``@('#')'' and those longer than 4 are replaced
 by ``@('...')'', and terms of the form @('(hide ...)') are printed as
 @('<hidden>').  Also see @(see set-iprint) for an alternative to printing
 ``@('#')'' and ``@('...')''.</p>

 <p>Stack overflows may occur, perhaps caused by looping rewrite rules.  In
 some Lisps, stack overflows may manifest themselves as segmentation faults,
 causing the entire ACL2 image to crash.  Finding looping rewrite rules can be
 tricky, especially if you are using books supplied by other people.  (However,
 see @(see set-rewrite-stack-limit) for a way to avoid stack overflows caused
 by rewriter loops.)</p>

 <p>Normally, a stack overflow will cause the printing of an error message that
 suggests how to proceed.  Just follow those instructions, and you will
 generally be able to see what is causing the loop.</p>

 <p>Suggestion: Once you have found the loop and fixed it, you should execute
 the ACL2 command @(':')@(tsee brr)@(' nil'), so that you don't slow down
 subsequent proof attempts.</p>")

(defxdoc |Common Lisp|
  :parents (|Pages Written Especially for the Tours|)
  :short "Common Lisp"
  :long "<p><see topic='@(url
 |An Example Common Lisp Function Definition|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p><img src='res/tours/common-lisp.gif'></img></p>

 <p>The logic of ACL2 is based on Common Lisp.</p>

 <p>Common Lisp is the standard list processing programming language.  It is
 documented in: Guy L. Steele, <a
 href='https://www.cs.cmu.edu/Groups/AI/html/cltl/cltl2.html'><b>Common Lisp
 The Language</b></a>, Digital Press, 12 Crosby Drive, Bedford, MA 01730,
 1990.</p>

 <p>ACL2 formalizes only a subset of Common Lisp.  It includes such familiar
 Lisp functions as @('cons'), @('car') and @('cdr') for creating and
 manipulating list structures, various arithmetic primitives such as @('+'),
 @('*'), @('expt') and @('<='), and @('intern') and @('symbol-name') for
 creating and manipulating symbols.  Control primitives include @('cond'),
 @('case') and @('if'), as well as function call, including recursion.  New
 functions are defined with @('defun') and macros with @('defmacro').  See
 @(see programming) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for a list of the Common Lisp primitives
 supported by ACL2.</p>

 <p>ACL2 supports five of Common Lisp's datatypes:</p>

 <p>* the precisely represented, unbounded numbers (integers, rationals, and
 the complex numbers with rational components, called the ``complex rationals''
 here),</p>

 <p>* the characters with ASCII codes between 0 and 255</p>

 <p>* strings of such characters</p>

 <p>* symbols (including packages)</p>

 <p>* conses</p>

 <p>ACL2 is a very small subset of full Common Lisp.  ACL2 does not include the
 Common Lisp Object System (CLOS), higher order functions, circular structures,
 and other aspects of Common Lisp that are <b>non-applicative</b>.  Roughly
 speaking, a language is applicative if it follows the rules of function
 application.  For example, @('f(x)') must be equal to @('f(x)'), which means,
 among other things, that the value of @('f') must not be affected by ``global
 variables'' and the object @('x') must not change over time.</p>

 <p><see topic='@(url |An Example Common Lisp Function Definition|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |Common Lisp as a Modeling Language|
  :parents (|Pages Written Especially for the Tours|)
  :short "Common Lisp as a Modeling Language"
  :long "<p><img src='res/tours/common-lisp.gif'></img></p>

 <p>In ACL2 we have adopted Common Lisp as the basis of our modeling language.
 If you have already read our brief note on Common Lisp and recall the example
 of @('app'), please proceed.  Otherwise click <see topic='@(url
 |Common Lisp|)'>here</see> for an exceedingly brief introduction to Common
 Lisp and then come <b>back</b> here.</p>

 <p>In Common Lisp it is very easy to write systems of formulas that manipulate
 discrete, inductively constructed data objects.  In building a model you might
 need to formalize the notion of sequences and define such operations as
 concatenation, length, whether one is a permutation of the other, etc.  It is
 easy to do this in Common Lisp.  Furthermore, if you have a Common Lisp
 ``theory of sequences'' you can <b>run</b> the operations and relations you
 define.  That is, you can execute the functions on concrete data to see what
 results your formulas produce.</p>

 <p>If you define the function @('app') as shown above and then type</p>

 @({
  (app '(A B) '(C D E))
 })

 <p>in any Common Lisp, the answer will be computed and will be @('(A B C D
 E)').</p>

 <p>The <b>executable</b> nature of Common Lisp and thus of ACL2 is very handy
 when producing models.</p>

 <p>But executability is not enough for a modeling language because the purpose
 of models is to permit analysis.</p>

 <p>Click <see topic='@(url |Analyzing Common Lisp Models|)'>here</see> to
 continue.</p>")

(defxdoc |Conversion|
  :parents (|Pages Written Especially for the Tours|)
  :short "Conversion to Uppercase"
  :long "<p>When symbols are read by Common Lisp they are converted to upper
 case.  Note carefully that this remark applies to the characters in
 <i>symbols</i>.  The characters in strings are not converted upper case.</p>

 <p>To type a symbol containing lower case characters you can enclose the
 symbol in vertical bars, as in @('|AbC|') or you can put a ``backslash''
 before each lower case character you wish to preserve, as in @('A\\bC').
 @('|AbC|') and @('A\\bC') are two different ways of writing the same symbol
 (just like 2/4 and 1/2 are two different ways of writing the same rational and
 123 and 0123 are two different ways to write the same natural number).  The
 symbol has three characters in its name, the middle one of which is a lower
 case b.</p>")

(defxdoc |Corroborating Models|
  :parents (|Pages Written Especially for the Tours|)
  :short "Corroborating Models"
  :long "<p><see topic='@(url |Models of Computer Hardware and Software|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>After producing a model, it must be <b>corroborated</b> against reality.
 The Falling Body Model has been corroborated by a vast number of experiments
 in which the time and distance were measured and compared according to the
 formula.  In general all models must be corroborated by experiment.</p>

 <p>The Falling Body Model can be derived from deeper models, namely Newton's
 laws of motion and the assertion that, over the limited distances concerned,
 gravitation exerts a constant acceleration on the object.  When the model in
 question can be derived from other models, it is the other models that are
 being corroborated by our experiments.</p>

 <p>Because nature is not formal, we cannot <b>prove</b> that our models of it
 are correct.  All we can do is test our models against nature's behavior.</p>

 <p>Such testing often exposes restrictions on the applicability of our models.
 For example, the Falling Body Model is inaccurate if air resistance is
 significant.  Thus, we learn not to use that model to predict how long it
 takes a feather to fall from a 200 foot tower in the earth's atmosphere.</p>

 <p>In addition, attempts at corroboration might reveal that the model is
 actually incorrect.  Careful measurements might expose the fact that the
 gravitational force increases as the body falls closer to earth.  Very careful
 measurements might reveal relativistic effects.  Technically, the familiar
 Falling Body Model is just wrong, even under excessive restrictions such as
 ``in a perfect vacuum'' and ``over small distances.''  But it is an incredibly
 useful model nonetheless.</p>

 <p>There are several morals here.</p>

 <p><b>Models need not be complete to be useful.</b></p>

 <p><b>Models need not be perfectly accurate to be useful.</b></p>

 <p><b>The user of a model must understand its limitations.</b></p>

 <p><see topic='@(url |Models of Computer Hardware and Software|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc dead-events
  :parents (debugging)
  :short "Using proof supporters to identify dead code and unused theorems"
  :long "<p>Below, when we talk about ``an event @('A')'', we mean an event
 whose name is @('A').</p>

 <p>When event @('A') is used in a proof performed to admit event @('B') that
 you submit to ACL2, we say that @('A') is a ``proof-supporter'' of @('B').
 ACL2 stores an association list such that for every event @('B') with at least
 one proof-supporter, @('B') is associated with a list of all of its
 proof-supporters, sorted by @(tsee symbol-<).  The following form evaluates to
 that alist, which is called the ``proof-supporters-alist''.</p>

 @({
  (global-val 'proof-supporters-alist (w state))
 })

 <p>By ``used in a proof'' above, we mean: applied as a rule or supplied
 explicitly via @(see hints) of type @(':use'), @(':by'), or
 @(':clause-processor').  That is, the @(see events) ``used in a proof'' for
 admitting an event @('E') are those listed in the summary printed at the
 conclusion of admitting @('E').</p>

 <p>Note that if proofs are skipped when admitting event @('E'), say because
 the last admission of @('E') was done by @(tsee include-book) (or
 @('certify-book'), which ends with an @(tsee include-book)), then there will
 be no entry in that alist for @('E').  (An exception is made however for
 @(tsee encapsulate) @(see events), where proof-supporters are remembered from
 the first pass; see below.)  So if you want the proof-supporters-alist to
 include supporters for events in a book, use @(tsee ld) rather than @(tsee
 include-book) or @(tsee certify-book) to process the events in that book.  If
 however you are interested in the proof-supporters FROM a book that support a
 later event, then it is fine to include that book.</p>

 <p>The case for @(tsee encapsulate) is slightly tricky.  Consider an example
 of the following form.</p>

 @({
  A ; event preceding the encapsulate
  (encapsulate
   ()
   B
   (local C) ; uses A and B in a proof
   D ; uses C in a proof
   )
 })

 <p>At the conclusion of this @(tsee encapsulate) event, the
 proof-supporters-alist associates @('D') with @('A') and @('B'), but not
 @('C') (which has disappeared, since it is @(see local)).</p>

 <p>Note that this sort of ``transitive closure'' operation is only performed
 when necessary due to the disappearance of @(see local) @(see events).  For
 example, if we replace @('(local C)') above by just @('C'), then @('D') is
 associated in the proof-supporters-alist only with @('C'), not with @('A') or
 @('B').  If you want the transitive closure of the relation computed by the
 proof-supporters-alist, you have to compute it yourself. (This was a
 deliberate design decision, in order to avoid slowing down event processing.)
 However, there is help available on how to do such a computation:</p>

 <p>A community book, @('books/tools/dead-events.lisp'), does such a transitive
 closure, and moreover uses that information to find ``dead events'' relative
 to a list of ``desired'' events.  For example, suppose you use @(tsee LD) to
 process the events, with proofs, in a book intended to prove theorems
 @('MAIN-1') and @('MAIN-2').  (Remember, @(tsee certify-book) will not save
 such information.)  Suppose furthermore that the book begins with some @(tsee
 include-book) forms followed by @('(deflabel book-start)').  You could
 evaluate this form:</p>

 @({
  (dead-events '(main-1 main-2) :start 'book-start)
 })

 <p>The result is a list of events that you probably can delete from the book
 without causing any proofs to fail.  See the @('dead-events.lisp') book for
 further documentation.</p>

 <p>You might also find the code in the above book to be helpful for writing
 your own utilities based on the proof-supporters-alist.</p>")

(defxdoc dealing-with-key-combinations-of-function-symbols
  :parents (introduction-to-the-theorem-prover)
  :short "How to get rid of key combinations of function symbols"
  :long "<p>Suppose @('REV') reverses a list, @('MEMBER') checks that its first
 argument is an element of its second, and @('SQUARES-PLUS-3P') is some
 complicated predicate.  Suppose you're proving some Main Theorem that involves
 those concepts and the theorem prover presents you with the following hideous
 formula as a key checkpoint.  What action should you take?</p>

 <p>Hint: Don't read the formula ``for sense,'' i.e., don't try to understand
 what this formula is saying!  Just look at every subterm involving a nest of
 two function symbols and ask if you know something about those two symbols
 that allows you to <i>simplify</i> that one subterm.</p>

 @({
  (IMPLIES (AND (CONSP X)
                (MEMBER (+ 3 (* I I)) (REV X))
                (LIST-OF-INTEGERS X)
                (INTEGERP I)
                (<= 0 I)
                (INTEGERP K)
                (<= 0 K)
                (< I K)
                (SQUARES-PLUS-3P K X)
                (NOT (EQUAL (CAR X) (+ 3 (* I I))))
                (NOT (MEMBER (+ 3 (* I I)) X)))
           (SQUARES-PLUS-3P K (REV X)))?
 })

 <p>The experienced ACL2 user will stop reading at the second hypothesis!</p>

 @({
                (MEMBER (+ 3 (* I I)) (REV X))
 })

 <p>The combination of @('MEMBER') and @('REV') can be simplified.  The
 question ``is @('e') a member of @('(REV x)')'' can be answered by asking ``is
 @('e') a member of @('x')''.  The two questions are equivalent.  This insight
 comes from your intuition about the <i>semantics</i> of @('REV') &mdash; it
 just reorders the elements but doesn't add or delete any.  The second question
 is simpler since it doesn't mention @('REV'), so this is a good transformation
 to make.  And the theorem that they are equivalent is simpler than the key
 checkpoint above because it involves fewer functions and smaller
 expressions.</p>

 <p>You might formalize this insight as</p>

 @({
  (equal (member e (rev x))
         (member e x))
 })

 <p>But this conjecture is <i>not</i> a theorem, because @('(member e x)')
 returns the @('cdr') of @('x') that begins with @('e'), not just a Boolean
 (@('t') or @('nil')) indicating whether @('e') is an element of @('x').  The
 location of the first @('e') in @('(rev x)') is generally different than the
 location in @('x').  So when we say the two questions are ``equivalent'' we
 don't mean they are equal.  We mean that they're propositionally equivalent:
 both @('nil') or both non-@('nil').  This sense of equivalence is called ``if
 and only if'' and is checked by the function @('iff').</p>

 <p>So our intuitive insight can be phrased as this theorem:</p>

 @({
  (iff (member e (rev x))
       (member e x))
 })

 <p>Suggesting that this formulation of the insight is ``obvious'' begs many
 questions.  Mathematically, we could have avoided @('iff') and just written
 two implications:</p>

 @({
  (and (implies (member e x) (member e (rev x)))
       (implies (member e (rev x)) (member e x))).
 })

 <p>or</p>

 @({
  (and (implies (member e x) (member e (rev x)))
       (implies (not (member e x))  (not (member e (rev x))))).
 })

 <p>Or we could have used @('iff') but ``oriented'' it the other way:</p>

 @({
  (iff (member e x)
       (member e (rev x)))
 })

 <p>We choose to write</p>

 @({
  (iff (member e (rev x))
       (member e x))
 })

 <p>because of <i>our knowledge of how ACL2 turns formulas into rules!</i></p>

 <p>We deal with this at greater length later.  But just to drive the point
 home, if we issue the command:</p>

 @({
  (defthm member-rev
    (iff (member e (rev x))
         (member e x)))
 })

 <p>ACL2 will build in a rule that causes every propositional occurrence of
 @('(MEMBER e (REV x))') to be replaced by @('(MEMBER e x)').  (By
 ``propositional occurrence'' we mean an occurrence in which the value is
 tested, as by @('IF') or the propositional connectives.  Remember, one might
 use @('member') to determine the location of an element too.)</p>

 <p>Note carefully: <i>if you do not tell ACL2 how to make a rule</i> from a
 theorem, it makes a rewrite rule.  Rewrite rules always replace instances of
 the left-hand side by the corresponding instances of the right-hand side.
 That is, when interpreted as a rewrite rule, @('(iff ')<i>alpha</i>
 <i>beta</i>@(')') makes ACL2 replace <i>alpha</i> by <i>beta</i>.</p>

 <p>Probably the biggest mistake new users make is forgetting that every
 theorem they prove creates a very specific rule.  You must remember that you
 are <i>programming</i> ACL2 with these rules.  Being careless in your
 statement of theorems is tantamount to being careless in your programming.
 What you get is a mess.</p>

 <p>Had we proved the same equivalence, but with the @('iff') commuted, we
 would be giving ACL2 <i>bad advice</i>.  We would be telling it ``replace
 instances of @('(MEMBER e x)') by the corresponding instances of @('(MEMBER e
 (REV x))')''!  If ACL2 had that rule and ever tried to simplify any
 @('member') expression, e.g., @('(MEMBER A B)'), it would get into an infinite
 loop, e.g., producing the following sequence of transformations:</p>

 @({
  (MEMBER A B)
  (MEMBER A (REV B))
  (MEMBER A (REV (REV B)))
  ...
 })

 <p>until it eventually exhausted some resource.</p>

 <p>Recall that we entertained the idea of phrasing our insight about
 @('member') and @('rev') with implications rather than @('iff').  Generally
 speaking, implications produce weaker rules &mdash; rules that apply less
 often.  We discuss that later.</p>

 <p>Now suppose we've proved @('member-rev'), oriented so as to rewrite
 @('(member e (rev x))') to @('(member e x)'), and built it in as a rewrite
 rule.  Then suppose we repeated the attempt to prove our Main Theorem.  This
 time, when the prover is processing the hideous Key Checkpoint printed above,
 our new lemma, @('member-rev'), will hit it.  It will transform the formula
 to:</p>

 @({
  (IMPLIES (AND (CONSP X)
                (MEMBER (+ 3 (* I I)) X)   ; <-- the hyp has simplified
                (LIST-OF-INTEGERS X)
                (INTEGERP I)
                (<= 0 I)
                (INTEGERP K)
                (<= 0 K)
                (< I K)
                (SQUARES-PLUS-3P K X)
                (NOT (EQUAL (CAR X) (+ 3 (* I I))))
                (NOT (MEMBER (+ 3 (* I I)) X)))
           (SQUARES-PLUS-3P K (REV X)))?
 })

 <p>and then that will collapse to @('T'), since the @('IMPLIES') has
 contradictory hypotheses (note the last hypothesis above).</p>

 <p>By proving @('member-rev') we proved the hideous checkpoint.  We never had
 to look at the rest of the formula or think about why it is a theorem.
 Furthermore, attacking the main theorem again, from scratch, with
 @('member-rev') in the database, may eliminate other checkpoints that came up
 the last time we tried to prove our main goal.  So we recommend addressing one
 checkpoint at a time.</p>

 <p>This example illustrates that purely <i>local</i> thinking &mdash; looking
 for simplifiable combinations of function symbols &mdash; can sometimes lead
 to proofs and should always be your first reaction to a key checkpoint: what
 local fact do you know that would clean up the formula?  Don't think about
 deep questions like ``why is this true?'' until you can't see any way to make
 it simpler.</p>

 <p>It is important to train yourself to see combinations of function symbols
 and to create strong rules for eliminating them.  We will give you
 opportunities to practice this later in the tutorial.</p>

 <p>If you have been reading the tutorial introduction to the theorem prover,
 use your browser's <b>Back Button</b> now to return to @(see
 INTRODUCTION-TO-KEY-CHECKPOINTS).</p>")

(defxdoc dealing-with-tau-problems
  :parents (introduction-to-the-tau-system)
  :short "Some advice on dealing with problems caused by the tau system"
  :long "<p>For background on the tau system, see @(see
 introduction-to-the-tau-system).  The two most common problems caused by the
 tau system have to do with the system's interaction with ``legacy'' proof
 scripts.  Such scripts may suffer because they were not designed to exploit
 tau reasoning and which may configure the tau database in quite incomplete and
 arbitrary ways.  The two most common problems we have seen are (a) significant
 slow downs in a few proofs and (b) failed proof attempts due to hints being
 misapplied because the tau system caused subgoals to be renumbered.</p>

 <p>We discuss the rather limited means of dealing with these problems here.
 In @(see future-work-related-to-the-tau-system) we list some major
 inadequacies of the tau system.</p>

 <p>If the tau system contributes to a proof, the @(see rune) @('(:')@(tsee
 executable-counterpart)@(' tau-system)') will be listed among the Rules in the
 Summary.  However, merely by being attempted the tau system can slow down
 proofs in which it makes no contribution.</p>

 <p>The most brutal and fool-proof way to isolate a proof from the tau system
 is to disable the entire system.  This can be done globally by</p>

 @({
  (in-theory (disable (tau-system)))  ; (:executable-counterpart tau-system)
 })

 <p>or locally with a subgoal specific hint:</p>

 @({
  ...
  :hints ((\"...subgoal id...\" :in-theory (disable (tau-system))))
 })

 <p>Conducting a proof with and without the participation of the tau system can
 help you determine whether tau reasoning is helping or hurting.</p>

 <p><i>Dealing with Slowdowns</i></p>

 <p>The @(tsee time-tracker) utility was added to allow users to investigate
 whether excessive amounts of time are being spent in a given function.  It was
 then used to annotate the code for the tau system as described in @(see
 time-tracker-tau).  The result is that if ``excessive'' time is spent in tau
 reasoning, messages to that effect will be printed to the proof log.  The
 question is: aside from disabling the tau system how can the proof be sped
 up?</p>

 <p>There are two common causes of slowdown in the tau system.  The first stems
 from the system's use of @(':')@(tsee executable-counterpart)s to determine
 whether a constant has a given tau.  Recall that a tau is a conjunction of
 monadic predicates.  To determine whether some constant satisfies the tau, the
 predicates are executed.  If you have a hard-to-compute predicate this can be
 very slow.  The most typical such predicates in ACL2 applications are those
 that check invariants, e.g., that recognize ``good states'' or ``well-formed
 data.''  These are often written inefficiently because they are intended only
 for used in theorems and, before the tau system was added, they may have never
 been applied to constants.  The most common constants tau predicates are
 applied to are @('0'), @('T'), and @('NIL'), although different models may
 stress other constants.  To understand why @('NIL') for example is frequently
 tested, if the test of an @('IF')-expression is computed to have tau <i>s</i>
 then the next question we ask is ``does @('nil') satisfy <i>s</i>?''</p>

 <p>You may determine whether the tau system is spending time executing tau
 predicates by observing the rewriter &mdash; see @(see dmr) &mdash; or by
 interrupting the system and getting a backtrace (see @(see
 set-debugger-enable)).</p>

 <p>If excessive time is being spent in a tau predicate, a draconian solution
 is to disable the @(':')@(tsee executable-counterpart) of that predicate, for
 example in either of these equivalent ways.  The tau system does not execute
 disabled @(':')@(tsee executable-counterpart)s.</p>

 @({
  (in-theory (disable (:executable-counterpart foo)))
  (in-theory (disable (foo)))
 })

 <p>In either case above, you may prefer to provide local @(':')@(tsee
 in-theory) @(':')@(tsee hints) rather than @(':in-theory') @(see events).</p>

 <p>Disabling the executable-counterpart of expensive tau predicates will
 weaken the tau system, probably only negligibly, because it can no longer run
 the predicates to determine whether they admits given constants.</p>

 <p>A more sophisticated solution is to make the tau system record values of
 the @(':')@(tsee logic)-mode function in question, so that the system will
 look up the necessary values rather than running the function every time the
 question arises.  It will look up recorded values whether the
 executable-counterpart of the tau predicate is enabled or disabled.  Here is
 an example of a lemma that can provide such a solution.  See the discussion of
 the <i>Eval</i> form of @(':')@(tsee tau-system) rules.</p>

 @({
  (defthm lemma
    (and (foo 0)
         (foo 17)
         (foo t)
         (not (foo '(a b c))))
    :rule-classes :tau-system)
 })

 <p>It might be difficult to determine <i>which</i> constants are being
 repeatedly tested, although tracing (@(tsee trace$)) suspected tau predicates
 will show what they are being called on.</p>

 <p>At the moment there are no better user-level tools to discover this.
 However, some users may wish to consider the following hack: In the ACL2
 source file @('tau.lisp'), immediately after the definition of the system
 function @('ev-fncall-w-tau-recog'), there is a comment which contains some
 raw Lisp code that can be used to investigate whether tau's use of evaluation
 on constants is causing a problem and to determine which constants are
 involved.</p>

 <p>The second main cause of slowdowns by the tau system is that the system
 contains ``too many'' conjunctive rules (see the <i>Conjunctive</i> form in
 @(tsee tau-system)).  Unfortunately, we have no tools for either identifying
 the problem or addressing it!  That said, let us tell you what we do know!</p>

 <p>Conjunctive rules are used to ``complete'' each tau as it is built.
 Referring to the @('weekdayp') example in @(tsee tau-system), if a tau is
 constructed that recognizes weekdays but not @('MON'), @('TUE'), @('THU'), or
 @('FRI'), it is completed by adding that the tau recognizes (only) @('WED').
 This means that when we construct a tau we scan all known conjunctive rules
 and see whether all but one of the literals of any conjunctive rule are
 present.  This can be expensive.  To mitigate this expense, the tau system
 caches the computation on a per proof basis (the cache is cleared after every
 proof).</p>

 <p>To learn what conjunctive rules there are in your system, evaluate</p>

 @({
  (assoc 'tau-conjunctive-rules (tau-database (w state)))
 })

 <p>Perhaps by sending the implementors that list, we can think of ways to
 index the conjunctive rules to save time.</p>

 <p><i>Dealing with Misapplied Hints</i></p>

 <p>The second common problem caused by the tau system in legacy proof scripts
 is that it can cause subgoals to be renumbered and thus cause hints to be
 missed.  The only ways to address this problem is either to disable the tau
 system (locally or globally by disabling @('(:executable-counterpart
 tau-system)')) or change the legacy hints to use the new subgoal names.</p>")

(defxdoc debugging
  :parents (top

; Including acl2 as a parent so that all ACL2 system topics can be found under
; the graph rooted at the acl2 node.

            acl2)
  :short "Tools for debugging failed or slow proofs, or misbehaving
 functions.")

(defxdoc declare

; Warning: Keep this in sync with ACL2 source function acceptable-dcls-alist.

  :parents (programming acl2-built-ins)
  :short "Extra declarations that can occur in function definitions, @(see let)
  bindings, and so forth."

  :long "<p>Common Lisp provides a declaration mechanism that allows the
 programmer to explain additional information to the compiler.  For
 instance:</p>

 <ul>

 <li>The programmer might declare that some variable always has some particular
 type.  The compiler might then, depending on its optimization/safety settings,
 either add run-time checks to ensure that this really is true, or optimize the
 compiled code by assuming the variable has the correct type.</li>

 <li>The programmer might declare that some variable is @('ignore')d.  The
 compiler might then, instead of warning the programmer that the variable is
 never used, explicitly check to make sure that it really is never used.</li>

 </ul>

 <p>ACL2 supports the above kinds of declarations, and also adds its own kinds
 of declarations for specifying things like the @(see guard)s and @(see
 measure)s of functions, as described in @(see xargs).</p>

 <p>There are also other kinds of Common Lisp declarations that ACL2 does not
 support, e.g., pertaining to inlining, safety settings, variable lifetime, and
 so forth.</p>

 <h3>Usage</h3>

 <p>Examples:</p>

 @({
 (declare (ignore x y z))
 (declare (ignorable x y z)
          (irrelevant w) ; for DEFUN only
          (type integer i j k)
          (type (satisfies integerp) m1 m2))
 (declare (xargs :guard (and (integerp i)
                             (<= 0 i))
                 :guard-hints ((\"Goal\" :use (:instance lemma3
                                               (x (+ i j)))))))
 })

 <p>General Form:</p>

 @({
     (declare d1 ... dn)
 })

 <p>where, in ACL2, each @('di') is of one of the following forms:</p>

 <dl>

 <dt>@('(ignore v1 ... vn)')</dt>

 <dd>where each @('vi') is a variable introduced in the immediately superior
 lexical environment.  These variables must not occur free in the scope of the
 declaration.  This declaration can be useful for inhibiting compiler warnings;
 see also @(see set-ignore-ok).</dd>

 <dt>@('(ignorable v1 ... vn)')</dt>

 <dd>where each @('vi') is a variable introduced in the immediately superior
 lexical environment.  These variables need not occur free in the scope of the
 declaration.  This declaration can be useful for inhibiting compiler warnings;
 see also @(see set-ignore-ok).</dd>

 <dt>@('(irrelevant v1 ... vn)')</dt>

 <dd>where each @('vi') is a formal parameter declared at the top level of a
 surrounding @(tsee defun) form, as shown below.  See @(see irrelevant-formals)
 for more information.</dd>

 <dt>@('(type type-spec v1 ... vn)')</dt>

 <dd>where each @('vi') is a variable introduced in the immediately superior
 lexical environment and @('type-spec') is a type specifier (as described in
 the documentation for @(see type-spec)).  This declaration can be useful for
 optimizing Common Lisp execution speed.  See also @(see the).</dd>

 <dt>@('(xargs :key1 val1 ... :keyn valn)')</dt>

 <dd>where the legal values of the keys and values are described in the
 documentation for @(see xargs).  These declarations are only allowed at the
 top level of definitions (@(tsee defun) and @(tsee defmacro), as shown below),
 and convey information such as the @(see guard) and @(see measure) for a
 function.</dd>

 <dt>@('(optimize ...)')</dt>

 <dd>for example, @('(optimize (safety 3))').  This is allowed only at the top
 level of @(tsee defun) forms and is probably only rarely of any interest.  See
 any Common Lisp documentation for more information.</dd>

 </dl>

 <p>Declarations in ACL2 may occur only where @('dcl') occurs below:</p>

 <ul>
 <li>@('(DEFUN name args doc-string dcl ... dcl body)')</li>
 <li>@('(DEFMACRO name args doc-string dcl ... dcl body)')</li>
 <li>@('(LET ((v1 t1) ...) dcl ... dcl body)')</li>
 <li>@('(MV-LET (v1 ...) term dcl ... dcl body)')</li>
 <li>@('(FLET ((name args dcl ... dcl body) ...))')</li>
 </ul>

 <p>Of course, if a form macroexpands into one of these (e.g., as @(tsee let*)
 expands into nested @(tsee let)s and our @('er-let*') expands into nested
 @(tsee mv-let)s) then declarations are permitted as handled by the macros
 involved.</p>

 <p>@('Declare') is defined in Common Lisp.  See any Common Lisp documentation
 for more information.</p>")

(defxdoc declare-stobjs
  :parents (stobj declare)
  :short "Declaring a formal parameter name to be a single-threaded object"
  :long "<p>When a @(tsee defun) uses one of its formals as a single-threaded
 object (@(see stobj)), the @('defun') <i>must</i> include a declaration that
 the formal is to be so used.  An exception is the formal ``@(tsee state),''
 which if not declared as explained below, may still be used provided an
 appropriate global ``declaration'' is issued: see @(see set-state-ok).</p>

 <p>If the formal in question is @('counters') then an appropriate declaration
 is</p>

 @({
  (declare (xargs :stobjs counters))
 })

 <p>or, more generally,</p>

 @({
  (declare (xargs :stobjs (... counters ...)))
 })

 <p>where all the single-threaded formals are listed.</p>

 <p>For such a declaration to be legal it must be the case that all the names
 have previously been defined as single-threaded objects with @(tsee
 defstobj).</p>

 <p>When an argument is declared to be single-threaded the guard of the
 function is augmented by conjoining to it the condition that the argument
 satisfy the recognizer for the single-threaded object.  Furthermore, the
 syntactic checks done to enforce the legal use of single-threaded objects are
 also sufficient to allow these guard conjuncts to be automatically proved.</p>

 <p>The obvious question arises: Why does ACL2 insist that you declare stobj
 names before using them in @('defun')s if you can only declare names that have
 already been defined with @('defstobj')?  What would go wrong if a formal were
 treated as a single-threaded object if and only if it had already been so
 defined?</p>

 <p>Suppose that one user, say Jones, creates a book in which @('counters') is
 defined as a single-threaded object.  Suppose another user, Smith, creates a
 book in which @('counters') is used as an ordinary formal parameter.  Finally,
 suppose a third user, Brown, wishes to use both books.  If Brown includes
 Jones' book first and then Smith's, then Smith's function treats @('counters')
 as single-threaded.  But if Brown includes Smith's book first, the argument is
 treated as ordinary.</p>

 <p>ACL2 insists on the declaration to ensure that the definition is processed
 the same way no matter what the context.</p>")

(defxdoc defabbrev
  :parents (macros events programming)
  :short "A convenient form of macro definition for simple expansions"
  :long "@({
  Examples:
  (defabbrev snoc (x y) (append y (list x)))
  (defabbrev sq (x) (declare (type (signed-byte 8) x)) (* x x))

  General Form:
  (defabbrev name (v1 ... vn) doc-string decl1 ... declk body)
 })

 <p>where @('name') is a new function symbol, the @('vi') are distinct variable
 symbols, and @('body') is a term.  The @('decli'), if supplied, should be
 legal @('declare') forms; see @(see declare).  @('Doc-string'), if
 non-@('nil'), is an optional string that can provide documentation but is
 essentially ignored by ACL2.</p>

 <p>Roughly speaking, the @('defabbrev') event is akin to defining @('f') so
 that @('(f v1 ... vn) = body').  But rather than do this by adding a new
 axiom, @('defabbrev') defines @('f') to be a macro so that @('(f a1 ... an)')
 expands to @('body'), with the ``formals,'' @('vi'), replaced by the
 ``actuals,'' @('ai').</p>

 <p>For example, if @('snoc') is defined as shown in the first example above,
 then @('(snoc (+ i j) temp)') is just an abbreviation for</p>

 @({
  (append temp (list (+ i j))).
 })

 <p>In order to generate efficiently executable Lisp code, the macro that
 @('defabbrev') introduces uses a @(tsee let) to bind the ``formals'' to the
 ``actuals.''  Consider the second example above.  Logically speaking, @('(sq
 (ack i j))') is an abbreviation for @('(* (ack i j) (ack i j))').  But in fact
 the macro for @('sq') introduced by @('defabbrev') actually arranges for
 @('(sq (ack i j))') to expand to:</p>

 @({
  (let ((x (ack i j)))
    (* x x))
 })

 <p>which executes more efficiently than @('(* (ack i j) (ack i j))').</p>

 <p>In the theorem prover, the @('let') above expands to</p>

 @({
  ((lambda (x) (* x x)) (ack i j))
 })

 <p>and thence to @('(* (ack i j) (ack i j))').</p>

 <p>It is important to note that the term in @('body') should not contain a
 call of @('name') &mdash; i.e., @('defabbrev') should not be used in place of
 @('defun') when the function is recursive.  ACL2 will not complain when the
 @('defabbrev') form is processed, but instead ACL2 will more than likely go
 into an infinite loop during macroexpansion of any form that has a call of
 @('name').</p>

 <p>It is also important to note that the parameters of any call of a macro
 defined by defabbrev will, as is the case for the parameters of a function
 call, be evaluated before the body is evaluated, since this is the evaluation
 order of @(tsee let).  This may lead to some errors or unexpected
 inefficiencies during evaluation if the body contains any conditionally
 evaluated forms like @('cond'), @('case'), or @('if').  Consider the following
 example.</p>

 @({
  (defabbrev foo (x y)
    (if (test x) (bar y) nil))
 })

 <p>Notice a typical one-step expansion of a call of @('foo') (see @(see
 trans1)):</p>

 @({
  ACL2 !>:trans1 (foo expr1 expr2)
   (LET ((X EXPR1) (Y EXPR2))
        (IF (TEST X) (BAR Y) NIL))
  ACL2 !>
 })

 <p>Now imagine that @('expr2') is a complicated expression whose evaluation is
 intended only when the predicate @('test') holds of @('expr1').  The expansion
 above suggests that @('expr2') will always be evaluated by the call @('(foo
 expr1 expr2)'), which may be inefficient (since perhaps we only need that
 value when @('test') is true of @('expr1')).  The evaluation of @('expr2') may
 even cause an error, for example in @(':')@(tsee program) mode if the
 expression @('expr2') has been constructed in a manner that could cause a
 guard violation unless @('test') holds of @('expr1').</p>")

(defxdoc defabsstobj
  :parents (events stobj)
  :short "Define a new abstract single-threaded object"
  :long "<p>We assume familiarity with single-threaded objects; see @(see
 stobj) and see @(see defstobj).  The event @('defabsstobj') defines a
 so-called ``abstract stobj'', a notion we introduce briefly now and then
 explain in more depth below.</p>

 <p>The evaluation of a @(see defstobj) event produces logical definitions for
 several functions: a recognizer, which characterizes the @(see stobj) in terms
 of lists; a creator, which produces an initial suitable list structure; and
 field accessors and updaters, defined in terms of @(tsee nth) and @(tsee
 update-nth).  @('Defabsstobj') provides a way to define alternate definitions
 for ``stobj primitives'' for a corresponding single-threaded object.  These
 stobj primitives include a recognizer, a creator, and other ``exported''
 functions.  In essence, @('defabsstobj') establishes interface functions, or
 ``exports'', on a new stobj that is a copy of an indicated ``concrete'' stobj
 that already exists.</p>

 <p>We begin below with an introduction to abstract @(see stobj)s.  We then
 explain the @(tsee defabsstobj) event by way of an example.  We conclude by
 giving summary documentation for the @('defabsstobj') event.</p>

 <p>For another introduction to abstract stobjs, see the paper ``Abstract
 Stobjs and Their Application to ISA Modeling'' by Shilpi Goel, Warren A. Hunt,
 Jr., and Matt Kaufmann, in the proceedings of <a
 href='http://www.cs.uwyo.edu/~ruben/acl2-13'>ACL2 Workshop 2013</a>.</p>

 <p><b>INTRODUCTION</b></p>

 <p>We start with a brief review of @(see stobj)s and some potential problems
 with them, followed by an introduction to abstract stobjs and how they can
 avoid these problems.  Prior experience with stobjs will probably help the
 reader to absorb the ideas below.</p>

 <p>Recall that single-threaded objects, or @(see stobj)s, provide a way for
 ACL2 users to stay within the ACL2 logic, where every data object is an atom
 or a @(tsee cons) of data objects, while obtaining the benefits of fast
 evaluation through destructive updates.  Consider for example this very simple
 event.</p>

 @({
  (defstobj st fld)
 })

 <p>This event introduces a recognizer, @('stp'), and a creator,
 @('create-st'), for a data structure consisting of a single field accessed and
 updated by functions @('fld') and @('update-fld'), respectively.  Each of
 these four primitive functions has both a logical definition, which is used
 when the prover reasons about the function, and an executable definition,
 which is used in raw Lisp.  In the logic, @('stp') recognizes objects that
 have the requisite fields.  In raw Lisp, there is a ``live stobj'', which is
 an array object whose fields correspond to those specified by the @(tsee
 defstobj) event, implemented as Lisp arrays.</p>

 <p>Here are the logical definition and the executable definition,
 respectively, that are introduced for the field accessor, @('fld'), introduced
 above.  Notice that since a stobj is represented in raw Lisp using an array,
 the raw Lisp accessor uses a raw Lisp array accessor, @('svref').  (You can
 see all the logical and executable definitions by evaluating the form
 @('(trace$ defstobj-axiomatic-defs defstobj-raw-defs)') before evaluating the
 @(tsee defstobj) form.)</p>

 @({
  ; logical definition
  (defun fld (st)
    (declare (xargs :guard (stp st)
                    :verify-guards t))
    (nth 0 st))

  ; executable (raw Lisp) definition
  (defun fld (st)
    (svref st 0))
 })

 <p>Sophisticated programming with stobjs can provide efficient implementations
 of algorithms, but may require the preservation of a complex invariant.  One
 can, of course, define a function to implement such an invariant after
 introducing the stobj, as follows.</p>

 @({
  ; Introduce a stobj.
  (defstobj st fld1 ... fldk)

  ; Define an invariant on that stobj.
  (defun good-stp (st)
    (declare (xargs :stobjs st))
    ...)

  ; Define some basic functions that update the stobj and preserve the
  ; invariant.
  (defun update-st (... st ...)
    (declare (xargs :stobjs st
                    :guard (and (good-stp st) ...)))
    ...)
  ...

  ; Prove that the invariant is indeed preserved by those basic functions.
  (defthm good-stp-update-st
    (implies (and (good-stp st)
                  ...)
             (good-stp (update-st ... st ...))))
  ...

  ; Implement algorithms built on the basic functions.
  (defun foo (... st ...)
    (declare (xargs :stobjs st
                    :guard (and (good-stp st) ...)))
    ... (update-st ... st ...) ...)

  ; Prove invariance theorems about these algorithms.
  (defthm good-stp-foo
    (implies (and (good-stp st)
                  ...)
             (good-stp (foo ... st ...))))
  ...

  ; Prove other properties of these algorithms.
  (defthm foo-is-correct
    (implies (and (good-stp st)
                  ...)
             (some-property (foo ... st ...))))
  ...
 })

 <p>But there are at least two potential difficulties in using stobjs as
 described above.</p>

 <blockquote><p>1. When @('foo') is executed on concrete data in the ACL2 loop,
 the guard check may be expensive because @('(good-stp st)') is expensive.</p>

 <p>2. Reasoning about @('foo') (using rules like @('foo-is-correct') above)
 involves proving hypotheses of invariance theorems, which may be complicated
 for the user to manage or slow for the theorem prover.</p></blockquote>

 <p>The @('defabsstobj') event offers an opportunity to address these issues.
 It introduces a new stobj, which we call an ``abstract stobj'', which is
 associated with a corresponding ``concrete stobj'' introduced by an earlier
 @(tsee defstobj) event.  The @('defabsstobj') event specifies a logical
 (@(':LOGIC')) and an executable (@(':EXEC')) definition for each primitive
 operation, or ``stobj primitive'', involving that stobj.  As is the case for
 @(tsee defstobj), the logical definition is what ACL2 reasons about, and is
 appropriate to apply to an ACL2 object satisfying the logical definition of
 the recognizer function for the stobj.  The executable definition is applied
 in raw Lisp to a live stobj, which is an array object associated with the
 given stobj name.</p>

 <p>We can picture a sequence of updates to corresponding abstract and concrete
 stobjs as follows.  Initially in this picture, @('st$a0') and @('st$c0') are a
 corresponding abstract and concrete stobj (respectively).  Then an update,
 @('u1'), is applied with @(':LOGIC') and @(':EXEC') functions @('u$a1') and
 @('u$c1'), respectively.  The resulting abstract and concrete stobj,
 @('st$a1') and @('st$c1'), correspond as before.  Then a second update,
 @('u2'), is applied with @(':LOGIC') and @(':EXEC') functions @('u$a2') and
 @('u$c2'), respectively &mdash; again preserving the correspondence.  And so
 on.</p>

 @({
  Abstract               u$a1       u$a2       u$a3
  (:logic)         st$a0  --> st$a1  --> st$a2  -->   ...

                     ^          ^          ^               ^
  Correspondence     |          |          |          ...  |
                     v          v          v               v

                         u$c1       u$c2       u$c3
  Concrete         st$c0  --> st$c1  --> st$c2  -->   ...
  (:exec)
 })

 <p>We conclude this introduction with some remarks about implementation.
 Consider an abstract stobj @('st') with corresponding concrete stobj
 @('st$c').  The live stobjs for @('st') and @('st$c') have the same structure,
 but are distinct arrays.  Indeed, the raw Lisp creator function for @('st$c')
 is called to create a new initial live stobj for @('st').  As we will see
 below, reads and writes in raw Lisp to the live stobj for @('st') are
 ultimately performed using the primitive accessors and updaters defined for
 @('st$c').  One might think of the live stobjs for @('st') and @('st$c') as
 being congruent stobjs (see @(see defstobj)), except that the stobjs
 themselves are not congruent: the stobj primitives introduced for @('st') may
 be applied to @('st') but not arbitrary field updaters of @('st$c'), for
 example.  As one might expect, the @(':EXEC') function for an exported
 function is applied to the live stobj for @('st') in raw Lisp.</p>

 <p><b>EXAMPLE</b></p>

 <p>We present examples, with detailed comments intended to explain abstract
 stobjs, in two community books: @('books/misc/defabsstobj-example-1.lisp') and
 @('books/misc/defabsstobj-example-2.lisp').  In this section we outline the
 first of these.  We suggest that after you finish this @(see documentation)
 topic, you read through those two books.</p>

 <p>Here is the first of two closely related @('defabsstobj') @(see events)
 from the book @('defabsstobj-example-1.lisp'), but in expanded form.  We will
 show the abbreviated form later, which omits most of data in the form that is
 immediately below.  Thus most of the information shown here is default
 information.  We believe that the comments below explain most or all of what
 you need to know in order to start using @('defabsstobj'), and that you will
 learn the remainder when you see error messages.  For example, we do not say
 in the comments below that every @(':LOGIC') and @(':EXEC') function must be
 @(see guard)-verified, but that is indeed a requirement.</p>

 <code>
 (defabsstobj st ; The new abstract stobj is named st.

 ; The concrete stobj corresponding to st is st$c:

   :concrete st$c

 ; The recognizer for the new abstract stobj is stp, which is defined to be
 ; st$ap in the logic, and is executed on the live stobj in raw Lisp using
 ; st$cp.

   :recognizer (stp :logic st$ap :exec st$cp)

 ; The initial stobj is defined as create-st (a function of no arguments),
 ; which is defined logically as create-st$a, though create-st$c is invoked to
 ; create the initial live stobj for st.  The :correspondence and :preserved
 ; keywords refer to proof obligations, discussed below.

   :creator (create-st :logic create-st$a :exec create-st$c
                       :correspondence create-st{correspondence}
                       :preserved create-st{preserved})

 ; Proof obligations are generated that involve a correspondence between the
 ; new abstract stobj and corresponding concrete stobj.  The function
 ; st$corr, which need not be executable (see :DOC defun-nx), takes two
 ; arguments, a concrete stobj and an abstract stobj.  This function symbol is
 ; used in the statements of the proof obligations.

   :corr-fn st$corr

 ; In this example we have four exports.  In each case a new function is
 ; introduced that has the same signature as its :EXEC function, except that
 ; st$c is replaced by st.  The :LOGIC and :EXEC functions are as specified,
 ; and the other keywords refer to proof obligations that we discuss below.

   :exports ((lookup :logic lookup$a
                     :exec mem$ci
                     :correspondence lookup{correspondence}
                     :guard-thm lookup{guard-thm})
             (update :logic update$a
                     :exec update-mem$ci
                     :correspondence update{correspondence}
                     :preserved update{preserved}
                     :guard-thm update{guard-thm})
             (misc :logic misc$a
                   :exec misc$c
                   :correspondence misc{correspondence})
             (update-misc :logic update-misc$a
                          :exec update-misc$c
                          :correspondence update-misc{correspondence}
                          :preserved update-misc{preserved}))
   :doc nil)
 </code>

 <p>Note that all stobj primitives (recognizer, creator, and exported
 functions) are defined in the ACL2 loop in terms of their @(':LOGIC')
 functions and in raw Lisp in terms of their @(':EXEC') functions.  In the ACL2
 loop, a @(tsee defun) form defines a function, while in raw Lisp, a @(tsee
 defmacro) form defines a macro (for efficiency).  We first illustrate how that
 works for the recognizer.  (You can see all the logical and executable
 definitions by evaluating the form @('(trace$ defabsstobj-axiomatic-defs
 defabsstobj-raw-defs)') before evaluating the @(tsee defstobj) form.)</p>

 @({
  ; In the ACL2 loop:
  (defun stp (st)
    (declare (xargs :guard 't))
    (st$ap st))

  ; In raw Lisp:
  (defmacro stp (&rest args) (cons 'st$cp args))
 })

 <p>The definitions are made similarly for exported functions, with @(see
 guard)s derived from their @(':LOGIC') functions as follows.  Consider the
 exported function @('update') in our example.  Its @(':LOGIC') function,
 @('update$a'), has formals @('(k val st$a)') and the following guard.</p>

 @({
  (and (and (integerp k) (<= 0 k) (<= k 49))
       (and (integerp val) (<= 0 val))
       (st$ap st$a)
       (mem$c-entryp val))
 })

 <p>The formals of @('update') are obtained by starting with the formals of its
 @(':EXEC') function, @('update-mem$ci') &mdash; which are @('(i v st$c)')
 &mdash; and replacing the concrete stobj name @('st$c') by the new stobj name
 @('st').  The formals of @('update') are thus @('(i v st)').  The guard for
 @('update') is obtained in two steps.  The first step is to substitute the
 formals of @('update') for the formals of @('update$a') in the guard for
 @('update$a'), to obtain the following.</p>

 @({
  (and (and (integerp i) (<= 0 i) (<= i 49))
       (and (integerp v) (<= 0 v))
       (st$ap st)
       (mem$c-entryp v))
 })

 <p>The second step is to replace, for each new stobj primitive @('p'), the
 @(':LOGIC') function for @('p') by @('p') itself.  The only @(':LOGIC')
 function occurring in the formula just above is @('st$ap'), which is the
 @(':LOGIC') function for @('stp').  The guard for @('update') is thus as
 follows.</p>

 @({
  (and (and (integerp i) (<= 0 i) (<= i 49))
       (and (integerp v) (<= 0 v))
       (stp st)
       (mem$c-entryp v))
 })

 <p>We turn now to the proof obligations, as promised above.  There are three
 types: @(':CORRESPONDENCE'), @(':PRESERVED'), and @(':GUARD-THM').  All
 required lemmas may be printed simply by defining the necessary @(':LOGIC')
 and @(':EXEC') functions and then submitting the @('defabsstobj') event.  (To
 advanced users: also see @(see defabsstobj-missing-events) for a utility that
 returns the required formulas in translated form.)  Although the
 @('defabsstobj') event will fail if the required lemmas have not been proved,
 first it will print the @(tsee defthm) forms that must be admitted in order to
 complete submission of the @('defabsstobj') event.  (Note that although the
 those theorems are stated exactly in the form expected by the system, you are
 welcome to supply whatever @(':')@(tsee rule-classes) you prefer, even though
 the system creates @(':rule-classes nil') by default.)</p>

 <p>The detailed theory explaining the need for these lemmas may be found in a
 comment in ACL2 source file @('other-events.lisp'), in a comment entitled
 ``Essay on the Correctness of Abstract Stobjs''.  Here, we give an informal
 sense of the importance of these lemmas as we present examples of them.
 Fundamental is the notion of evaluation in the logic versus evaluation using
 live stobjs, where one imagines tracking the current value of each abstract
 stobj during each of these two evaluations.</p>

 <p>We start with the @(':CORRESPONDENCE') lemmas.  These guarantee that
 evaluation in the logic agrees with evaluation using live stobjs, in the sense
 that the only difference is between a logical stobj and a live stobj, where
 the two correspond in the sense of the function specified by @(':CORR-FN').
 We start with the @(':CREATOR') function where the statement is quite simple,
 stating that the @(':CORR-FN') holds initially.</p>

 @({
  (defthm create-st{correspondence}
    (st$corr (create-st$c) (create-st$a)))
 })

 <p>For the exported functions, there are essentially two cases.  If an
 exported function returns other than the new abstract stobj, then the theorem
 asserts the equality of the results of applying the @(':LOGIC') and @(':EXEC')
 functions for the exported function.  Hypotheses include the @(':CORR-FN')
 correspondence followed by the @(see guard) for the @(':LOGIC') function,
 which is stated in terms of the formal parameters of the @(':EXEC') function
 except using the abstract stobj (here, @('st')) in place of the concrete stobj
 (here, @('st$c')).  The conclusion uses the @(':EXEC') formals, modified in
 the call of the @(':LOGIC') function (here, @('lookup$a')) to use the abstract
 stobj, as in the hypotheses.</p>

 @({
  (defthm lookup{correspondence}
    (implies (and (st$corr st$c st)
                  (integerp i) (<= 0 i) (<= i 49)
                  (st$ap st))
             (equal (mem$ci i st$c)
                    (lookup$a i st)))
    :rule-classes nil)
 })

 <p>By contrast, if the exported function returns the new abstract stobj, then
 the conclusion uses the correspondence function instead of @('EQUAL'), as in
 the following.</p>

 @({
  (defthm update{correspondence}
    (implies (and (st$corr st$c st)
                  (integerp i) (<= 0 i) (<= i 49)
                  (integerp v) (<= 0 v)
                  (st$ap st)
                  (mem$c-entryp v))
             (st$corr (update-mem$ci i v st$c)
                      (update$a i v st)))
    :rule-classes nil)
 })

 <p>For exported functions that return multiple values, such conclusions are
 conjoined together over the returned values.</p>

 <p>The @(':PRESERVED') lemmas guarantee that updates to the abstract stobj
 preserve its recognizer.  The fact that every exported function has this
 property provides justification for an optimization performed by ACL2 during
 generation of proof obligations for @(see guard) verification, by assuming
 that the recognizer always holds.  The @(':PRESERVED') lemma for the
 @(':CREATOR') shows that the recognizer holds initially.</p>

 @({
  (defthm create-st{preserved}
    (st$ap (create-st$a)))
 })

 <p>Here is a typical such lemma, for the exported function @('update').  Note
 that there is no such lemma for @('lookup'), since @('lookup') does not return
 @('st').</p>

 @({
  (defthm update{preserved}
    (implies (and (integerp i) (<= 0 i) (<= i 49)
                  (integerp v) (<= 0 v)
                  (st$ap st)
                  (mem$c-entryp v))
             (st$ap (update$a i v st))))
 })

 <p>Finally, we consider the @(':GUARD-THM') lemmas.  These serve to guarantee
 that the @(see guard) holds for each call of an @(':EXEC') function.  During
 guard verification, logical definitions are used; in particular, since each
 exported function is defined in the logic as the corresponding call of its
 @(':LOGIC') function, guard verification shows that each call of the
 @(':LOGIC') function for an exported function satisfies that function's guard.
 But why is this true for raw Lisp evaluation using live stobjs, where the
 @(':EXEC') function is called for an exported function?  The @(':GUARD-THM')
 lemmas provide the answer, as they state that if the @(':LOGIC') function's
 guard holds, then the @(':EXEC') function's guard holds.  Here is an example.
 Note that the hypotheses come from the correspondence of the concrete and
 abstract function as guaranteed by the @(':CORR') function, together with the
 guard of the @(':LOGIC') function; and the conclusion comes from the guard of
 the @(':EXEC') function.</p>

 @({
  (defthm lookup{guard-thm}
    (implies (and (st$corr st$c c)
                  (integerp i)
                  (<= 0 i)
                  (<= i 49)
                  (st$ap st))
             (and (integerp i)
                  (<= 0 i)
                  (< i (mem$c-length st$c))))
    :rule-classes nil)
 })

 <p>We conclude this EXAMPLE section by showing a short form for the
 @('defabsstobj') form displayed above.</p>

 @({
  (defabsstobj st
    :exports ((lookup :exec mem$ci)
              (update :exec update-mem$ci)
              misc update-misc))
 })

 <p><b>SUMMARY DOCUMENTATION</b></p>

 <p>The General Form is as shown below, where the order of keywords is
 unimportant.  Duplicate keywords are discouraged; while permitted, only the
 first (leftmost) occurrence of a given keyword is used.  Only the
 @(':exports') keyword is required.</p>

 @({
  (defabsstobj st
    :concrete concrete
    :recognizer recognizer
    :creator creator
    :corr-fn corr-fn
    :congruent-to congruent-to
    :protect-default protect-default
    :exports (e1 ... ek)
    :doc doc)
 })

 <p>The keyword argument @(':EXPORTS') must be supplied, and missing or
 @('nil') keyword arguments have defaults as indicated below.  All arguments
 must satisfy the conditions below.</p>

 <p>Before we describe the arguments, we define a notion of a ``function spec''
 and its ``completion''.  A function spec is either a symbol or else a list of
 the form</p>

 <code>
 (fn @(':kwd1') val1 ... @(':kwdn') valn), </code>

 <p>that is, a symbol followed by a @(tsee keyword-value-listp).  We view the
 case of a symbol, @('s'), as the function spec @('(s)'), with no keywords.
 There must be no duplicate keywords.  In each case that we expect a function
 spec, the context provides a set of valid keywords for that function spec; it
 is an error to provide any other keyword in the function spec.  Each function
 spec is interpreted as its ``completion'', obtained by extending the function
 spec with a default value for each valid keyword as indicated below.  With
 that interpretation, the ``exported function'' of a function spec is its
 @('car'), and that function symbol and each keyword value must be a
 guard-verified function symbol; and moreover, the @(':EXEC') function must not
 include the new abstract stobj name, @('st'), among its formals.</p>

 <p>We are ready to describe the arguments of @('defabsstobj').</p>

 <blockquote><p>@('St') is a symbol, which names the new abstract stobj.</p>

 <p>@('Concrete') is the name of an existing stobj that is not an abstract
 stobj, i.e., was introduced with @(tsee defstobj) (not @(tsee
 defabsstobj)).</p>

 <p>@('Recognizer') is a function spec (for the recognizer function).  The
 valid keywords are @(':LOGIC') and @(':EXEC').  The default for
 @('recognizer') is obtained by adding the suffix @('\"P\"') to @('name').  The
 default value for @(':LOGIC') is formed by adding the suffix @('\"$AP\"') to
 @('recognizer'); for @(':EXEC'), by adding the suffix @('\"$CP\"').  The
 @(':EXEC') function must be the recognizer for the specified @(':CONCRETE')
 stobj.</p>

 <p>@('Creator') is a function spec (for the creator function).  The valid
 keywords are @(':LOGIC') and @(':EXEC').  The default for @('creator') is
 obtained by adding the prefix @('\"CREATE-\"') to @('name').  The default
 value for @(':LOGIC') is formed by adding the suffix @('\"$A\"') to
 @('creator'); for @(':EXEC'), by adding the suffix @('\"$C\"').  The
 @(':CREATOR') function must be the creator for the specified @(':CONCRETE')
 stobj, as ACL2 checks that the @(':CREATOR') function takes no arguments and
 returns the @(':CONCRETE') stobj.</p>

 <p>@('Corr-fn') is a known function symbol that takes two arguments (for the
 correspondence theorems).  The default for @('corr-fn') is obtained by adding
 the suffix @('\"$CORR\"') to @('name').</p>

 <p>@('Congruent-to') should either be @('nil') (the default) or the name of an
 abstract stobj previously introduced (by @(tsee defabsstobj)).  In the latter
 case, the current and previous abstract stobj should have the same concrete
 stobj (not merely congruent concrete stobjs), and their @(':EXPORTS') fields
 should have the same length and also correspond, as follows: the ith export of
 each should have the same @(':LOGIC') and @(':EXEC') symbols.  See @(see
 defstobj) for more about congruent stobjs.  Note that if two names are
 congruent, then they are either both ordinary stobjs or both abstract
 stobjs.</p>

 <p>@('Protect-default') should either be @('nil') (the default) or @('t').  It
 provides the value of keyword @(':PROTECT') for each member of @('exports')
 that does not explicitly specify @(':PROTECT').  See the discussion of
 @('exports') below.</p>

 <p>An important aspect of the @('congruent-to') parameter is that if it is not
 @('nil'), then the checks for lemmas &mdash; @('{CORRESPONDENCE}'),
 @('{GUARD-THM}'), and @('{PRESERVED}') &mdash; are omitted.  Thus, the values
 of keyword @(':CORR-FN'), and the values of keywords @(':CORRESPONDENCE'),
 @(':GUARD-THM'), and @(':PRESERVED') in each export (as we discuss next), are
 irrelevant; they are not inferred and they need not be supplied.</p>

 <p>The value of @(':EXPORTS') is a non-empty true list.  Each @('ei') is a
 function spec (for an exported function).  The valid keywords are @(':LOGIC'),
 @(':EXEC'), @(':CORRESPONDENCE'), and @(':GUARD-THM'), @(':PROTECT'), and also
 @(':PRESERVED') if and only if the specified @(':EXEC') function returns the
 @(':CONCRETE') stobj.  The default values for all of these keywords except
 @(':PROTECT') are obtained by respectively adding the suffix @('\"$A\"')
 @('\"$C\"'), @('\"{CORRESPONDENCE}\"'), @('\"{GUARD-THM}\"'), or
 @('\"{PRESERVED}\"').  For @(':PROTECT'), the default is @('nil') unless the
 @('defabsstobj') event specifies @(':PROTECT-DEFAULT t').</p>

 <p>@('Doc'), if non-@('nil'), is a string that can provide documentation but
 is essentially ignored by ACL2.</p></blockquote>

 <p>Not shown is the keyword, @(':MISSING'); the effect of @(':missing t') is
 to turn the call of @('defabsstobj') into a corresponding call of @(tsee
 defabsstobj-missing-events).</p>

 <p>Note that a @('defabsstobj') event will fail if the required lemmas &mdash;
 that is, those for valid keywords @(':CORRESPONDENCE'), @(':GUARD-THM'), and
 @(':PRESERVED') &mdash; have not been proved, unless proofs are being skipped.
 The exemption when skipping proofs allows the supporting lemmas to be @(tsee
 local) to @(see books) and @(tsee encapsulate) @(see events).  If the @(tsee
 ld) special @(tsee ld-skip-proofsp) is @('t'), then the missing @(see events)
 are printed with a warning before the @('defabsstobj') event is admitted; but
 if @('ld-skip-proofsp') is the symbol @('INCLUDE-BOOK'), then that warning is
 omitted.  (Also see @(see skip-proofs) and see @(see ld-skip-proofsp).)  If
 however proofs are not being skipped, then the @('defabsstobj') event will
 fail after printing the missing events.  Advanced users may wish to see @(see
 defabsstobj-missing-events) for a utility that returns a data structure
 containing the missing lemmas.</p>

 <p>Let @('st') be an abstract stobj with corresponding concrete stobj
 @('st$c').  let @('f') be an exported function for @('st') and let @('f$a')
 and @('f$c') be the corresponding @(':LOGIC') and @(':EXEC') functions,
 respectively.  The formals of @('f') are obtained by taking the formals of
 @('f$c') and replacing @('st$c') by @('st').  The @(see guard) for @('f') is
 derived as follows from the guard of @('f$a').  First, the formals of @('f$a')
 are replaced by the formals of @('f') in the guard of @('f$a'), to obtain a
 term we denote here as @('guard-pre').  Now for each exported function symbol
 @('g') of @('st') with corresponding @(':LOGIC') function @('g$a'), form a
 functional substitution by consing @('g$a') with @('g').  Finally, apply that
 functional substitution to @('guard-pre'); the result is the guard of @('f').
 That guard must satisfy the usual conditions of a guard: thus, it must return
 a single non-@(see stobj) value and satisfy normal syntactic restrictions,
 including single-threadedness in its handling of stobjs.</p>

 <p>@('Remark').  Because of how guards are created for exported functions, and
 in particular because @(':LOGIC') functions are replaced as discussed above, a
 good discipline is to define @(':LOGIC') functions that are not intended for
 general use, but are intended only for use as @(':LOGIC') functions of
 corresponding stobj primitives.  For example, suppose that you use @('length')
 as the @(':LOGIC') function for some stobj primitive, @('f') (as opposed to
 using your own function, say, @('foo-length') or @('foo$a')).  Then every call
 of @('length') will be replaced by @('f') when creating the guard of a stobj
 primitive from the guard of its @(':LOGIC') function.  This might not be what
 you intended if you were using @('length') in that guard simply to compute the
 length of an ordinary list.</p>

 <p>There are a few additional restrictions, as follows.</p>

 <blockquote><p>All exported function names must be new (unless redefinition is
 on; see @(see ld-redefinition-action)), and there must be no duplicates among
 them.</p>

 <p>The @(':CONCRETE') stobj name must be a formal parameter of the @(':EXEC')
 fn of every function spec, except for the @(':CREATOR') function spec.  Also
 the input signatures of the @(':LOGIC') and @(':EXEC') function for a function
 spec must agree, except perhaps at the position of that @(':CONCRETE')
 formal.</p>

 <p>For function specs other than the @(':CREATOR') function spec, the output
 signatures of the @(':LOGIC') and @(':EXEC') functions must have the same
 length and must agree, except perhaps at position @('p_out') of the
 @(':CONCRETE') stobj in the @(':EXEC') function's output.  If @('p_in') is the
 position of the @(':CONCRETE') stobj in the @(':EXEC') function's formals,
 then the @(':LOGIC') function's output at position @('p_out') should match the
 @(':LOGIC') function's formal at position @('p_in').</p>

 <p>The @(':PROTECT') keyword is something that you should ignore unless you
 get an error message about it, pertaining to modifying the concrete stobj
 non-atomically.  In that case, you can eliminate the error by providing
 @(':PROTECT t') in the function spec, or by providing @('defabsstobj') keyword
 argument @(':PROTECT-DEFAULT t') at the top level.  The above explanation is
 probably all you need to know about @(':PROTECT'), but just below is a more
 complete explanation for those who desire it.  Further information is also
 available if you need it; see @(see set-absstobj-debug), and see the example
 uses of these keywords in community book
 @('books/misc/defabsstobj-example-2.lisp').</p></blockquote>

 <p>For those who are interested, here is a more detailed discussion of
 @(':PROTECT') and @(':PROTECT-DEFAULT'), as promised above.  It applies to any
 function spec for an export (hence not to the @(':CREATOR') function spec).
 If the @(':EXEC') function is a stobj primitive, then clearly the following
 property holds: any execution of a call of that function can only update the
 concrete stobj at most once &mdash; i.e., modification of the concrete stobj
 is atomic.  ACL2 can deduce this property not only for stobj primitives but
 for many other functions as well.  However, if ACL2 cannot deduce this
 property, then it will cause an error saying that the @(':EXEC') function
 ``appears capable of modifying the concrete stobj, @('<stobj_name>'),
 non-atomically.''  That message also explains how to eliminate this error:
 provide @(':PROTECT t') for the function spec.  Alternatively, all function
 specs without an explicit @(':PROTECT') keyword can be implicitly supplied
 @(':PROTECT t') by supplying the value @('t') for the @(':PROTECT-DEFAULT')
 keyword parameter of the @('defabsstobj') event.  However, beware that when
 @(':PROTECT') is @('t'), the generated raw Lisp code runs slightly less
 efficiently &mdash; though perhaps with negligible efficiency loss if the
 @(':EXEC') function is not trivial.  Community books
 @('books/misc/defabsstobj-example-3.lisp') and
 @('books/misc/defabsstobj-example-4.lisp') provide related information.</p>

 <p>We conclude with some remarks.</p>

 <p>Unlike @(tsee defstobj), there is no @(':renaming') argument.  Instead, the
 scheme described above provides a flexible way to assign names.  Also unlike
 @(tsee defstobj), there is no @(':inline') or @(':non-memoizable') argument;
 @(':inline') is essentially t, in the sense that stobj primitives are macros
 in raw Lisp; and the @(':non-memoizable') argument is derived implicitly from
 the value of that argument (@('nil') by default) for the corresponding
 concrete stobj.</p>

 <p>Those who use @(see hons-enabled) features, including function
 memoization (see @(see memoize)), may be aware that the memo table for a
 function is flushed whenever it is the case that one of its stobj inputs is
 updated.  In fact, such flushing happens even when a stobj that is congruent
 to one of its stobj inputs is updated.  For that purpose, an abstract stobj is
 considered to be congruent to its corresponding concrete stobj.</p>")

(defxdoc defabsstobj-missing-events
  :parents (events)
  :short "Obtain the @(see events) needed to admit a @(tsee defabsstobj) event"
  :long "<p>We assume familiarity with @(tsee defabsstobj).
 @('Defabsstobj-missing-events') is a macro is for advanced users (who, for
 example, understand the role of the @('translate') and @('untranslate')
 functions), who want programmatic access to the @(tsee defthm) events required
 to admit a specific @('defabsstobj') event.</p>

 <p>This macro has the same syntax as @(tsee defabsstobj) &mdash; to use it,
 just replace a call of @(tsee defabsstobj) by a call of
 @('defabsstobj-missing-events') on the same arguments.  The result is an error
 triple @('(mv erp val state)').  If @('erp') is @('nil'), then @('val') is the
 list of all objects @('(name formula . old-formula)'), where a @(tsee defthm)
 event named @('name') remains to be admitted whose translated formula is
 @('formula'), and where @('old-formula') is @('nil') unless the indicated
 event already exists (hence with a different formula), in which case
 @('old-formula') is the existing translated formula.</p>

 <p>To build a @(tsee defthm) event from the above value, @('val'), we suggest
 evaluating a form like @('(untranslate formula t (w state))').</p>")

(defxdoc defattach
  :parents (events)
  :short "Execute constrained functions using corresponding attached functions"
  :long "<p>This @(see documentation) topic is organized into the following
 sections:</p>

 <p><b>Introductory example.</b><br></br>

 <b>Syntax and semantics of defattach.</b><br></br>

 <b>Three primary uses of defattach.</b><br></br>

 <b>Miscellaneous remarks, with discussion of possible user errors.</b></p>

 <p>Please see @(see encapsulate) if you intend to use @('defattach') but are
 not already familiar with the use of @('encapsulate') to introduce constrained
 functions.  It may also be helpful to see @(see evaluation).</p>

 <p>See community book @('books/misc/defattach-example.lisp') for a small
 example.  it illustrates how @('defattach') may be used to build something
 like ``higher-order'' programs, in which constrained functions may be refined
 to different executable functions.  More uses of @('defattach') may be found
 in the ACL2 source code, specifically, file @('boot-strap-pass-2-a.lisp').</p>

 <p>The argument @(':skip-checks t') enables easy experimentation with
 @('defattach'), by permitting use of @(':')@(tsee program) mode functions and
 the skipping of semantic checks.  Also permitted is @(':skip-checks nil') (the
 default) and @(':skip-checks :cycles'), which turns off only the update of the
 extended ancestor relation (see below) and hence the check for cycles in this
 relation; see below.  We do not make any logical claims when the value of
 @(':skip-checks') is non-@('nil'); indeed, a trust tag is required in this
 case (see @(see defttag)).  Note that the interaction of memoization and
 attachments is not tracked for attachments introduced with a non-@('nil')
 value of @(':skip-checks').  For more discussion of @(':skip-checks t'), see
 @(see defproxy); we do not discuss @(':skip-checks') further, here.</p>

 <p><b>Introductory example.</b></p>

 <p>We begin with a short log illustrating the use of @('defattach').  Notice
 that after evaluating the event @('(defattach f g)'), a call of the
 constrained function @('f') is evaluated by instead calling @('g') on the
 arguments.</p>

 @({
  ACL2 !>(encapsulate
          ((f (x) t :guard (true-listp x)))
          (local (defun f (x) x))
          (defthm f-property
            (implies (consp x) (consp (f x)))))
  [... output omitted ...]
   T
  ACL2 !>(defun g (x)
           (declare (xargs :guard (or (consp x) (null x))))
           (cons 17 (car x)))
  [... output omitted ...]
   G
  ACL2 !>(f '(3 4)) ; undefined function error

  ACL2 Error in TOP-LEVEL:  ACL2 cannot ev the call of undefined function
  F on argument list:

  ((3 4))

  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

  ACL2 !>(defattach f g)
  [... output omitted ...]
   :ATTACHMENTS-RECORDED
  ACL2 !>(f '(3 4)) ; f is evaluated using g
  (17 . 3)
  ACL2 !>(trace$ f g)
   ((F) (G))
  ACL2 !>(f '(3 4)) ; f is evaluated using g
  1> (ACL2_*1*_ACL2::F (3 4))
    2> (ACL2_*1*_ACL2::G (3 4))
      3> (G (3 4))
      <3 (G (17 . 3))
    <2 (ACL2_*1*_ACL2::G (17 . 3))
  <1 (ACL2_*1*_ACL2::F (17 . 3))
  (17 . 3)
  ACL2 !>(defattach f nil) ; unattach f (remove its attachment)
  [... output omitted ...]
   :ATTACHMENTS-RECORDED
  ACL2 !>(f '(3 4)) ; undefined function error once again
  1> (ACL2_*1*_ACL2::F (3 4))

  ACL2 Error in TOP-LEVEL:  ACL2 cannot ev the call of undefined function
  F on argument list:

  ((3 4))

  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

  ACL2 !>
 })

 <p><b>Syntax and semantics of defattach.</b></p>

 <p>The log above shows that the event @('(defattach f g)') allows @('g') to be
 used for evaluating calls of @('f').  From a logical perspective, the
 evaluation takes place in the addition to the current session of an
 ``attachment equation'' axiom (universally quantified over all @('x')) for
 each @('defattach') event:</p>

 @({
  (equal (f x) (g x)) ;;; attachment equation axiom for (defattach f g)
 })

 <p>Below we explain @('defattach') in some detail.  But it is important to
 keep in mind that evaluation with the attachment equations takes place in an
 extension of the logical theory of the session.  ACL2 guarantees that this
 so-called ``evaluation theory'' remains consistent, assuming the absence of
 @(tsee defaxiom) @(see events) from the user.  This guarantee is a consequence
 of a more general guarantee: an ACL2 logical @(see world) exists in which
 (loosely speaking) the attachment equation for @('(defattach f g)'), as
 @('(defun f (...) (g ...))'), takes the place of the original defining event
 for @('f'), for each @('defattach') event.  This more general guarantee holds
 even if there are @(tsee defaxiom) events, though as explained below, no
 function symbol that syntactically supports a @('defaxiom') formula is allowed
 to get an attachment.  A deeper discussion of the logical issues is available
 (but not intended to be read by most users) in a long comment in the ACL2
 source code labeled ``Essay on Defattach.''</p>

 @({
  Example Forms:
  (defattach f g)   ; call g in place of calling constrained function f
  (defattach (f g)) ; same as just above
  (defattach (f g :hints ((\"Goal\" :in-theory (enable foo)))))
                    ; equivalent to first form above, except with hints for the
                    ; proof that the guard of f implies the guard of g
  (defattach (f g :hints ((\"Goal\" :in-theory (enable foo)))
                  :otf-flg t))
                    ; as above, except with an :otf-flg of t for the proof that
                    ; the guard of f implies the guard of g
  (defattach (f g)
             :hints ((\"Goal\" :use my-thm)))
                    ; equivalent to first form above, except with hints for the
                    ; proof that the constraints on f hold for g
  (defattach (f g)
             :hints ((\"Goal\" :use my-thm))
             :otf-flg t)
                    ; as above, except with an :otf-flg of t for the proof that
                    ; the constraints on f hold for g
  (defattach (f g)
             (h j)) ; Attach g to f and attach j to h
  (defattach (f g :attach nil)
             (h j)) ; Same as just above, including the same proof obligations,
                    ; except for one difference: because of :attach nil, calls
                    ; of f will not be evaluated, i.e., there will be no
                    ; executable attachment of g to f
  (defattach (f nil)
             (h j)) ; Attach j to h and unattach f
  (defattach (f g :hints ((\"Goal\" :in-theory (enable foo))))
             (h j :hints ((\"Goal\" :in-theory (enable bar))))
             :hints ((\"Goal\" :use my-thm)))
                    ; Attach g to f and attach j to h, with hints:
                    ; - For proving that the guard of f implies the guard of g,
                    ;   enable foo;
                    ; - For proving that the guard of h implies the guard of j,
                    ;   enable bar; and
                    ; - For proving that the constraints on f and h hold for
                    ;   g and j (respectively), use theorem my-thm.

  (defattach f nil)   ; remove the attachment of f, if any (e.g., g above)
  (defattach (f nil)) ; same as just above

  General Forms:
  (defattach f g)   ; single attach or, if g is nil, unattach
  (defattach (f1 g1 :kwd val ...)
             ...
             (fk gk :kwd' val' ...)
             :kwd'' val'' ...)
 })

 <p>where each indicated keyword-value pair is optional and each keyword is one
 of @(':ATTACH'), @(':HINTS'), @(':OTF-FLG'), or @(':INSTRUCTIONS').  The value
 of each @(':ATTACH') keyword is either @('t') or @('nil'), with default @('t')
 except that the value of @(':ATTACH') at the ``top level,'' after each entry
 @('(fi gi ...)'), is the default for each @(':ATTACH') keyword supplied in
 such an entry.  We discuss the @(':ATTACH') keyword later in this @(see
 documentation) topic.  The associated values for the other keywords have the
 usual meanings for the proof obligations described below: the guard proof
 obligation for keywords within each @('(fi gi ...)') entry, and the constraint
 proof obligation for keywords at the top level.  No keyword may occur twice in
 the same context, i.e., within the same @('(fi gi ...)') entry or at the top
 level; and @(':INSTRUCTIONS') may not occur in the same context with
 @(':HINTS') or @(':OTF-FLG').</p>

 <p>The first General Form above is simply an abbreviation for the form
 @('(defattach (f g))'), which is an instance of the second General Form above.
 For the second General Form we say that @('gi') is ``attached to'' @('fi') (by
 the @('defattach') event) if @('gi') is not @('nil'), and otherwise we say
 that @('fi') is ``unattached'' (by the @('defattach') event).  It is also
 convenient to refer to @('<fi,gi>') as an ``attachment pair'' (of the event)
 if @('gi') is not @('nil').  We may refer to the set of @('fi') as the
 ``attachment nest'' of each @('fi').</p>

 <p>We start with a brief introduction to the first General Form in the case
 that @('g') is not @('nil').  This form arranges that during evaluation, with
 exceptions noted below, every call of the constrained function symbol @('f')
 will in essence be replaced by a call of the function symbol @('g') on the
 same arguments.  We may then refer to @('g') as the ``attachment of'' @('f'),
 or say that ``@('g') is attached to @('f').''  Notable exceptions, where we do
 not use attachments during evaluation, are for macroexpansion, evaluation of
 @(tsee defconst) and @(tsee defpkg) terms, evaluation during @(tsee table)
 events, some @(see stobj) operations including all <see topic='@(url
 STOBJ)'>updates</see>, and especially evaluation of ground terms (terms
 without free variables) during proofs.  However, even for these cases we allow
 the use of attachments in the first argument of @(tsee prog2$) and, more
 generally, the next-to-last (i.e., second) argument of @(tsee return-last)
 when its first argument is not of the form @(''m') for some macro, @('m').</p>

 <p>To see why attachments are disallowed during evaluation of ground terms
 during proofs (except for the @(tsee prog2$) and @(tsee return-last) cases
 mentioned above), consider the following example.</p>

 @({
  (defstub f (x) t)
  (defun g (x) (+ 3 x))
  (defattach f g)
 })

 <p>If the form @('(f 2)') is submitted at the ACL2 prompt, the result will be
 @('5') because the attachment @('g') of @('f') is called on the argument,
 @('2').  However, during a proof the term @('(f 2)') will not be simplified to
 @('5'), since that would be unsound, as there are no axioms about @('f') that
 would justify such a simplification.</p>

 <p>For the case that @('g') is @('nil') in the first General Form above, the
 result is the removal of the existing attachment to @('f'), if any.  After
 this removal, calls of @('f') will once again cause errors saying that ``ACL2
 cannot ev the call of undefined function @('f') ...''.  In this case not only
 is the previous attachment to @('f') removed; moreover, for every function
 symbol @('f'') in the attachment nest of @('f') in the @('defattach') event
 that introduced the existing attachment to @('f'), then @('f'') is unattached.
 (An example near the end of this @(see documentation) topic shows why this
 unattachment needs to be done.) Such removal takes place before the current
 @('defattach') is processed, but is restored if the new event fails to be
 admitted.</p>

 <p>We focus henceforth on the second General Form.  There must be at least one
 attachment, i.e., @('i') must be at least 1.  All keywords are optional; their
 role is described below.  The @('fi') must be distinct constrained function
 symbols, that is, function symbols all introduced in @(see signature)s of
 @(tsee encapsulate) @(see events) (or macros such as @(tsee defstub) that
 generate @(tsee encapsulate) events).  Each non-@('nil') @('gi') is a
 @(':')@(tsee logic)-mode function symbol that has had its guards verified,
 with the same @(see signature) as @('fi') (though formal parameters for
 @('fi') and @('gi') may have different names).  (Note: The macro
 @('defattach!'), defined in community book @('books/misc/defattach-bang'),
 avoids this restriction.)  This event generates proof obligations and an
 ordering check, both described below.  The effect of this event is first to
 remove any existing attachments for all the function symbols @('fi'), as
 described above for the first General Form, and then to attach each @('gi') to
 @('fi').</p>

 <p>Proof obligations must be checked before making attachments.  For this
 discussion we assume that each @('gi') is non-@('nil') (otherwise first remove
 all attachment pairs @('<fi,gi>') for which @('gi') is nil).  Let @('s') be
 the functional substitution mapping each @('fi') to @('gi').  For any term
 @('u'), we write @('u\\s') for the result of applying @('s') to @('u'); that
 is, @('u\\s') is the ``functional instance'' obtained by replacing each
 @('fi') by @('gi') in @('u').  Let @('G_fi') and @('G_gi') be the guards of
 @('fi') and @('gi'), respectively.  Let @('G_fi'') be the result of replacing
 each formal of @('fi') by the corresponding formal of @('gi') in @('G_fi').
 ACL2 first proves, for each @('i') (in order), the formula @('(implies G_fi'
 G_gi)\\s').  If this sequence of proofs succeeds, then the remaining formula
 to prove is the functional instance @('C\\s') of the conjunction @('C') of the
 constraints on the symbols @('fi'); see @(see constraint).  This last proof
 obligation is thus similar to the one generated by functional instantiation
 (see @(see constraint)).  As with functional instantiation, ACL2 stores the
 fact that such proofs have been done so that they are avoided in future events
 (see @(see lemma-instance)).  Thus, you will likely avoid some proofs with the
 sequence</p>

 @({
  (defattach f g)
  (defattach f nil)
  (defattach f g)
  (defattach f nil)
  ...
 })

 <p>rather than the sequence:</p>

 @({
  (defattach f g)
  :u
  (defattach f g)
  :u
  ...
 })

 <p>It remains to describe an ordering check.  We begin with the following
 motivating example.</p>

 @({
  (defstub f (x) t) ; constrained function with no constraints
  (defun g (x) (declare (xargs :guard t)) (not (f x)))
  (defattach f g) ; ILLEGAL!
 })

 <p>Were the above @('defattach') event to succeed, the evaluation theory
 (discussed above) would be inconsistent: @('(f x)') equals @('(g x)') by the
 new attachment equation, which in turn equals @('(not (f x))') by definition
 of @('g').  The evaluation would therefore be meaningless.  Also, from a
 practical perspective, there would be an infinite loop resulting from any call
 of @('f').</p>

 <p>We consider a function symbol @('g') to be an ``extended immediate ancestor
 of'' a function symbol @('f') if either of the following two criteria is met:
 (a) @('g') occurs in the formula that introduces @('f') (i.e., definition body
 or constraint) and @('g') is introduced by an event different from (earlier
 than) the event introducing @('f'); or (b) @('g') is attached to @('f').  For
 a proposed @('defattach') event, we check that this relation has no cycles,
 where for condition (b) we include all attachment pairs that would result,
 including those remaining from earlier @('defattach') events.</p>

 <p>Of course, a special case is that no function symbol may be attached to
 itself.  Similarly, no function symbol may be attached to any of its
 ``siblings'' &mdash; function symbols introduced by the same event &mdash; as
 siblings are considered equivalent for purposes of the acyclicity check.</p>

 <p><b>Three primary uses of defattach.</b><br></br></p>

 <p>We anticipate three uses of @('defattach'):</p>

 <p>(1) Constrained function execution</p>

 <p>(2) Sound modification of the ACL2 system</p>

 <p>(3) Program refinement</p>

 <p>We discuss these in turn.</p>

 <p>(1) The example at the beginning of this @(see documentation) illustrates
 constrained function execution.</p>

 <p>(2) ACL2 is written essentially in itself.  Thus, there is an opportunity
 to attaching to system functions.  For example, encapsulated function
 @('too-many-ifs-post-rewrite'), in the ACL2 source code, receives an
 attachment of @('too-many-ifs-post-rewrite-builtin'), which implements a
 heuristic used in the rewriter.  To find all such examples, search the source
 code for the string `-builtin'.</p>

 <p>Over time, we expect to continue replacing ACL2 source code in a similar
 manner.  We invite the ACL2 community to assist in this ``open architecture''
 enterprise; feel free to email the ACL2 implementors if you are interested in
 such activity.</p>

 <p>(3) Recall that for an attachment pair @('<f,g>'), a proof obligation is
 (speaking informally) that @('g') satisfies the constraint on @('f').  Yet
 more informally speaking, @('g') is ``more defined'' than @('f'); we can think
 of @('g') as ``refining'' @('f').  With these informal notions as motivation,
 we can view defattach as providing refinement through the following formal
 observation: the evaluation theory extends the theory of the ACL2 session,
 specifically by the addition of all attachment equations.  For the
 logic-inclined, it may be useful to think model-theoretically: The class of
 models of the evaluation theory is non-empty but is a subset of the class of
 models of the current session theory.</p>

 <p><b>Miscellaneous remarks, with discussion of possible user errors.</b></p>

 <p>We conclude with remarks on some details.</p>

 <p>A @('defattach') event is never redundant (see @(see redundant-events)); in
 that sense it is analogous to @(tsee in-theory).</p>

 <p>As mentioned above, the use of attachments is disabled for evaluation of
 ground terms during proofs.  However, attachments can be used on code during
 the proof process, essentially when the ``program refinement'' is on theorem
 prover code rather than on functions we are reasoning about.  The attachment
 to @('too-many-ifs-post-rewrite') described above provides one example of such
 attachments.  Meta functions and clause-processor functions can also have
 attachments, with the restriction that no common ancestor with the evaluator
 can have an attachment; see @(see evaluator-restrictions).</p>

 <p>For an attachment pair @('<f,g>'), evaluation of @('f') never consults the
 @(see guard) of @('f').  Rather, control passes to @('g'), whose guard is
 checked if necessary.  The proof obligation related to guards, as described
 above, guarantees that any legal call of @('f') is also a legal call of
 @('g').  Thus for guard-verified code that results in calls of @('f') in raw
 Lisp, it is sound to replace these calls with corresponding calls of
 @('g').</p>

 <p>@('Defattach') events are illegal inside any @(tsee encapsulate) event with
 a non-empty @(see signature) unless they are @(see local) to the @(tsee
 encapsulate).</p>

 <p>We next discuss a restriction based on a notion of a function symbol
 syntactically supporting an event.  Function symbol @('f') is <i>ancestral</i>
 in event @('E') if either @('f') occurs in @('E'), or (recursively) @('f')
 occurs in an event @('E'') that introduces some function symbol @('g') that is
 ancestral in @('E').  We require that no function symbol ancestral in the
 formula of a @(tsee defaxiom) event may have an attachment.  Theoretical
 reasons are discussed in comments in the ACL2 source code, but here we give a
 little example showing the need for some such restriction: without it, we show
 how to prove @('nil')!</p>

 @({
  (defn g1 () 1)
  (defn g2 () 2)
  (defstub f1 () t)
  (defstub f2 () t)
  (defund p (x)
    (declare (ignore x))
    t)
  (defevaluator evl evl-list
    ((p x)))
  (defaxiom f1-is-f2
    (equal (f1) (f2)))
  (defun meta-fn (x)
    (cond ((equal (f1) (f2))
           x)
          (t *nil*)))
  (defthm bad-meta-rule
    (equal (evl x a)
           (evl (meta-fn x) a))
    :rule-classes ((:meta :trigger-fns (p))))
  (defattach f1 g1)
  (defattach f2 g2)
  (defthm contradiction
    nil
    :hints ((\"Goal\" :use ((:instance (:theorem (not (p x)))
                                     (x t)))))
    :rule-classes nil)
 })

 <p>To see all attachments: @('(all-attachments (w state))').  However, note
 that attachments introduced with a non-@('nil') value of @(':skip-checks')
 will be omitted from this list.  To obtain the attachment to a function symbol
 @('FN'), without the above restriction and with value @('nil') if there is no
 attachment to @('FN'): @('(cdr (attachment-pair 'FN (w state)))').</p>

 <p>Next we discuss the @(':ATTACH') keyword.  There is rarely if ever a reason
 to specify @(':ATTACH T'), but the following (admittedly contrived) example
 shows why it may be necessary to specify @(':ATTACH NIL').  First we introduce
 three new function symbols.</p>

 @({
    (defstub f (x) t)

    (defun g (x)
      (f x))

    (encapsulate ((h (x) t))
      (local (defun h (x) (g x)))
      (defthm h-prop
        (equal (h x) (g x))))
 })

 <p>Now suppose we want to attach the function @(tsee acl2-numberp) to both
 @('f') and @('h').</p>

 @({
    (defattach (f acl2-numberp) (h acl2-numberp))
 })

 <p>Such an attempt fails, because the following constraint is generated but is
 not a theorem: @('(EQUAL (ACL2-NUMBERP X) (G X))').  Clearly we also need to
 attach to @('g') as well.</p>

 @({
    (defattach (f acl2-numberp) (h acl2-numberp) (g acl2-numberp))
 })

 <p>But this fails for a different reason, as explained by the error
 message:</p>

 @({
    ACL2 Error in ( DEFATTACH (F ACL2-NUMBERP) ...):  It is illegal to
    attach to function symbol G, because it was introduced with DEFUN.
    See :DOC defattach.
 })

 <p>That is: logically, we need to attach @('acl2-numberp') to @('g'), but we
 cannot actually attach to @('g') because it was not introduced with @(tsee
 encapsulate) (it was introduced with @(tsee defun)).  So we specify @(':ATTACH
 NIL') for the attachment to @('g'), saying that no actual attachment should be
 made to the code for @('g'), even though for logical purposes we should
 consider that @('g') has been given the indicated attachment.</p>

 @({
    (defattach (f acl2-numberp) (h acl2-numberp) (g acl2-numberp :attach nil))
 })

 <p>Finally, we can check that @('f'), @('g'), and @('h') execute as
 expected.</p>

 @({
      ACL2 !>(assert-event (and (f 3)
                         (not (f t))
                         (g 3)
                         (not (g t))
                         (h 3)
                         (not (h t))))
       :PASSED
      ACL2 !>
 })

 <p>We conclude with an example promised above, showing why it is necessary in
 general to unattach all function symbols in an existing attachment nest when
 unattaching any one of those function symbols.  Consider the following
 example.</p>

 @({
  (defstub f1 () t)
  (encapsulate ((f2 () t))
    (local (defun f2 () (f1)))
    (defthm f2=f1 (equal (f2) (f1))))
  (encapsulate ((f3 () t))
    (local (defun f3 () (f1)))
    (defthm f3=f1 (equal (f3) (f1))))
  (defun four () (declare (xargs :guard t)) 4)
  (defun five () (declare (xargs :guard t)) 5)
  (defattach (f1 four) (f2 four))
  (defattach (f1 five) (f3 five))
 })

 <p>The second @('defattach') erases the existing attachment pair
 @('<f1,four>') before installing the new attachment pairs @('<f1,five>') and
 @('<f3,five>').  After the second defattach, both @('(f1)') and @('(f3)')
 evaluate to 5.  Now suppose that the attachment pair @('<f2,four>') were not
 erased.  Then we would have @('(f1)') evaluating to 5 and @('(f2)') evaluating
 to 4, contradicting the constraint @('f2=f1').  The evaluation theory would
 thus be inconsistent, and at a more concrete level, the user might well be
 surprised by evaluation results if the code were written with the assumption
 specified in the constraint @('f2=f1').</p>")

(defxdoc default
  :parents (arrays acl2-built-ins)
  :short "Return the @(':default') from the @(see header) of a 1- or
  2-dimensional array"
  :long "@({
  Example Form:
  (default 'delta1 a)

  General Form:
  (default name alist)
 })

 <p>where @('name') is an arbitrary object and @('alist') is a 1- or
 2-dimensional array.  This function returns the contents of the @(':default')
 field of the @(see header) of @('alist').  When @(tsee aref1) or @(tsee aref2)
 is used to obtain a value for an index (or index pair) not bound in
 @('alist'), the default value is returned instead.  Thus, the array @('alist')
 may be thought of as having been initialized with the default value.
 @('default') operates in virtually constant time if @('alist') is the semantic
 value of @('name').  See @(see arrays).</p>

 @(def default)")

(defxdoc default-backchain-limit
  :parents (rule-classes)
  :short "Specifying the backchain limit for a rule"
  :long "<p>See @(see backchain-limit).</p>

 <p>The initial value is @('(nil nil)').  To inspect the current value (as
 explained elsewhere; see @(see backchain-limit)):</p>

 @({
  (default-backchain-limit wrld :ts) ; for type-set reasoning
  (default-backchain-limit wrld :rewrite) ; for rewriting
 })")

(defxdoc default-defun-mode
  :parents (miscellaneous)
  :short "The default @(see defun-mode) of @(tsee defun)'d functions"
  :long "<p>When a @(tsee defun) is processed and no @(':mode') @('xarg') is
 supplied, the function @('default-defun-mode') is used.  To find the default
 @(see defun-mode) of the current ACL2 @(see world), type
 @('(default-defun-mode (w state))').  See @(see defun-mode) for a discussion
 of @(see defun-mode)s.  To change the default @(see defun-mode) of the ACL2
 @(see world), type one of the keywords @(':')@(tsee program) or @(':')@(tsee
 logic).</p>

 <p>The default ACL2 @(see prompt) displays the current default @(see
 defun-mode) by showing the character @('p') for @(':')@(tsee program) mode,
 and omitting it for @(':')@(tsee logic) mode; see @(see default-print-prompt).
 The default @(see defun-mode) may be changed using the keyword @(see command)s
 @(':')@(tsee program) and @(':')@(tsee logic), which are equivalent to the
 @(see command)s @('(program)') and @('(logic)').  Each of these names is
 documented separately: see @(see program) and see @(see logic).  The default
 @(see defun-mode) is stored in the @(see table) @(tsee acl2-defaults-table)
 and hence may also be changed by a @(tsee table) @(see command).  See @(see
 table) and also see @(see acl2-defaults-table).  Both mode-changing @(see
 command)s are @(see events).</p>

 <p>While @(see events) that change the default @(see defun-mode) are permitted
 within an @(tsee encapsulate) or the text of a book, their effects are @(tsee
 local) in scope to the duration of the encapsulation or inclusion.  For
 example, if the default @(see defun-mode) is @(':')@(tsee logic) and a book is
 included that contains the event @('(program)'), then subsequent @(see events)
 within the book are processed with the default @(see defun-mode) @(':')@(tsee
 program); but when the @(tsee include-book) event completes, the default @(see
 defun-mode) will still be @(':')@(tsee logic).  @(see Command)s that change
 the default @(see defun-mode) are not permitted inside @(tsee local)
 forms.</p>")

(defxdoc default-hints
  :parents (hints)
  :short "A list of hints added to every proof attempt"
  :long "@({
  Examples:
  ACL2 !>(default-hints (w state))
  ((computed-hint-1 clause)
   (computed-hint-2 clause stable-under-simplificationp))
 })

 <p>The value returned by this function is added to the right of the
 @(':')@(tsee hints) argument of every @(tsee defthm) and @(tsee thm) command,
 and to hints provided to @(tsee defun)s as well (@(':hints'),
 @(':guard-hints'), and (for ACL2(r)) @(':std-hints')).</p>

 <p>See @(see set-default-hints) for a more general discussion.  Advanced users
 only: see @(see override-hints) for an advanced variant of default hints that
 are not superseded by @(':')@(tsee hints) arguments.</p>")

(defxdoc default-hints-table
  :parents (default-hints)
  :short "A @(see table) used to provide @(see hints) for proofs"
  :long "<p>Please see @(see set-default-hints), see @(see add-default-hints),
 and see @(see remove-default-hints) for how to use this table.  For
 completeness, we mention here that under the hood, these events all update the
 @('default-hints-table') by updating its key, @('t'), for example as
 follows.</p>

 @({
  (table default-hints-table t
         '((computed-hint-1 clause)
           (computed-hint-2 clause
                            stable-under-simplificationp)))
 })

 <p>The use of default hints is explained elsewhere; see @(see
 set-default-hints).</p>

 <p>Advanced users only: see @(see override-hints) for an advanced variant of
 default hints.</p>")

(defxdoc default-print-prompt
  :parents (ld)
  :short "The default @(see prompt) printed by @(tsee ld)"
  :long "@({
  Example prompt:
  ACL2 p!s>
 })

 <p>The @(see prompt) printed by ACL2 displays the current package, followed by
 a space, followed by zero or more of the three @(see characters) as specified
 below, followed by the character @(tsee >) printed one or more times,
 reflecting the number of recursive calls of @(tsee ld).  The three @(see
 characters) in the middle are as follows:</p>

 @({
  p     ; when (default-defun-mode (w state)) is :program
  !     ; when guard checking is on
  s     ; when (ld-skip-proofsp state) is t
 })

 <p>See @(see default-defun-mode), see @(see set-guard-checking), and see @(see
 ld-skip-proofsp).</p>

 <p>Also see @(see ld-prompt) to see how to install your own @(see prompt).</p>

 <p>Here are some examples with @('ld-skip-proofsp nil').</p>

 @({
  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
 })

 <p>Here are some examples with @(tsee default-defun-mode) of @(':')@(tsee
 logic).</p>

 @({
  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
 })

 <p>Finally, here is the prompt in raw mode (see @(see set-raw-mode)),
 regardless of the settings above:</p>

 @({
  ACL2 P>
 })")

(defxdoc default-ruler-extenders
  :parents (rulers)
  :short "The default @(see ruler-extenders) for @(tsee defun)'d functions"
  :long "<p>When a @(tsee defun) is processed and no @(':ruler-extenders')
 @('xarg') is supplied, the function @('default-ruler-extenders') is used to
 obtain the current ruler-extenders; see @(see rulers).  To find the default
 ruler-extenders of the current ACL2 @(see world), type
 @('(default-ruler-extenders (w state))').</p>

 <p>While @(see events) that change the default ruler-extenders are permitted
 within an @(tsee encapsulate) or the text of a book, their effects are @(tsee
 local) in scope to the duration of the encapsulation or inclusion.  See @(see
 default-defun-mode) for an analogous discussion for defun-modes.</p>")

(defxdoc default-total-parallelism-work-limit
  :parents (parallel-proof)
  :short "For ACL2(p): returns the default value for global
  @('total-parallelism-work-limit')"
  :long "<p>See @(see set-total-parallelism-work-limit).</p>")

(defxdoc defaxiom
  :parents (events)
  :short "Add an axiom"
  :long "<p>WARNING: We strongly recommend that you not add axioms.  If at all
 possible you should use @(tsee defun) or @(tsee mutual-recursion) to define
 new concepts recursively or use @(tsee encapsulate) to constrain them
 constructively.  If your goal is to defer a proof by using a top-down style,
 consider using @(tsee skip-proofs); see the discussion on ``Top-Down Proof''
 in Section B.1.2 of ``Computer-Aided Reasoning: An Approach.''  Adding new
 axioms frequently renders the logic inconsistent.</p>

 @({
  Example:
  (defaxiom sbar (equal t nil)
            :rule-classes nil)

  General Form:
  (defaxiom name term
           :rule-classes rule-classes)
 })

 <p>where @('name') is a new symbolic name (see @(see name)), @('term') is a
 term intended to be a new axiom, and @('rule-classes') is a legal value for
 @(':rule-classes') (see @(see rule-classes)).  The keyword argument is
 optional.  If @(':')@(tsee rule-classes) is not supplied, the list
 @('(:rewrite)') is used; if you wish the axiom to generate no rules, specify
 @(':')@(tsee rule-classes) @('nil').</p>")

(defxdoc defchoose
  :parents (events)
  :short "Define a Skolem (witnessing) function"
  :long "@({
  Examples:
  (defchoose choose-x-for-p1-and-p2 (x) (y z)
    (and (p1 x y z)
         (p2 x y z)))

  ; Axiom added by the event above:
  (IMPLIES (AND (P1 X Y Z) (P2 X Y Z))
           (LET ((X (CHOOSE-X-FOR-P1-AND-P2 Y Z)))
                (AND (P1 X Y Z) (P2 X Y Z))))

  (defchoose choose-x-for-p1-and-p2 x (y z) ; equivalent to the above
    (and (p1 x y z)
         (p2 x y z)))

  ; The following is as above, but strengthens the axiom added to pick a sort
  ; of canonical witness, as described below.
  (defchoose choose-x-for-p1-and-p2 x (y z)
    (and (p1 x y z)
         (p2 x y z))
    :strengthen t)

  (defchoose choose-x-and-y-for-p1-and-p2 (x y) (z)
    (and (p1 x y z)
         (p2 x y z)))

  General Form:
  (defchoose fn
             (bound-var1 ... bound-varn)
             (free-var1 ... free-vark)
             body
             :strengthen b),
 })

 <p>where @('fn') is the symbol you wish to define and is a new symbolic name
 (see @(see name)), @('(bound-var1 ... bound-varn)') is a list of distinct
 `bound' variables (see below), @('(free-var1 ... free-vark)') is the list of
 formal parameters of @('fn') and is disjoint from the bound variables, and
 @('body') is a term.  The use of @('lambda-list') keywords (such as
 @('&optional')) is not allowed.  The @(':strengthen') keyword argument is
 optional; if supplied, it must be @('t') or @('nil').</p>

 <p>The system treats @('fn') very much as though it were declared in the @(see
 signature) of an @(tsee encapsulate) event, with a single axiom exported as
 described below.  If you supply a @(':use') hint (see @(see hints)), @(':use
 fn'), it will refer to that axiom.  No rule (of class @(':')@(tsee rewrite) or
 otherwise; see @(see rule-classes)) is created for @('fn').</p>

 <p>@('Defchoose') is only executed in @(see defun-mode) @(':')@(tsee logic);
 see @(see defun-mode).  Also see @(see defun-sk).</p>

 <p>In the most common case, where there is only one bound variable, it is
 permissible to omit the enclosing parentheses on that variable.  The effect is
 the same whether or not those parentheses are omitted.  We describe this case
 first, where there is only one bound variable, and then address the other
 case.  Both cases are discussed assuming @(':strengthen') is @('nil'), which
 is the default.  We deal with the case @(':strengthen t') at the end.</p>

 <p>The effect of the form</p>

 @({
  (defchoose fn bound-var (free-var1 ... free-vark)
    body)
 })

 <p>is to introduce a new function symbol, @('fn'), with formal parameters
 @('(free-var1 ... free-vark)').  Now consider the following axiom, which
 states that @('fn') picks a value of @('bound-var') so that the body will be
 true, if such a value exists:</p>

 @({
  (1)   (implies body
                 (let ((bound-var (fn free-var1 ... free-vark)))
                   body))
 })

 <p>This axiom is ``clearly conservative'' under the conditions expressed
 above: the function @('fn') simply picks out a ``witnessing'' value of
 @('bound-var') if there is one.  For a rigorous statement and proof of this
 conservativity claim, see @(see conservativity-of-defchoose).</p>

 <p>Next consider the case that there is more than one bound variable, i.e.,
 there is more than one bound-var in the following.</p>

 @({
  (defchoose fn
             (bound-var1 ... bound-varn)
             (free-var1 ... free-vark)
             body)
 })

 <p>Then @('fn') returns a multiple value with @('n') components, and formula
 (1) above is expressed using @(tsee mv-let) as follows:</p>

 @({
  (implies body
           (mv-let (bound-var1 ... bound-varn)
                   (fn free-var1 ... free-vark)
                   body))
 })

 <p>We now discuss the case that @(':strengthen t') is supplied.  For
 simplicity we return to our simplest case, with @('defchoose') applied to
 function @('fn'), a single free variable @('y'), and a single bound variable
 @('bound-var').  The idea is that if we pick the ``smallest'' witnessing
 @('bound-var') for two different free variables @('y') and @('y1'), then
 either those two witnesses are the same, or else one is less than the other,
 in which case the smaller one is a witness for its free variable but not for
 the other.  (See comments in source function @('defchoose-constraint-extra')
 for more details.)  Below, @('body1') is the result of replacing @('y') by
 @('y1') in @('body').</p>

 @({
  (2)   (or (equal (fn y) (fn y1))
            (let ((bound-var (fn y)))
              (and body
                   (not body1)))
            (let ((bound-var (fn y1)))
              (and body1
                   (not body))))
 })

 <p>An important application of this additional axiom is to be able to define a
 ``fixing'' function that picks a canonical representative of each equivalence
 class, for a given equivalence relation.  The following events illustrate this
 point.</p>

 @({
  (encapsulate
   ((equiv (x y) t))
   (local (defun equiv (x y) (equal x y)))
   (defequiv equiv))

  (defchoose efix (x) (y)
    (equiv x y)
    :strengthen t)

  (defthm equiv-implies-equal-efix-1
    (implies (equiv y y1)
             (equal (efix y) (efix y1)))
    :hints ((\"Goal\" :use efix))
    :rule-classes (:congruence))

  (defthm efix-fixes
    (equiv (efix x) x)
    :hints ((\"Goal\" :use ((:instance efix (y x))))))
 })

 <p>If there is more than one bound variable, then (2) is modified in complete
 analogy to (1) to use @(tsee mv-let) in place of @(tsee let).</p>

 <p>Comment for logicians: As we point out in the documentation for @(tsee
 defun-sk), @('defchoose') is ``appropriate,'' by which we mean that it is
 conservative, even in the presence of @('epsilon-0') induction.  For a proof,
 See @(see conservativity-of-defchoose).</p>")

(defxdoc defcong
  :parents (events)
  :short "Prove @(see congruence) rule"
  :long "<p>@('Defcong') is used to prove that one @(see equivalence) relation
 preserves another in a given argument position of a given function.</p>
 @({
 Example:
 (defcong set-equal iff (memb x y) 2)

 is an abbreviation for

 (defthm set-equal-implies-iff-memb-2
   (implies (set-equal y y-equiv)
            (iff (memb x y) (memb x y-equiv)))
   :rule-classes (:congruence))
 })

 <p>See @(see congruence) and also see @(see equivalence).</p>

 @({
  General Form:
  (defcong equiv1 equiv2 term k
    :rule-classes rule-classes
    :instructions instructions
    :hints hints
    :otf-flg otf-flg
    :event-name event-name
    :doc doc)
 })

 <p>where @('equiv1') and @('equiv2') are known @(see equivalence) relations;
 @('term') is a call of a function @('fn'), other than @('if'), on the correct
 number of distinct variable arguments, @('(fn x1 ... xn)'); @('k') is a
 positive integer less than or equal to the arity of @('fn'); and other
 arguments are as specified in the documentation for @(tsee defthm).  The
 @('defcong') macro expands into a call of @(tsee defthm).  The name of the
 @(tsee defthm) event is @('equiv1-implies-equiv2-fn-k') unless an
 @(':event-name') keyword argument is supplied for the name.  The term of the
 theorem is</p>

 @({
  (implies (equiv1 xk yk)
           (equiv2 (fn x1... xk ...xn)
                   (fn x1... yk ...xn))).
 })

 <p>The rule-class @(':')@(tsee congruence) is added to the @(tsee
 rule-classes) specified, if it is not already there.  All other arguments to
 the generated @(tsee defthm) form are as specified by the keyword arguments
 above.</p>

 <p>NOTE: In normal usage, @('defcong') can only create classic @(see
 congruence) rules, not @(see patterned-congruence) rules.  However, if @('fn')
 is a macro, it's possible for a patterned congruence rule to be generated,
 depending on what @('term') expands to.</p>

 <p>For example, the following produces a shallow patterned congruence
 rule:</p>

 @({
 (defun f (x y) (and x y))
 (defmacro g (x) `(f ,x t))
 (defcong iff equal (g x) 1)
 })")

(defxdoc defconst
  :parents (events programming)
  :short "Define a constant"
  :long "@({
  Examples:
  (defconst *digits* '(0 1 2 3 4 5 6 7 8 9))
  (defconst *n-digits* (the unsigned-byte (length *digits*)))

  General Form:
  (defconst name term doc-string)
 })

 <p>where @('name') is a symbol beginning and ending with the character @('*'),
 @('term') is a variable-free term that is evaluated to determine the value of
 the constant, and @('doc-string'), if non-@('nil'), is an optional string that
 can provide documentation but is essentially ignored by ACL2.</p>

 <p>When a constant symbol is used as a @(see term), ACL2 replaces it by its
 value; see @(see term).</p>

 <p>Note that @('defconst') uses so-called @(see safe-mode) to evaluate its
 form, in order to avoids soundness issues but with an efficiency penalty
 (perhaps increasing the evaluation time by several hundred percent).  If
 efficiency is a concern, or if for some reason you need the form to be
 evaluated without safe mode (e.g., you are an advanced system hacker using
 trust tags to traffic in raw Lisp code), consider using @(see defconsts)
 instead.  Also see @(see using-tables-efficiently) for an analogous issue with
 @(tsee table) events.</p>

 <p>It may be of interest to note that @('defconst') is implemented at the lisp
 level using @('defparameter'), as opposed to @('defconstant').
 (Implementation note: this is important for proper support of undoing and
 redefinition.)</p>

 <p>We close with a technical remark, perhaps of interest only who make use of
 the @(see hons-enabled) features of ACL2.  For an event of the form
 @('(defconst *C* (quote OBJ))'), i.e., @('(defconst *C* 'OBJ)'), then the
 value associated with @('*C*') is @('OBJ'); that is, the value of @('*C*') is
 @(tsee eq) to the actual object @('OBJ') occurring in the @('defconst') form.
 So for example, if @(tsee make-event) is used to generate such a @('defconst')
 event, as it is in the two books mentioned above, and @('OBJ') is a fast
 alist (see @(see fast-alists)), then the value of @('*C*') is a fast alist.
 This guarantee disappears if the term in the @('defconst') form is not a
 quoted object, i.e., if it is not of the form @('(quote OBJ)').</p>")

(defxdoc defdoc
  :parents (events)
  :short "Deprecated event (formerly for adding documentation)"
  :long "<p>This event is deprecated; see @(see xdoc) for information about
 @(see documentation) in ACL2.  @('Defdoc') @(see events) are never considered
 redundant (see @(see redundant-events)).</p>")

(defxdoc defequiv
  :parents (events)
  :short "Prove that a function is an @(see equivalence) relation"
  :long "@({
  Example:
  (defequiv set-equal)

  is an abbreviation for
  (defthm set-equal-is-an-equivalence
    (and (booleanp (set-equal x y))
         (set-equal x x)
         (implies (set-equal x y) (set-equal y x))
         (implies (and (set-equal x y)
                       (set-equal y z))
                  (set-equal x z)))
    :rule-classes (:equivalence))
 })

 <p>See @(see equivalence).</p>

 @({
  General Form:
  (defequiv fn
    :rule-classes rule-classes
    :instructions instructions
    :hints hints
    :otf-flg otf-flg
    :event-name event-name
    :doc doc)
 })

 <p>where @('fn') is a function symbol of arity 2, @('event-name'), if
 supplied, is a symbol, and all other arguments are as specified in the
 documentation for @(tsee defthm).  The @('defequiv') macro expands into a call
 of @('defthm').  The name of the @('defthm') is @('fn-is-an-equivalence'),
 unless @('event-name') is supplied, in which case @('event-name') is the name
 used.  The term generated for the @('defthm') event states that @('fn') is
 Boolean, reflexive, symmetric, and transitive.  The rule-class
 @(':equivalence') is added to the @(see rule-classes) specified, if it is not
 already there.  All other arguments to the generated @('defthm') form are as
 specified by the other keyword arguments above.</p>")

(defxdoc defevaluator
  :parents (events)
  :short "Introduce an evaluator function"
  :long "@({
  Example:
  (defevaluator evl evl-list
    ((length x) (member-equal x y)))
 })

 <p>See @(see meta).</p>

 @({
  General Form:
  (defevaluator ev ev-list
     ((g1 x1 ... xn_1)
      ...
      (gk x1 ... xn_k))
     :namedp flg)       ; [optional keyword argument]
 })

 <p>where @('ev') and @('ev-list') are new function symbols and @('g1'), ...,
 @('gk') are old function symbols with the indicated number of formals, i.e.,
 each @('gi') has @('n_i') formals.  If the @(':namedp') keyword argument
 is provided, its value should be Boolean.  If not provided, the default
 value for @('flg') is @('nil').</p>

 <p>This function provides a convenient way to constrain @('ev') and
 @('ev-list') to be mutually-recursive evaluator functions for the symbols
 @('g1'), ..., @('gk').  Roughly speaking, an evaluator function for a fixed,
 finite set of function symbols is a restriction of the universal evaluator to
 terms composed of variables, constants, lambda expressions, and applications
 of the given functions.  However, evaluator functions are constrained rather
 than defined, so that the proof that a given metafunction is correct vis-a-vis
 a particular evaluator function can be lifted (by functional instantiation) to
 a proof that it is correct for any larger evaluator function.  See @(see meta)
 for a discussion of metafunctions.</p>

 <p>If the @(':namedp') @('flg') is @('nil') (the default) constraints have
 names of the form <i>ev</i>@('-CONSTRAINT-')<i>i</i>, e.g.,
 @('EV-CONSTRAINT-0'), @('EV-CONSTRAINT-1'), etc.  If @('flg') is non-@('nil'),
 the constraints are named more mnemonically, e.g., @('EV-OF-VARIABLE'),
 @('EV-OF-REVAPPEND-CALL'), etc.  We illustrate the @(':namedp t') names
 below.</p>

 <p>@('Defevaluator') executes an @(tsee encapsulate) after generating the
 appropriate @(tsee defun) and @(tsee defthm) events.  Perhaps the easiest way
 to understand what @('defevaluator') does is to execute the keyword
 command</p>

 @({
  :trans1 (defevaluator evl evl-list ((length x) (member-equal x y)))
 })

 <p>and inspect the output.  This trick is also useful in the rare case that
 the event fails because a hint is needed.  In that case, the output of
 @(':')@(tsee trans1) can be edited by adding hints, then submitted
 directly.</p>

 <p>Formally, @('ev') is said to be an ``evaluator function for @('g1'), ...,
 @('gk'), with mutually-recursive counterpart @('ev-list')'' iff @('ev') and
 @('ev-list') are constrained functions satisfying just the @(see constraint)s
 discussed below.</p>

 <p>@('Ev') and @('ev-list') must satisfy @(see constraint)s (0)-(5) and
 (k) below.  When @(':namedp nil') is supplied, the <i>i</i> in the generated
 constraint names are the parenthesized numbers below.  When @(':namedp t')
 is supplied, the mnemonic names are those shown in brackets below.</p>

 @({
  (0) How to ev an arbitrary function application:
      [EV-OF-FNCALL-ARGS]
      (implies (and (consp x)
                    (syntaxp (not (equal a ''nil)))
                    (not (equal (car x) 'quote)))
               (equal (ev x a)
                      (ev (cons (car x)
                                (kwote-lst (ev-list (cdr x) a)))
                          nil)))

  (1) How to ev a variable symbol:
      [EV-OF-VARIABLE]
      (implies (symbolp x)
               (equal (ev x a) (and x (cdr (assoc-equal x a)))))

  (2) How to ev a constant:
      [EV-OF-QUOTE]
      (implies (and (consp x)
                    (equal (car x) 'quote))
               (equal (ev x a) (cadr x)))

  (3) How to ev a lambda application:
      [EV-OF-LAMBDA]
      (implies (and (consp x)
                    (consp (car x)))
               (equal (ev x a)
                      (ev (caddar x)
                          (pairlis$ (cadar x)
                                    (ev-list (cdr x) a)))))

  (4) How to ev an empty argument list:
      [EV-LIST-OF-ATOM]
      (implies (not (consp x-lst))
               (equal (ev-list x-lst a)
                      nil))

  (5) How to ev a non-empty argument list:
      [EV-LIST-OF-CONS]
      (implies (consp x-lst)
               (equal (ev-list x-lst a)
                      (cons (ev (car x-lst) a)
                            (ev-list (cdr x-lst) a))))

  (k) For each i from 1 to k, how to ev an application of gi,
      where gi is a function symbol of n arguments:
      [EV-OF-gi-CALL]
      (implies (and (consp x)
                    (equal (car x) 'gi))
               (equal (ev x a)
                      (gi (ev x1 a)
                          ...
                          (ev xn a)))),
      where xi is the (cad...dr x) expression equivalent to (nth i x).
 })

 <p>@('Defevaluator') defines suitable witnesses for @('ev') and @('ev-list'),
 proves the theorems about them, and constrains @('ev') and @('ev-list')
 appropriately.  We expect @('defevaluator') to work without assistance from
 you, though the proofs do take some time and generate a lot of output.  The
 proofs are done in the context of a fixed theory, namely the value of the
 constant @('*defevaluator-form-base-theory*').</p>

 <p>(Aside: (3) above may seem surprising, since the bindings of @('a') are not
 included in the environment that is used to evaluate the lambda body,
 @('(caddar x)').  However, ACL2 lambda expressions are all <i>closed</i>: in
 @('(lambda (v1 ... vn) body)'), the only free variables in @('body') are among
 the @('vi').  See @(see term).)</p>

 <p>Acknowledgment: We thank Sol Swords and Jared Davis for their community
 book @('tools/defevaluator-fast.lisp'), which provided the model on which the
 current @('defevaluator') is based.  The original @('defevaluator') was very
 inefficient, e.g., taking thousands of times longer than the current one on an
 evaluator interpreting 800 function symbols.  We refactored their
 @('defevaluator-fast') (with permission) and made it the new implementation as
 of ACL2 Version_7.2.  Both implementations produce the same constraints modulo
 the naming option provided by @(':namedp').</p>")

(defxdoc defexec
  :parents (events mbe)
  :short "Attach a terminating executable function to a definition"
  :long "<p>Suppose you define a function @('(fn x)') with a @(see guard) of
 @('(good-input-p x)'), and you know that when the guard holds, the measure
 decreases on each recursive call.  Unfortunately, the definitional principle
 (see @(see defun)) ignores the guard.  For example, if the definition has the
 form</p>

 @({
  (defun fn (x)
    (declare (xargs :guard (good-input-p x)))
    (if (not-done-yet x)
        (... (fn (destr x)) ...)
      ...))
 })

 <p>then in order to admit this definition, ACL2 must prove the appropriate
 formula asserting that @('(destr x)') is ``smaller than'' @('x') under the
 assumption @('(not-done-yet x)') but without the assumption @('(good-input-p
 x)'), even if @('(not-done-yet x)') is true.  In essence, it may be necessary
 to submit instead the following definition.</p>

 @({
  (defun fn (x)
    (declare (xargs :guard (good-input-p x)))
    (if (good-input-p x)
        (if (not-done-yet x)
            (... (fn (destr x)) ...)
          ...)
      nil)
 })

 <p>But it is unfortunate that when calls of @('fn') are evaluated, for example
 when @('fn') is applied to an explicit constant during a proof, then a call of
 @('good-input-p') must now be evaluated on each recursive call.</p>

 <p>Fortunately, @('defexec') provides a way to keep the execution efficient.
 For the example above we could use the following form.</p>

 @({
  (defexec fn (x)
    (declare (xargs :guard (good-input-p x)))
    (mbe :logic (if (good-input-p x)
                    (if (not-done-yet x)
                        (... (fn (destr x)) ...)
                      ...)
                  nil)
         :exec  (if (not-done-yet x)
                    (... (fn (destr x)) ...)
                  ...)))
 })

 <p>Here ``@(tsee mbe)'' stands for ``must be equal'' and, roughly speaking,
 its call above is logically equal to the @(':logic') form but is evaluated
 using the @(':exec') form when the guard holds.  See @(see mbe).  The effect
 is thus to define @('fn') as shown in the @(tsee defun) form above, but to
 cause execution of @('fn') using the @(':exec') body.  The use of @('defexec')
 instead of @(tsee defun) in the example above causes a termination proof to be
 performed, in order to guarantee that evaluation always theoretically
 terminates, even when using the @(':exec') form for evaluation.</p>

 @({
  Example:

  ; Some of the keyword arguments in the declarations below are irrelevant or
  ; unnecessary, but they serve to illustrate their use.

  (defexec f (x)
    (declare (xargs :measure (+ 15 (acl2-count x))
                    :ruler-extenders :basic
                    :hints ((\"Goal\" :in-theory (disable nth)))
                    :guard-hints ((\"Goal\" :in-theory (disable last)))
                    :guard (and (integerp x) (<= 0 x) (< x 25)))
             (exec-xargs
                    :test (and (integerp x) (<= 0 x))
                    :default-value 'undef ; defaults to nil
                    :measure (nfix x)
                    :ruler-extenders :basic
                    :well-founded-relation o<))
    (mbe :logic (if (zp x)
                    1
                  (* x (f (- x 1))))
         :exec  (if (= x 0)
                    1
                  (* x (f (- x 1))))))
 })

 <p>The above example macroexpands to the following.</p>

 @({
  (ENCAPSULATE ()
   (LOCAL
    (ENCAPSULATE ()
     (SET-IGNORE-OK T)
     (SET-IRRELEVANT-FORMALS-OK T)
     (LOCAL (DEFUN F (X)
              (DECLARE
               (XARGS :VERIFY-GUARDS NIL
                      :HINTS ((\"Goal\" :IN-THEORY (DISABLE NTH)))
                      :MEASURE (NFIX X)
                      :RULER-EXTENDERS :BASIC
                      :WELL-FOUNDED-RELATION O<))
              (IF (AND (INTEGERP X) (<= 0 X))
                  (IF (= X 0) 1 (* X (F (- X 1))))
                  'UNDEF)))
     (LOCAL (DEFTHM F-GUARD-IMPLIES-TEST
              (IMPLIES (AND (INTEGERP X) (<= 0 X) (< X 25))
                       (AND (INTEGERP X) (<= 0 X)))
              :RULE-CLASSES NIL))))
   (DEFUN F (X)
     (DECLARE (XARGS :MEASURE (+ 15 (ACL2-COUNT X))
                     :RULER-EXTENDERS :BASIC
                     :HINTS ((\"Goal\" :IN-THEORY (DISABLE NTH)))
                     :GUARD-HINTS ((\"Goal\" :IN-THEORY (DISABLE LAST)))
                     :GUARD (AND (INTEGERP X) (<= 0 X) (< X 25))))
     (MBE :LOGIC
          (IF (ZP X) 1 (* X (F (- X 1))))
          :EXEC
          (IF (= X 0) 1 (* X (F (- X 1)))))))
 })

 <p>Notice that in the example above, the @(':')@(tsee hints) in the @(tsee
 local) definition of @('F') are inherited from the @(':hints') in the @(tsee
 xargs) of the @('defexec') form.  We discuss such inheritance below.</p>

 <p>CAVEAT: Termination is not considered for calls of @(tsee mbe) under the
 top-level call.  Moreover, the @(':exec') part of an @(tsee mbe) call under
 the @(':logic') part of any superior @('mbe') call is completely ignored.</p>

 @({
  General Form:
  (defexec fn (var1 ... varn) doc-string dcl ... dcl
    (mbe :LOGIC logic-body
         :EXEC  exec-body))
 })

 <p>where the syntax is identical to the syntax of @(tsee defun) where the body
 is a call of @('mbe'), with the exceptions described below.  Thus, @('fn') is
 the symbol you wish to define and is a new symbolic name and @('(var1
 ... varn)') is its list of formal parameters (see @(see name)).  The first
 exception is that at least one @('dcl') (i.e., @(tsee declare) form) must
 specify a @(':guard'), @('guard').  The second exception is that one of the
 @('dcl')s is allowed to contain an element of the form @('(exec-xargs ...)').
 The @('exec-xargs') form, if present, must specify a non-empty @(tsee
 keyword-value-listp) each of whose keys is one of @(':test'),
 @(':default-value'), or one of the standard @(tsee xargs) keys of
 @(':measure'), @(':ruler-extenders'), @(':well-founded-relation'),
 @(':hints'), or @(':stobjs').  Any of these five standard @('xargs') keys that
 is present in an @('xargs') of some @('dcl') but is not specified in the
 (possibly nonexistent) @('exec-xargs') form is considered to be specified in
 the @('exec-xargs') form, as illustrated in the example above for @(':hints').
 (So for example, if you want @(':hints') in the final, non-local definition
 but not in the local definition, then specify the @(':hints') in the
 @('xargs') but specify @(':hints nil') in the @('exec-xargs').)  If @(':test')
 is specified and not @('nil'), let @('test') be its value; otherwise let
 @('test') default to @('guard').  If @(':default-value') is specified, let
 @('default-value') be its value; else @('default-value') is @('nil').
 @('Default-value') should have the same @(see signature) as @('exec-body');
 otherwise the @('defexec') form will fail to be admitted.</p>

 <p>The above General Form's macroexpansion is of the form @('(PROGN encap
 final-def)'), where @('encap') and @('final-def') are as follows.
 @('Final-def') is simply the result of removing the @('exec-xargs')
 declaration (if any) from its @(tsee declare) form, and is the result of
 evaluating the given @('defexec') form, since @('encap') is of the following
 form.</p>

 @({
  ; encap
  (ENCAPSULATE ()
    (set-ignore-ok t)             ; harmless for proving termination
    (set-irrelevant-formals-ok t) ; harmless for proving termination
    (local local-def)
    (local local-thm))
 })

 <p>The purpose of @('encap') is to ensure the the executable version of
 @('name') terminates on all arguments.  Thus, @('local-def') and
 @('local-thm') are as follows, where the @('xargs') of the @(tsee declare)
 form are the result of adding @(':VERIFY-GUARDS NIL') to the result of
 removing the @(':test') and (optional) @(':default-value') from the
 @('exec-xargs').</p>

 @({
  ; local-def
  (DEFUN fn formals
    (DECLARE (XARGS :VERIFY-GUARDS NIL ...))
    (IF test
        exec-body
      default-value))

  ; local-thm
  (DEFTHM fn-EXEC-GUARD-HOLDS
    (IMPLIES guard test)
    :RULE-CLASSES NIL)
 })

 <p>We claim that if the above @('local-def') and @('local-thm') are admitted,
 then all evaluations of calls of @('fn') terminate.  The concern is that the
 use of @(tsee mbe) in @('final-def') allows for the use of @('exec-body') for
 a call of @('fn'), as well as for subsequent recursive calls, when @('guard')
 holds and assuming that the guards have been verified for @('final-def').
 However, by @('local-thm') we can conclude in this case that @('test') holds,
 in which case the call of @('fn') may be viewed as a call of the version of
 @('fn') defined in @('local-def').  Moreover, since guards have been verified
 for @('final-def'), then guards hold for subsequent evaluation of
 @('exec-body'), and in particular for recursive calls of @('fn'), which can
 thus continue to be viewed as calls using @('local=def').</p>")

(defxdoc define-pc-help
  :parents (proof-builder)
  :short "Define a macro command whose purpose is to print something"
  :long "@({
  Example:
  (define-pc-help pp ()
    (if (goals t)
        (io? proof-builder nil state
             (state-stack)
             (fms0 \"~|~y0~|\"
                   (list (cons #0
                               (fetch-term (conc t)
                                           (current-addr t))))))
      (print-all-goals-proved-message state)))

  General Form:
  (define-pc-help name args &rest body)
 })

 <p>This defines a macro command named @('name'), as explained further below.
 The @('body') should (after removing optional declarations) be a form that
 returns @('state') as its single value.  Typically, it will just print
 something.</p>

 <p>What @('(define-pc-help name args &rest body)') really does is to create a
 call of @('define-pc-macro') that defines @('name') to take arguments
 @('args'), to have the declarations indicated by all but the last form in
 @('body'), and to have a body that (via @('pprogn')) first executes the form
 in the last element of body and then returns a call to the command @('skip')
 (which will return @('(mv nil t state)')).</p>")

(defxdoc define-pc-macro
  :parents (proof-builder)
  :short "Define a proof-builder macro command"
  :long "@({
  Example:
  (define-pc-macro ib (&optional term)
    (value
     (if term
         `(then (induct ,term) bash)
       `(then induct bash))))
 })

 <p>The example above captures a common paradigm: one attempts to prove the
 current goal by inducting and then simplifying the resulting goals.  (See
 @(see proof-builder-commands) for documentation of the command @('then'),
 which is itself a pc-macro command, and commands @('induct') and @('bash').)
 Rather than issuing @('(then induct bash)'), or worse yet issuing @('induct')
 and then issuing @('bash') for each resulting goals, the above definition of
 @('ib') would let you issue @('ib') and get the same effect.</p>

 @({
  General Form:
  (define-pc-macro cmd args doc-string dcl ... dcl body)
 })

 <p>where @('cmd') is the name of the pc-macro than you want to define,
 @('args') is its list of formal parameters.  @('Args') may include lambda-list
 keywords @('&optional') and @('&rest'); see @(see macro-args), but note that
 here, @('args') may not include @('&key') or @('&whole').</p>

 <p>The value of @('body') should be an @(see error-triple), of the form @('(mv
 erp xxx state)') for some @('erp') and @('xxx').  If @('erp') is @('nil'),
 then @('xxx') is handed off to the interactive proof-builder's instruction
 interpreter.  Otherwise, evaluation typically halts.  We may write more on the
 full story later if there is interest in reading it.</p>")

(defxdoc define-pc-meta
  :parents (proof-builder)
  :short "Define a proof-builder meta command"
  :long "<p>Built-in meta commands of the interactive @(see proof-builder)
 include @('undo') and @('restore'), and others (@('lisp'), @('exit'), and
 @('sequence')); see @(see proof-builder-commands).  The advanced proof-builder
 user can define these as well.  See ACL2 source file @('proof-builder-b.lisp')
 for examples, and contact the ACL2 implementors if those examples do not
 provide sufficient documentation.</p>")

(defxdoc define-trusted-clause-processor
  :parents (events)
  :short "Define a trusted (unverified) goal-level simplifier"
  :long "<p>This @(see documentation) assumes familiarity with
 @(':clause-processor') rules; see @(see clause-processor).  Briefly put, a
 <i>clause-processor</i> is a user-defined function that takes as input the
 ACL2 representation of a goal &mdash; a <i>clause</i> &mdash; and returns a
 list of goals (i.e., a list of clauses).  A @(':clause-processor') rule is a
 way to inform ACL2 that a clause-processor has been proved correct and now may
 be specified in @(':clause-processor') @(see hints).</p>

 <p>Here we describe a utility, @('define-trusted-clause-processor'), that
 provides another way to inform ACL2 that a function is to be considered a
 clause-processor that can be specified in a @(':clause-processor') hint.  You
 can find examples of correct and incorrect use of this utility in community
 book @('books/clause-processors/basic-examples').</p>

 <p>Consider the simple example already presented for @(':clause-processor')
 rules (again, see @(see clause-processor)), for a simple clause-processor
 named @('note-fact-clause-processor').  Instead of introducing an evaluator
 and proving a correctness theorem with @(':rule-classes :clause-processor'),
 we can simply inform ACL2 that we trust the function
 @('note-fact-clause-processor') to serve as a clause-processor.</p>

 @({
  (define-trusted-clause-processor
    note-fact-clause-processor
    nil
    :ttag my-ttag)
 })

 <p>A non-nil @(':ttag') argument generates a @(tsee defttag) event in order to
 acknowledge the dependence of the ACL2 session on the (unproved) correctness
 of this clause-processor.  That argument can be omitted if there is currently
 an active trust tag.  Note that the extra @(tsee defttag) event will be @(see
 local) to the @('define-trusted-clause-processor') event; that is, its effect
 will disappear after the @('define-trusted-clause-processor') event completes.
 This point becomes clear if one understands that a call of
 @('define-trusted-clause-processor') expands to a call of @(tsee encapsulate),
 and a @(tsee defttag) event is essentially @(see local) within any @(tsee
 encapsulate) event, as is any event that sets the @(tsee acl2-defaults-table).
 See @(see defttag).  Because we are trusting this clause-processor, rather
 than having proved it correct, we refer to it as a ``trusted''
 clause-processor to contrast with a proved-correct, or ``verified'',
 clause-processor.</p>

 <p>Now that the event displayed above has established
 @('note-fact-clause-processor') as a (trusted) clause-processor, we can use it
 in a @(':clause-processor') hint, for example as follows.  Notice that the
 output is identical to that for the corresponding example presented for the
 verified case (see @(see clause-processor)), except that the word ``verified''
 has been replaced by the word ``trusted''.</p>

 @({
  ACL2 !>(thm (equal (car (cons x y))
                     x)
              :hints
              ((\"Goal\"
                :clause-processor
                (note-fact-clause-processor clause '(equal a a)))))

  [Note:  A hint was supplied for our processing of the goal above.
  Thanks!]

  We now apply the trusted :CLAUSE-PROCESSOR function NOTE-FACT-CLAUSE-
  PROCESSOR to produce two new subgoals.

  Subgoal 2
  (IMPLIES (EQUAL A A)
           (EQUAL (CAR (CONS X Y)) X)).

  But we reduce the conjecture to T, by the :executable-counterpart of
  IF and the simple :rewrite rule CAR-CONS.

  Subgoal 1
  (EQUAL A A).

  But we reduce the conjecture to T, by primitive type reasoning.

  Q.E.D.

  Summary
  Form:  ( THM ...)
  Rules: ((:EXECUTABLE-COUNTERPART IF)
          (:EXECUTABLE-COUNTERPART NOT)
          (:FAKE-RUNE-FOR-TYPE-SET NIL)
          (:REWRITE CAR-CONS))
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

  Proof succeeded.
  ACL2 !>
 })

 <p>Indeed, if one runs this example first and subsequently verifies the
 clause-processor, one will see the word ``trusted'' change to
 ``verified''.</p>

 <p>The general form is as follows.</p>

 @({
  (define-trusted-clause-processor
    cl-proc           ;;; clause-processor function
    supporters        ;;; see below
    &key
    label             ;;; optional; cl-proc$label by default
    ttag              ;;; discussed above
    partial-theory    ;;; optional encapsulate event
    )
 })

 <p>We discussed the @(':ttag') argument above, and we will discuss the
 @('supporters') and @(':partial-theory') arguments later below.  Let us turn
 our attention to the @('label') argument and its ramifications for undoing and
 redundancy.</p>

 <p>As mentioned above, a successful @('define-trusted-clause-processor') event
 results in an @(tsee encapsulate) event.  If the @(':label') argument is
 supplied with a non-@('nil') value @('L'), or if @(':label') is omitted and
 @('L') is the result of adding the suffix @('\"$LABEL\"') to @('cl-proc'),
 then the event @('(deflabel L)') will be included under the resulting
 @('encapsulate') form.  Thus, you will be able to undo this
 @('define-trusted-clause-processor') with @(':')@(tsee ubt)@(' L').  Also,
 because of the criteria for redundant encapsulate events (see @(see
 REDUNDANT-ENCAPSULATE)),the entire form is considered redundant (skipped) if
 it is identical to one already executed in the current ACL2 @(see world), with
 one exception: if @(':partial-theory') is @('nil') or omitted, and also
 @(':label nil') is supplied explicitly, then the event will not be redundant.
 If the event is not redundant, then @('cl-proc') must not already be
 designated as a trusted clause-processor.</p>

 <p>Note that @('cl-proc') may be defined either in @(':program')-mode or
 @(':logic')-mode.</p>

 <p>The @('supporters') argument should be a true list of function symbols in
 the current ACL2 world.  It is important that this list include user-defined
 functions whose definitions support the correctness of the clause-processor
 function.  Otherwise, @(tsee local) definitions of those missing supporters
 can render the use of this clause-processor unsound, as discussed in the paper
 referenced at the end of the @(see clause-processor) documentation topic.
 Moreover, ACL2 assumes for dependent clause-processors (discussed below) that
 every function symbol constrained by the ``promised encapsulate'' of that
 event is either among those @('supporters') or ancestral in one of them
 (i.e. a supporter of a supporter, a supporter of one of those, etc.).</p>

 <p><b>Dependent clause-processors and promised encapsulates</b>: The
 @(':partial-theory') argument</p>

 <p>Suppose you want to introduce a clause-processor to reason about a complex
 hardware simulator that is implemented outside ACL2.  Sawada and Reeber had
 just such a problem, as reported in their FMCAD 2006 paper.  Indeed, they used
 @(tsee sys-call) to implement a @(':')@(tsee program)-mode function in ACL2
 that can invoke that simulator.  (This has been changed to @(tsee sys-call*)
 since @('sys-call') cannot invoke the OS during proofs; see @(see sys-call).)
 In principle one could code the simulator directly in ACL2; but it would be a
 tremendous amount of work that has no practical purpose, given the interface
 to the external simulator.  So: In what sense can we have a clause-processor
 that proves properties about a simulator when that simulator is not fully
 axiomatized in ACL2?  Our answer, in a nutshell, is this: The above
 @(':partial-theory') argument provides a way to write merely some of the @(see
 constraint)s on the external tool (or even no constraints at all), with the
 understanding that such constraints are present implicitly in a stronger
 ``promised'' @('encapsulate'), for example by exporting the full
 definition.</p>

 <p>If a trusted clause-processor is introduced with a @(':partial-theory')
 argument, we call it a ``dependent'' clause-processor, because its correctness
 is dependent on the constraints implicitly introduced by the
 @(':partial-theory') @('encapsulate') form.  The implicit constraints should
 logically imply the constraints actually introduced by the explicit
 @('encapsulate'), but they should also be sufficient to justify every possible
 invocation of the clause-processor in a @(':clause-processor') hint.  The user
 of a @('define-trusted-clause-processor') form is making a guarantee &mdash;
 or, is relying on a guarantee provided by the writer of that form &mdash; that
 in principle, there exists a so-called ``promised encapsulate'': an
 @('encapsulate') form with the same @(see signature) as the
 @(':partial-theory') @('encapsulate') form associated with the trusted
 clause-processor, but whose constraints introduced are the aforementioned
 implicit constraints.</p>

 <p>There are several additional requirements on a @(':partial-theory')
 argument.  First, it must be an @(tsee encapsulate) event with non-empty @(see
 signature).  Moreover, the functions introduced by that event must be exactly
 those specified in the signature, and no more.  And further still, the
 @('define-trusted-clause-processor') form cannot be executed inside any @(tsee
 encapsulate) form with non-empty @(see signature); we can think of this
 situation as attempting to associate more than one @('encapsulate') with the
 functions introduced in the inner @('encapsulate').</p>

 <p>The @(':partial-theory') event will (in essence) be executed as part of the
 evaluation of the @('define-trusted-clause-processor') form.  Again, a
 critical obligation rests on the user who provides a @(':partial-theory'):
 there must exist (in principle at least) a corresponding promised encapsulate
 form with the same @(see signature) that could logically be admitted, whenever
 the above @('define-trusted-clause-processor') form is evaluated successfully,
 that justifies the designation of @('cl-proc') as a clause-processor.  See
 also the paper mentioned above for more about promised encapsulates.  A key
 consequence is that the @(see constraint)s are unknown for the functions
 introduced in (the signature of) a @(':partial-theory') @(tsee encapsulate)
 form.  Thus, functional instantiation (see @(see
 functional-instantiation-example)) is disabled for function in the signature
 of a @(':partial-theory') form.</p>

 <p><b>A remark on the underlying implementation</b></p>

 <p>You can see all of the current trusted clause-processors by issuing the
 command @('(table trusted-clause-processor-table)').  Those that are dependent
 clause-processors will be associated in the resulting association list with a
 pair whose @('car') is the list of supporters and whose @('cdr') is @('t'),
 i.e., with @('(supporters . t)'); the others will be associated just with
 @('(supporters)').</p>

 <p>Thus, @('define-trusted-clause-processor') is actually a macro that
 generates (among other things) a @('table') event for a table named
 @('trusted-clause-processor-table'); see @(see table).  You are invited to use
 @(':')@(tsee trans1) to see expansions of calls of this macro.</p>

 <p><b>A technique for using raw Lisp to define a trusted
 clause-processor</b></p>

 <p>The following code is intended to give an idea for how one might define the
 ``guts'' of a trusted clause-processor in raw Lisp.  The idea is to stub out
 functions, such as @('acl2-my-prove below'), that you want to define in raw
 Lisp; and then, load a raw Lisp file to overwrite any such function with the
 real code.  But then we make any such overwritten function untouchable.  (This
 last step is important because otherwise, one can prove @('nil') using a
 @(':functional-instance') @(':use') hint, by exploiting the fact that this
 function has executable code for which there is no corresponding definitional
 axiom.)  Note: The point here is only to illustrate the use of raw Lisp, so we
 do not bother to define or explain functions @('hint-to-termlist') or
 @('disjoin-clause-segments-to-clause'), which this example assumes are defined
 elsewhere; their meanings are not important for this example.</p>

 @({
  (defstub acl2-my-prove (term hint) t)

  (program)

  (defttag :my-cl-proc)

  (progn

  ; We wrap everything here in a single progn, so that the entire form is
  ; atomic.  That's important because we want the use of push-untouchable to
  ; prevent anything besides my-clause-processor from calling acl2-my-prove.

    (progn!

     (set-raw-mode-on state)

     (load \"my-hint-raw.lsp\") ; defines my-prove in raw Lisp

     (defun acl2-my-prove (term hint)
       (my-prove term hint)))

    (defun my-clause-processor (cl hint)
      (declare (xargs :guard (pseudo-term-listp cl)
                      :mode :program))
      (if (acl2-my-prove (disjoin cl) hint)
          (disjoin-clause-segments-to-clause
           (pairlis$ (hint-to-termlist hint) nil)
           cl)
        (prog2$ (cw \"~|~%NOTE: Unable to prove goal with ~
                    my-clause-processor and indicated hint.~|\")
                (list cl))))

    (push-untouchable acl2-my-prove t)
    )
 })")

(defxdoc definition
  :parents (rule-classes)
  :short "Make a rule that acts like a function definition"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes
 and how they are used to build rules from formulas.  An example @(':')@(tsee
 corollary) formula from which a @(':definition') rule might be built is:</p>

 @({
  Examples:
  (defthm open-len-twice
    (implies (true-listp x)
             (equal (len x)
                    (if (null x)
                        0
                      (if (null (cdr x))
                          1
                        (+ 2 (len (cddr x)))))))
    :rule-classes :definition)

  ; Same as above, with :controller-alist made explicit:
  (defthm open-len-twice
    (implies (true-listp x)
             (equal (len x)
                    (if (null x)
                        0
                      (if (null (cdr x))
                          1
                        (+ 2 (len (cddr x)))))))
    :rule-classes ((:definition :controller-alist ((len t)))))

  General Form:
  (implies hyp (equiv (fn a1 ... an) body))
 })

 <p>where @('equiv') is an equivalence relation and @('fn') is a function
 symbol other than @(tsee if), @(tsee hide), @(tsee force) or @(tsee
 case-split).  Such rules allow ``alternative'' definitions of @('fn') to be
 proved as theorems but used as definitions.  These rules are not true
 ``definitions'' in the sense that they (a) cannot introduce new function
 symbols and (b) do not have to be terminating recursion schemes.  They are
 just conditional rewrite rules that are controlled the same way we control
 recursive definitions.  We call these ``definition rules'' or ``generalized
 definitions''.</p>

 <p>Consider the general form above.  Generalized definitions are stored among
 the @(':')@(tsee rewrite) rules for the function ``defined,'' @('fn') above,
 but the procedure for applying them is a little different.  During rewriting,
 instances of @('(fn a1 ... an)') are replaced by corresponding instances of
 @('body') provided the @('hyp')s can be established as for a @(':')@(tsee
 rewrite) rule and the result of rewriting @('body') satisfies the criteria for
 function expansion.  There are two primary criteria, either of which permits
 expansion.  The first is that the ``recursive'' calls of @('fn') in the
 rewritten body have arguments that already occur in the goal conjecture.  The
 second is that the ``controlling'' arguments to @('fn') are simpler in the
 rewritten body.</p>

 <p>The notions of ``recursive call'' and ``controllers'' are complicated by
 the provisions for mutually recursive definitions.  Consider a ``clique'' of
 mutually recursive definitions.  Then a ``recursive call'' is a call to any
 function defined in the clique and an argument is a ``controller'' if it is
 involved in the measure that decreases in all recursive calls.  These notions
 are precisely defined by the definitional principle and do not necessarily
 make sense in the context of generalized definitional equations as implemented
 here.</p>

 <p>But because the heuristics governing the use of generalized definitions
 require these notions, it is generally up to the user to specify which calls
 in body are to be considered recursive and what the controlling arguments are.
 This information is specified in the @(':clique') and @(':controller-alist')
 fields of the @(':definition') rule class.</p>

 <p>The @(':clique') field is the list of function symbols to be considered
 recursive calls of @('fn').  In the case of a non-recursive definition, the
 @(':clique') field is empty; in a singly recursive definition, it should
 consist of the singleton list containing @('fn'); otherwise it should be a
 list of all of the functions in the mutually recursive clique with this
 definition of @('fn').</p>

 <p>If the @(':clique') field is not provided it defaults to @('nil') if
 @('fn') does not occur as a function symbol in @('body') and it defaults to
 the singleton list containing @('fn') otherwise.  Thus, @(':clique') must be
 supplied by the user only when the generalized definition rule is to be
 treated as one of several in a mutually recursive clique.</p>

 <p>The @(':controller-alist') is an alist that maps each function symbol in
 the @(':clique') to a mask specifying which arguments are considered
 controllers.  The mask for a given member of the clique, @('fn'), must be a
 list of @('t')'s and @('nil')'s of length equal to the arity of @('fn').  A
 @('t') should be in each argument position that is considered a ``controller''
 of the recursion.  For a function admitted under the principle of definition,
 an argument controls the recursion if it is one of the arguments measured in
 the termination argument for the function.  But in generalized definition
 rules, the user is free to designate any subset of the arguments as
 controllers.  Failure to choose wisely may result in the ``infinite
 expansion'' of definitional rules but cannot render ACL2 unsound since the
 rule being misused is a theorem.</p>

 <p>If the @(':controller-alist') is omitted it can sometimes be defaulted
 automatically by the system.  If the @(':clique') is @('nil'), the
 @(':controller-alist') defaults to @('nil').  If the @(':clique') is a
 singleton containing @('fn'), the @(':controller-alist') defaults to the
 controller alist computed by @('(defun fn args body)').  (The user can obtain
 some control over this analysis by setting the default ruler-extenders; see
 @(see rulers).)  If the @(':clique') contains more than one function, the user
 must supply the @(':controller-alist') specifying the controllers for each
 function in the clique.  This is necessary since the system cannot determine
 and thus cannot analyze the other definitional equations to be included in the
 clique.</p>

 <p>For example, suppose @('fn1') and @('fn2') have been defined one way and it
 is desired to make ``alternative'' mutually recursive definitions available to
 the rewriter.  Then one would prove two theorems and store each as a
 @(':definition') rule.  These two theorems would exhibit equations
 ``defining'' @('fn1') and @('fn2') in terms of each other.  No provision is
 here made for exhibiting these two equations as a system of equations.  One is
 proved and then the other.  It just so happens that the user intends them to
 be treated as mutually recursive definitions.  To achieve this end, both
 @(':definition') rules should specify the @(':clique') @('(fn1 fn2)') and
 should specify a suitable @(':controller-alist').  If, for example, the new
 definition of @('fn1') is controlled by its first argument and the new
 definition of @('fn2') is controlled by its second and third (and they each
 take three arguments) then a suitable @(':controller-alist') would be @('((fn1
 t nil nil) (fn2 nil t t))').  The order of the pairs in the alist is
 unimportant, but there must be a pair for each function in the clique.</p>

 <p>Inappropriate heuristic advice via @(':clique') and @(':controller-alist')
 can cause ``infinite expansion'' of generalized definitions, but cannot render
 ACL2 unsound.</p>

 <p>Note that the actual definition of @('fn1') has the runic name
 @('(:definition fn1)').  The runic name of the alternative definition is
 @('(:definition lemma)'), where @('lemma') is the name given to the event that
 created the generalized @(':definition') rule.  This allows theories to switch
 between various ``definitions'' of the functions.</p>

 <p>By default, a @(':definition') rule establishes the so-called ``body'' of a
 function.  The body is used by @(':expand') @(see hints), and it is also used
 heuristically by the theorem prover's preprocessing (the initial
 simplification using ``simple'' rules that is controlled by the
 @('preprocess') symbol in @(':do-not') @(see hints)), induction analysis, and
 the determination for when to warn about non-recursive functions in rules.
 The body is also used by some heuristics involving whether a function is
 recursively defined, and by the @('expand'), @('x'), and @('x-dumb') commands
 of the interactive @(see proof-builder).</p>

 <p>See @(see rule-classes) for a discussion of the optional field
 @(':install-body') of @(':definition') rules, which controls whether a
 @(':definition') rule is used as described in the paragraph above.  Note that
 even if @(':install-body nil') is supplied, the rewriter will still rewrite
 with the @(':definition') rule; in that case, ACL2 just won't install a new
 body for the top function symbol of the left-hand side of the rule, which for
 example affects the application of @(':expand') hints as described in the
 preceding paragraph.  Also see @(see set-body) and see @(see show-bodies) for
 how to change the body of a function symbol.</p>

 <p>Note only that if you prove a definition rule for function @('foo'), say,
 @('foo-new-def'), you will need to refer to that definition as
 @('foo-new-def') or as @('(:DEFINITION foo-new-def)').  That is because a
 @(':definition') rule does not change the meaning of the symbol @('foo') for
 @(':use') @(see hints), nor does it change the meaning of the symbol @('foo')
 in theory expressions; see @(see theories), in particular the discussion there
 of runic designators.  Similarly @(':')@(tsee pe) @('foo') and @(':')@(tsee
 pf) @('foo') will still show the original definition of @('foo').</p>

 <p>The definitional principle, @(tsee defun), actually adds @(':definition')
 rules.  Thus the handling of generalized definitions is exactly the same as
 for ``real'' definitions because no distinction is made in the implementation.
 Suppose @('(fn x y)') is @(tsee defun)'d to be @('body').  Note that @(tsee
 defun) (or @(tsee defuns) or @(tsee mutual-recursion)) can compute the clique
 for @('fn') from the syntactic presentation and it can compute the controllers
 from the termination analysis.  Provided the definition is admissible, @(tsee
 defun) adds the @(':definition') rule @('(equal (fn x y) body)').</p>")

(defxdoc deflabel
  :parents (events)
  :short "Build a landmark"
  :long "@({
 Examples:
 (deflabel interp-section)

 General Form:
 (deflabel name)
 })

 <p>where @('name') is a new symbolic name (see @(see name)).  By virtue of the
 fact that @('deflabel') is an event, it marks the current @(see history) with
 the @('name').  For example, you may wish to undo back through some label or
 compute a theory expression (see @(see theories)) in terms of some labels.
 @('Deflabel') @(see events) are never considered redundant.  See @(see
 redundant-events).</p>")

(defxdoc deflock
  :parents (parallel-programming)
  :short "Define a wrapper macro that provides mutual exclusion in ACL2(p)"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel evaluation and proof; see @(see
 parallelism).</p>

 @({
  Example Form:
  (deflock *my-lock*)

  General Form:
  (deflock *symbol*)
 })

 <p>where @('*symbol*') is a symbol whose first and last characters are both
 the character @('#\\*').</p>

 <p>A call of this macro generates a definition of another macro, named
 @('with-<modified-lock-symbol>'), where @('<modified-lock-symbol>') is the
 given symbol with the leading and trailing @('*') characters removed.  This
 newly defined macro will guarantee mutually exclusive execution when called in
 the body of the raw Lisp definition of a function, as is typically the case
 for @(see guard)-verified functions, for @(':')@(tsee program) mode functions,
 and for calls of macro @(tsee top-level).  (See @(see guard-evaluation-table)
 for details of how raw Lisp code might not be invoked when guard-checking (see
 @(see set-guard-checking)) has value @(':none') or @(':all').)  Note that this
 macro is also simply the identity when invoked directly in the top-level loop;
 see @(see top-level) for a way to avoid this issue, and see @(see
 parallelism-at-the-top-level) for a general discussion of this issue for calls
 of @(see parallelism) primitives.</p>

 <p>To see how mutual exclusion is guaranteed, consider the raw Lisp code
 generated for the macro, @('with-<modified-lock-symbol>'), that is introduced
 by a call of @('deflock').  This code uses a lock (with the given
 @('*symbol*') as its name), which guarantees that for any two forms that are
 each in the scope of a call of @('with-<modified-lock-symbol>'), the forms do
 not execute concurrently.</p>

 <p>Note that a call of @('deflock') expands into the application of @('progn')
 to two events, as illustrated below.</p>

 @({
  ACL2 !>:trans1 (deflock *my-cw-lock*)
   (PROGN (TABLE LOCK-TABLE '*MY-CW-LOCK* T)
          (DEFMACRO WITH-MY-CW-LOCK (&REST ARGS)
                    (LIST* 'WITH-LOCK '*MY-CW-LOCK* ARGS)))
  ACL2 !>
 })

 <p>Thus, @('deflock') forms are legal embedded event forms (see @(see
 embedded-event-form)) for @(see books) as well as @(tsee encapsulate) and
 @(tsee progn) @(see events).</p>

 <p>The following log shows a lock in action.  Recall that locks work as
 expected in @(see guard)-verified and @(':')@(tsee program) mode functions;
 they do not, however, work in @(':')@(tsee logic) mode functions that have not
 been guard-verified, as illustrated below.</p>

 @({
  ACL2 !>(deflock *my-cw-lock*)
  [[.. output omitted ..]]
   WITH-MY-CW-LOCK
  ACL2 !>(defun foo (n)
           (declare (xargs :guard (natp n) :verify-guards nil))
           (plet ((x1 (with-my-cw-lock (cw \"~x0\" (make-list n))))
                  (x2 (with-my-cw-lock (cw \"~x0\" (make-list n)))))
                 (and (null x1) (null x2))))
  [[.. output omitted ..]]
   FOO
  ACL2 !>(foo 20)
  (NIL NIL NIL NIL( NIL NIL NIL NIL NIL NILNIL  NIL NILNIL  NIL NILNIL
       NIL NILNIL NIL  NIL NILNIL  NIL NIL
  NIL      NILNIL  NIL NILNIL )
  NIL NIL NIL NIL NIL NIL NIL NIL)
  T
  ACL2 !>(verify-guards foo)
  [[.. output omitted ..]]
   FOO
  ACL2 !>(foo 20)
  (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
       NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
  (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
       NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
  T
  ACL2 !>
 })")

(defxdoc defmacro
  :parents (macros events programming)
  :short "Define a macro"
  :long "@({
  Example Defmacros:
  (defmacro xor (x y)
    (list 'if x (list 'not y) y))

  (defmacro git (sym key)
    (list 'getprop sym key nil
          '(quote current-acl2-world)
          '(w state)))

  (defmacro one-of (x &rest rst)
    (declare (xargs :guard (symbol-listp rst)))
    (cond ((null rst) nil)
          (t (list 'or
                   (list 'eq x (list 'quote (car rst)))
                   (list* 'one-of x (cdr rst))))))

  Example Expansions:
  term                    macroexpansion

  (xor a b)              (if a (not b) b)
  (xor a (foo b))        (if a (not (foo b)) (foo b))

  (git 'car 'lemmas)     (getprop 'car 'lemmas nil
                                  'current-acl2-world
                                  (w state))

  (one-of x a b c)       (or (eq x 'a)
                             (or (eq x 'b)
                                 (or (eq x 'c) nil)))

  (one-of x 1 2 3)       ill-formed (guard violation)

  General Form:
  (defmacro name macro-args doc-string dcl ... dcl body)
 })

 <p>where @('name') is a new symbolic name (see @(see name)), @('macro-args')
 specifies the formal parameters of the macro, and @('body') is a term.  The
 formal parameters can be specified in a much more general way than is allowed
 by ACL2 @(tsee defun) @(see events); see @(see macro-args) for a description
 of keyword (@('&key')) and optional (@('&optional')) parameters as well as
 other so-called ``lambda-list keywords'', @('&rest') and @('&whole').
 @('Doc-string'), if non-@('nil'), is an optional string that can provide
 documentation but is essentially ignored by ACL2.  Each @('dcl') is an
 optional declaration (see @(see declare)) except that the only @(tsee xargs)
 keyword permitted by @('defmacro') is @(':')@(tsee guard).</p>

 <p>For compute-intensive applications, see @(see defmac), which can speed up
 macroexpansion by introducing an auxiliary @('defun').  For a variant of
 @('defmacro') that automatically quotes arguments by default, but provides a
 way for calls to evaluate specified arguments, see @(see defmacroq).</p>

 <p>Macroexpansion occurs when a form is read in, i.e., before the evaluation
 or proof of that form is undertaken.  To experiment with macroexpansion, see
 @(see trans).  When a form whose @(tsee car) is @('name') arises as the form
 is read in, the arguments are bound as described in CLTL pp. 60 and 145, the
 @(see guard) is checked, and then the @('body') is evaluated.  The result is
 used in place of the original form.</p>

 <p>In ACL2, macros do not have access to the ACL2 state, @(tsee state).  (If
 @(tsee state) or any user-defined stobj (see @(see stobj)) is a macro
 argument, it is treated as an ordinary variable, bound at macro-expansion time
 to a piece of syntax.)  This is in part a reflection of CLTL, p. 143, ``More
 generally, an implementation of Common Lisp has great latitude in deciding
 exactly when to expand macro calls with a program. ...  Macros should be
 written in such a way as to depend as little as possible on the execution
 environment to produce a correct expansion.''  In ACL2, the product of
 macroexpansion is independent of the current environment and is determined
 entirely by the macro body and the functions and constants it references.  It
 is possible, however, to define macros that produce expansions that refer to
 @(tsee state) or other single-threaded objects (see @(see stobj)) or variables
 not among the macro's arguments.  See the @('git') example above.  For a
 related utility that does have access to the ACL2 @(see state), see @(see
 make-event).</p>")

(defxdoc defmacro-last
  :parents (events)
  :short "Define a macro that returns its last argument, but with side effects"
  :long "<p>This is an advanced feature that requires a trust tag.  For
 explanation, including an example, see @(see return-last).</p>")

(defxdoc defn
  :parents (defun events)
  :short "Definition with @(see guard) @('t')"
  :long "<p>@('Defn') is @(tsee defun) with @(see guard) @('t').</p>")

(defxdoc defnd
  :parents (defun events)
  :short "@(see disable)d definition with @(see guard) @('t')"
  :long "<p>@('Defnd') is @(tsee defund) with @(see guard) @('t').</p>")

(defxdoc defpkg
  :parents (events packages programming)
  :short "Define a new symbol package"
  :long "@({
  Example:
  (defpkg \"MY-PKG\"
          (union-eq *acl2-exports*
                    *common-lisp-symbols-from-main-lisp-package*))

  General Form:
  (defpkg \"name\" term doc-string)
 })

 <p>where @('\"name\"') is a non-empty string consisting of standard characters
 (see @(see standard-char-p)), none of which is lower case, that names the
 package to be created; @('term') is a variable-free expression that evaluates
 to a list of symbols, where no two distinct symbols in the list may have the
 same @(tsee symbol-name), to be imported into the newly created package; and
 @('doc-string'), if non-@('nil'), is an optional string that can provide
 documentation but is essentially ignored by ACL2.  The name of the new package
 must be ``new'': the host lisp must not contain any package of that name.
 There are two exceptions to this newness rule, discussed at the end of this
 documentation.</p>

 <p>(There is actually an additional argument, book-path, that is used for
 error reporting but has no logical content.  Users should generally ignore
 this argument, as well as the rest of this sentence: a book-path will be
 specified for @(tsee defpkg) events added by ACL2 to the @(see portcullis) of
 a book's @(see certificate); see @(see hidden-death-package).)</p>

 <p>@('Defpkg') forms can be entered at the top-level of the ACL2 @(see
 command) loop.  They should not occur in @(see books) (see @(see
 certify-book)).</p>

 <p>After a successful @('defpkg') it is possible to ``intern'' a string into
 the package using @(tsee intern-in-package-of-symbol).  The result is a symbol
 that is in the indicated package, provided the imports allow it.  For example,
 suppose @(''my-pkg::abc') is a symbol whose @(tsee symbol-package-name) is
 @('\"MY-PKG\"').  Suppose further that the imports specified in the
 @('defpkg') for @('\"MY-PKG\"') do not include a symbol whose @(tsee
 symbol-name) is @('\"XYZ\"').  Then</p>

 @({
  (intern-in-package-of-symbol \"XYZ\" 'my-pkg::abc)
 })

 <p>returns a symbol whose @(tsee symbol-name) is @('\"XYZ\"') and whose @(tsee
 symbol-package-name) is @('\"MY-PKG\"').  On the other hand, if the imports to
 the @('defpkg') does include a symbol with the name @('\"XYZ\"'), say in the
 package @('\"LISP\"'), then</p>

 @({
  (intern-in-package-of-symbol \"XYZ\" 'my-pkg::abc)
 })

 <p>returns that symbol (which is uniquely determined by the restriction on the
 imports list above).  See @(see intern-in-package-of-symbol).</p>

 <p>Upon admission of a @('defpkg') event, the function @('pkg-imports') is
 extended to compute a list of all symbols imported into the given package,
 without duplicates.</p>

 <p>@('Defpkg') is the only means by which an ACL2 user can create a new
 package or specify what it imports.  That is, ACL2 does not support the Common
 Lisp functions @('make-package') or @('import').  Currently, ACL2 does not
 support exporting at all.</p>

 <p>The Common Lisp function @(tsee intern) is weakly supported by ACL2; see
 @(see intern).  A more general form of that function is also provided: see
 @(see intern$).</p>

 <p>We now explain the two exceptions to the newness rule for package names.
 The careful experimenter will note that if a package is created with a
 @('defpkg') that is subsequently undone, the host lisp system will contain the
 created package even after the undo.  Because ACL2 hangs onto @(see world)s
 after they have been undone, e.g., to implement @(':')@(tsee oops) but, more
 importantly, to implement error recovery, we cannot actually destroy a package
 upon undoing it.  Thus, the first exception to the newness rule is that
 @('name') is allowed to be the name of an existing package if that package was
 created by an undone @('defpkg') and the newly proposed set of imports is
 identical to the old one.  See @(see
 package-reincarnation-import-restrictions).  This exception does not violate
 the spirit of the newness rule, since one is disinclined to believe in the
 existence of undone packages.  The second exception is that @('name') is
 allowed to be the name of an existing package if the package was created by a
 @('defpkg') with identical set of imports.  That is, it is permissible to
 execute ``redundant'' @('defpkg') @(see command)s.  The redundancy test is
 based on the values of the two import forms (comparing them after sorting and
 removing duplicates), not on the forms themselves.</p>

 <p>Note that @('defpkg') performs evaluation in so-called @(see safe-mode),
 which can slow down evaluation significantly but checks @(see guard)s on
 @(see primitive)s.</p>

 <p>Finally, we explain why we require the package name to contain standard
 characters, none of which is lower case.  We have seen at least one
 implementation that handled lower-case package names incorrectly.  Since we
 see no need for lower-case characters in package names, which can lead to
 confusion anyhow (note for example that @('foo::bar') is a symbol whose @(tsee
 symbol-package-name) is @('\"FOO\"'), not @('\"foo\"')), we simply disallow
 them.  Since the notion of ``lower case'' is only well-specified in Common
 Lisp for standard characters, we restrict to these.</p>

 <p>NOTE: Also see @(see managing-acl2-packages) for contributed documentation
 on managing ACL2 packages.</p>")

(defxdoc defproxy
  :parents (events)
  :short "Define a non-executable @(':')@(tsee program)-mode function for
  attachment"
  :long "<p>This event is provided for those who want to experiment with @(tsee
 defattach) using @(':')@(tsee program) mode functions, and without proof
 obligations or constraints on cycles in the extended ancestors graph; see
 @(see defattach).  If you merely want to define a stub or a non-executable
 function, see @(see defstub) or see @(see defun-nx), respectively.</p>

 <p>See community book @('books/misc/defproxy-test.lisp') for an extended (but
 simple) example.</p>

 @({
  Example Forms:
  (defproxy subr1 (* *) => *)
  (defproxy add-hash (* * hashtable) => (mv * hashtable))

  General Form:
  (defproxy name args-sig => output-sig)
 })

 <p>where @('name') is a new function symbol and @('(name . args-sig) =>
 output-sig)') is a signature; see @(see signature).</p>

 <p>The macro @('defproxy') provides a convenient way to introduce a ``proxy'':
 a @(':program') mode function that can be given attachments for execution (see
 @(see defattach)), assuming that there is an active trust tag (see @(see
 defttag)).  Thus, a @('defproxy') call expands to a @(tsee defun) form with
 the following @(tsee xargs) @(tsee declare) form: @(':non-executable
 :program').  Note that @(tsee verify-termination) is not permitted for such a
 function.  However, it is permitted to put the proxy function into
 @(':')@(tsee logic) mode by use of an @(tsee encapsulate) event; indeed, this
 is the way to ``upgrade'' an attachment so that the normal checks are
 performed and no trust tag is necessary.</p>

 <p>In order to take advantage of a @(tsee defproxy) form, one provides a
 subsequent @('defattach') form to attach an executable function to the
 @('defproxy')-introduced function.  When @(':skip-checks t') is provided in a
 @(tsee defattach) form, the usual checks for @('defattach') @(see events) are
 skipped, including proof obligations and the check that the extended ancestor
 relation has no cycles (see @(see defattach)).  There must be an active trust
 tag (see @(see defttag)) in order to use @(':skip-checks t').  In that case
 the use of @(':skip-checks t') is permitted; but note that its use is in fact
 required if a @(':')@(tsee program) mode function is involved, and even if a
 @(':')@(tsee logic) mode function is involved that has not been @(see
 guard)-verified.</p>

 <p>The following log shows a simple use of defproxy.</p>

 @({
  ACL2 !>(defproxy foo-stub (*) => *)

  Summary
  Form:  ( DEFUN FOO-STUB ...)
  Rules: NIL
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
   FOO-STUB
  ACL2 !>(foo-stub '(3 4 5))

  ACL2 Error in TOP-LEVEL:  ACL2 cannot ev the call of undefined function
  FOO-STUB on argument list:

  ((3 4 5))

  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

  ACL2 !>(defun foo-impl (x)
           (declare (xargs :mode :program
                           :guard (or (consp x) (eq x nil))))
           (car x))

  Summary
  Form:  ( DEFUN FOO-IMPL ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FOO-IMPL
  ACL2 !>(defttag t)

  TTAG NOTE: Adding ttag :T from the top level loop.
   T
  ACL2 !>(defattach (foo-stub foo-impl) :skip-checks t)

  Summary
  Form:  ( DEFATTACH (FOO-STUB FOO-IMPL) ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   :ATTACHMENTS-RECORDED
  ACL2 !>(foo-stub '(3 4 5))
  3
  ACL2 !>
 })

 <p>One can replace this attachment with one that uses @(':')@(tsee logic) mode
 functions and does not skip checks.  The idea is to reintroduce the proxy
 function using an @(tsee encapsulate) form, which does not require
 redefinition (see @(see ld-redefinition-action)) to be enabled, and either to
 put the attachment into @(':')@(tsee logic) mode with the @(see guard)
 verified, as we do in the example below, or else to attach to a different
 @(see guard)-verified @(':')@(tsee logic) mode function.</p>

 @({
  ACL2 !>(defattach (foo-stub nil) :skip-checks t) ; remove attachment

  Summary
  Form:  ( DEFATTACH (FOO-STUB NIL) ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   :ATTACHMENTS-RECORDED
  ACL2 !>(encapsulate
          ((foo-stub (x) t :guard (true-listp x)))
          (local (defun foo-stub (x) (cdr x)))
          (defthm foo-stub-reduces-acl2-count
            (implies (consp x)
                     (< (acl2-count (foo-stub x))
                        (acl2-count x)))))

  [[ ... output omitted here ... ]]

  The following constraint is associated with the function FOO-STUB:

  (IMPLIES (CONSP X) (< (ACL2-COUNT (FOO-STUB X)) (ACL2-COUNT X)))

  Summary
  Form:  ( ENCAPSULATE ((FOO-STUB ...) ...) ...)
  Rules: NIL
  Warnings:  Non-rec
  Time:  0.02 seconds (prove: 0.01, print: 0.00, other: 0.01)
   T
  ACL2 !>(verify-termination foo-impl)

  Since FOO-IMPL is non-recursive, its admission is trivial.  We could
  deduce no constraints on the type of FOO-IMPL.

  Computing the guard conjecture for FOO-IMPL....

  The guard conjecture for FOO-IMPL is trivial to prove.  FOO-IMPL is
  compliant with Common Lisp.

  Summary
  Form:  ( DEFUN FOO-IMPL ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

  Summary
  Form:  ( MAKE-EVENT (VERIFY-TERMINATION-FN ...))
  Rules: NIL
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
   FOO-IMPL
  ACL2 !>(defttag nil) ; optional
   NIL
  ACL2 !>(defattach (foo-stub foo-impl))

  The guard proof obligation is

  (IMPLIES (TRUE-LISTP X)
           (OR (CONSP X) (EQ X NIL))).

  But we reduce the conjecture to T, by primitive type reasoning.

  Q.E.D.

  This concludes the guard proof.

  We now prove that the attachment satisfies the required constraint.
  The goal to prove is

  (IMPLIES (CONSP X)
           (< (ACL2-COUNT (FOO-IMPL X))
              (ACL2-COUNT X))).

  [[ ... output omitted here ... ]]

  Q.E.D.

  Summary
  Form:  ( DEFATTACH (FOO-STUB FOO-IMPL))
  Rules: ((:DEFINITION ACL2-COUNT)
          (:DEFINITION FOO-IMPL)
          (:ELIM CAR-CDR-ELIM)
          (:FAKE-RUNE-FOR-LINEAR NIL)
          (:FAKE-RUNE-FOR-TYPE-SET NIL)
          (:REWRITE CAR-CONS)
          (:REWRITE CDR-CONS)
          (:TYPE-PRESCRIPTION ACL2-COUNT))
  Time:  0.02 seconds (prove: 0.01, print: 0.01, other: 0.00)
   :ATTACHMENTS-RECORDED
  ACL2 !>
 })

 <p>We close with some remarks on the checking of @(see guard)s in the case
 that @(tsee defattach) has been called with keyword argument @(':skip-checks
 t').  We illustrate with examples, where we assume an attachment pair @('(f
 . g)') created by an event @('(defattach ... (f g) ... :skip-checks t ...)').
 A good model for the treatment of @(':skip-checks t') is dependent on whether
 @('f') was introduced with @('defproxy') or with @(tsee encapsulate): for
 @('defproxy'), the normal guard-related checks are treated as skipped, while
 for @(tsee encapsulate), they are assumed to hold.</p>

 <p>First suppose that @('f') was introduced using @('defproxy'), and consider
 the following example.</p>

 @({
  (defproxy f (*) => *)
  (defun g (x) (car x)) ; not guard-verified; implicit guard of t is too weak
  (defttag t) ; trust tag needed for :skip-checks t
  (defattach (f g) :skip-checks t)
 })

 <p>If we try to evaluate the form @('(f 3)') in ACL2, then the
 executable-counterpart of @('f') is invoked (see @(see evaluation)).  It calls
 the executable-counterpart of @('g'), which calls the executable-counterpart
 of @(tsee car), which in turn checks the @(see guard) of @(tsee car) and
 causes a guard violation error (unless we first turn off guard-checking; see
 @(see set-guard-checking)).</p>

 @({
  ACL2 !>(trace$ f g)
   ((F) (G))
  ACL2 !>(f 3)
  1> (ACL2_*1*_ACL2::F 3)
    2> (ACL2_*1*_ACL2::G 3)

  ACL2 Error in TOP-LEVEL:  The guard for the function call (CAR X),
  which is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments
  in the call (CAR 3).  To debug see :DOC print-gv, see :DOC trace, and
  see :DOC wet.  See :DOC set-guard-checking for information about suppressing
  this check with (set-guard-checking :none), as recommended for new
  users.

  ACL2 !>
 })

 <p>Little changes if we modify the example above by strengthening the guard of
 @('g').</p>

 @({
  (defproxy f (*) => *)
  (defun g (x)
    (declare (xargs :guard (consp x)))
    (car x))
  (defttag t) ; trust tag needed for :skip-checks t
  (defattach (f g) :skip-checks t)
 })

 <p>The result of evaluating @('(f 3)') is as before, except that this time the
 guard violation occurs at the time that @('g') is called.</p>

 @({
  ACL2 !>(trace$ f g)
   ((F) (G))
  ACL2 !>(f 3)
  1> (ACL2_*1*_ACL2::F 3)
    2> (ACL2_*1*_ACL2::G 3)

  ACL2 Error in TOP-LEVEL:  The guard for the function call (G X), which
  is (CONSP X), is violated by the arguments in the call (G 3).  To debug
  see :DOC print-gv, see :DOC trace, and see :DOC wet.  See :DOC set-
  guard-checking for information about suppressing this check with (set-
  guard-checking :none), as recommended for new users.

  ACL2 !>
 })

 <p>Now consider a slight variation of the example just above, in which @('f')
 is introduced using @(tsee encapsulate) instead of using @('defproxy').</p>

 @({
  (encapsulate ( ((f *) => *) )
               (local (defun f (x) x)))
  (defun g (x)
    (declare (xargs :guard (consp x)))
    (car x))
  (defttag t) ; trust tag needed for :skip-checks t
  (defattach (f g) :skip-checks t)
 })

 <p>Since @('f') was introduced by @(tsee encapsulate) instead of by
 @('defproxy'), ACL2 assumes that the usual guard properties hold.  In
 particular, it assumes that (informally speaking) the guard of @('f') implies
 the guard of @('g'); see @(see defattach) for details.  So in this case, ACL2
 proceeds under that assumption even though it's actually false, and the result
 is a raw Lisp error.</p>

 @({
  ACL2 !>(trace$ f g)
   ((F) (G))
  ACL2 !>(f 3)
  1> (ACL2_*1*_ACL2::F 3)
    2> (G 3)

  ***********************************************
  ************ ABORTING from raw Lisp ***********
  ********** (see :DOC raw-lisp-error) **********
  Error:  Attempt to take the car of 3 which is not listp.
  ***********************************************

  If you didn't cause an explicit interrupt (Control-C),
  then the root cause may be call of a :program mode
  function that has the wrong guard specified, or even no
  guard specified (i.e., an implicit guard of t).
  See :DOC guards.

  To enable breaks into the debugger (also see :DOC acl2-customization):
  (SET-DEBUGGER-ENABLE T)
  ACL2 !>
 })

 <p>If you replace @('g') by its definition in the first example of this
 series, i.e. with a guard (implicitly) of @('t'), you will see the same error,
 this time because the @(tsee defattach) event assumed that @('g') was
 guard-verified.</p>")

(defxdoc defrec
  :parents (events)
  :short "Introduce a record structure, like a @('struct') in C."

  :long "<p>The @('defrec') macro is built into ACL2 and is frequently used in
 the ACL2 sources to define basic kinds of structures.</p>

 <h3>Better Alternatives to Defrec</h3>

 <p>While @('defrec') may be a reasonable choice for writing @(see
 program)-mode code, most users would likely be better served by using one of
 the many, richer alternatives to @(see defrec) that are available in various
 books.  See for instance macros such as:</p>

 <ul>
 <li>The @(see std::defaggregate) macro from @(see std/util),</li>
 <li>The @(see defdata) macro,</li>
 <li>The @(see fty::defprod) macro from the @(see fty::fty) library, and</li>
 <li>The @('data-structures/structures') book.</li>
 </ul>

 <p>A major reason to favor these macros over @('defrec') is that they
 introduce the constructors and accessors for the structure as proper
 functions, rather than mere macros.  This is very helpful when you are trying
 to use ACL2 to reason about code that works with structures.  For instance, it
 means that your proof goals will involve terms like @('(employee->position
 x)') instead of @('(cdddr x)').</p>

 <p>Another reason is that @('defrec') does not support putting constraints on
 the fields of your structure.  For instance, you might want to have an
 @('employee') structure where the @('name') field is always a string.  You
 can't do this with @('defrec'), but any of the above macros support it.</p>

 <p>Some of the above macros also have other useful features, e.g., integration
 with @(see b*), support for @(see xdoc) documentation, and so forth.</p>

 <h3>Usage</h3>

 <p>A typical use of @('defrec') might look like this:</p>

 @({
     (defrec employee             ;; name of the structure
       (name salary . position)   ;; fields of the structure
       nil)                       ;; \"cheap\" flag
 })

 <p>This will result in the introduction of:</p>

 <ul>

 <li>A \"weak\" recognizer function, @('weak-employee-p'), which recognizes
 cons structures that have the right shape.  We call the recognizer <i>weak</i>
 because it doesn't impose any constraints on the fields, e.g., there is no
 requirement that the @('name') of an employee must be a string or that the
 @('salary') must be a number.</li>

 <li>A @(see make) macro that can be used like this:
     @({
        (make employee :name \"Jimmy\"
                       :salary 0
                       :position \"Unpaid Intern\")
     })</li>

 <li>A @(see change) macro that can be used like this:
     @({
         (let ((jimmy (make-employee :name \"Jimmy\" ...)))
           (change employee jimmy :salary 300000
                                  :position \"Vice President\"))
     })</li>

 <li>Suitable @(see access) macros that can be used like this:
     @({
         (let ((jimmy (make-employee :name \"Jimmy\" ...)))
           (access employee jimmy :name))
     })</li>

 </ul>")

(defxdoc defrefinement
  :parents (events)
  :short "Prove that @('equiv1') refines @('equiv2')"
  :long "@({
  Example:
  (defrefinement equiv1 equiv2)

  is an abbreviation for
  (defthm equiv1-refines-equiv2
    (implies (equiv1 x y) (equiv2 x y))
    :rule-classes (:refinement))
 })

 <p>See @(see refinement).</p>

 @({
  General Form:
  (defrefinement equiv1 equiv2
    :rule-classes rule-classes
    :instructions instructions
    :hints hints
    :otf-flg otf-flg
    :event-name event-name
    :doc doc)
 })

 <p>where @('equiv1') and @('equiv2') are known @(see equivalence) relations,
 @('event-name'), if supplied, is a symbol and all other arguments are as
 specified in the documentation for @(tsee defthm).  The @('defrefinement')
 macro expands into a call of @('defthm').  The name supplied is
 @('equiv1-refines-equiv2'), unless @('event-name') is supplied, in which case
 it is used as the name.  The term supplied states that @('equiv1') refines
 @('equiv2').  The rule-class @(':refinement') is added to the
 @('rule-classes') specified, if it is not already there.  All other arguments
 to the generated @('defthm') form are as specified by the other keyword
 arguments above.</p>")

(defxdoc defstobj
  :parents (events stobj)
  :short "Define a new single-threaded object"
  :long "<p>Note: Novices are advised to avoid @('defstobj'), perhaps instead
 using community books @(see std::defaggregate) or
 @('books/data-structures/structures.lisp').  At the least, consider using
 @('(')@(tsee set-verify-guards-eagerness)@(' 0)') to avoid @(see guard)
 verification.  On the other hand, after you learn to use @('defstobj'), see
 @(see defabsstobj) for another way to introduce single-threaded objects.</p>

 @({
  Example:
  (defconst *mem-size* 10) ; for use of *mem-size* just below
  (defstobj st
            (reg :type (array (unsigned-byte 31) (8))
                 :initially 0)
            (p-c :type (unsigned-byte 31)
                 :initially 555)
            halt                  ; = (halt :type t :initially nil)
            (mem :type (array (unsigned-byte 31) (*mem-size*))
                 :initially 0 :resizable t))

  General Form:
  (defstobj name
            (field1 :type type1 :initially val1 :resizable b1)
            ...
            (fieldk :type typek :initially valk :resizable bk)
            :renaming alist
            :inline flg
            :congruent-to old-stobj-name
            :non-memoizable nm-flg)
 })

 <p>where @('name') is a new symbol, each @('fieldi') is a symbol, each
 @('typei') is either a type-indicator (a @(tsee type-spec) or @(see stobj)
 name) or of the form @('(ARRAY type-indicator max)'), each @('vali') is an
 object satisfying @('typei'), and each @('bi') is @('t') or @('nil').  Each
 pair @(':initially vali') and @(':resizable bi') may be omitted; more on this
 below.  The @(':renaming alist') argument is optional and allows the user to
 override the default function names introduced by this event.  The @(':inline
 flg') Boolean argument is also optional and declares to ACL2 that the
 generated access and update functions for the stobj should be implemented as
 macros under the hood (which has the effect of inlining the function calls).
 The optional @(':congruent-to old-stobj-name') argument specifies an existing
 stobj with exactly the same structure, and is discussed below.  The optional
 @(':non-memoizable nm-flg') Boolean argument is ignored when @('nm-flg') is
 @('nil'); otherwise, it instructs ACL2 to lay down faster code for functions
 that return the new stobj but disallows @(see memoization) of any function
 that takes the new stobj as an argument.  We describe further restrictions on
 the @('fieldi'), @('typei'), @('vali'), and on @('alist') below.  We recommend
 that you read about single-threaded objects (stobjs) in ACL2 before
 proceeding; see @(see stobj).</p>

 <p>The effect of this event is to introduce a new single-threaded object
 (i.e., a ``@(see stobj)''), named @('name'), and the associated recognizers,
 creator, accessors, updaters, constants, and, for fields of @('ARRAY') type,
 length and resize functions.</p>

 <p><i>The Single-Threaded Object Introduced</i></p>

 <p>The @('defstobj') event effectively introduces a new global variable, named
 @('name'), which has as its initial logical value a list of @('k') elements,
 where @('k') is the number of ``field descriptors'' provided.  The elements
 are listed in the same order in which the field descriptors appear.  If the
 @(':type') of a field is @('(ARRAY type-indicator (max))') then @('max') is a
 non-negative integer or a symbol introduced by @(tsee defconst)) whose value
 is a non-negative integer, and the corresponding element of the stobj is
 initially of length specified by @('max').</p>

 <p>Whether the value @(':type') is of the form @('(ARRAY type-indicator
 (max))') or, otherwise, just @('type-indicator'), then @('type-indicator') is
 typically a type-spec; see @(see type-spec).  However, @('type-indicator') can
 also be the name of a stobj that was previously introduced (by @('defstobj')
 or @(tsee defabsstobj)).  We ignore this ``nested stobj'' case below; see
 @(see nested-stobjs) for a discussion of stobjs within stobjs.</p>

 <p>The keyword value @(':initially val') specifies the initial value of a
 field, except for the case of a @(':type') @('(ARRAY type-indicator (max))'),
 in which case @('val') is the initial value of the corresponding array.</p>

 <p>Note that the actual representation of the stobj in the underlying Lisp may
 be quite different; see @(see stobj-example-2).  For the moment we focus
 entirely on the logical aspects of the object.</p>

 <p>In addition, the @('defstobj') event introduces functions for recognizing
 and creating the stobj and for recognizing, accessing, and updating its
 fields.  For fields of @('ARRAY') type, length and resize functions are also
 introduced.  Constants are introduced that correspond to the accessor
 functions.</p>

 <p><i>Restrictions on the Field Descriptions in Defstobj</i></p>

 <p>Each field descriptor is of the form:</p>

 @({
  (fieldi :TYPE typei :INITIALLY vali)
 })

 <p>Note that the type and initial value are given in ``keyword argument''
 format and may be given in either order.  The @('typei') and @('vali')
 ``arguments'' are not evaluated.  If omitted, the type defaults to @('t')
 (unrestricted) and the initial value defaults to @('nil').</p>

 <p>Each @('typei') must be either a @(tsee type-spec) or else a list of the
 form @('(ARRAY type-spec (max))').  (Again, we are ignoring the case of nested
 stobjs, discussed elsewhere; see @(see nested-stobjs).)  The latter forms are
 said to be ``array types.''  Examples of legal @('typei') are:</p>

 @({
  (INTEGER 0 31)
  (SIGNED-BYTE 31)
  (ARRAY (SIGNED-BYTE 31) (16))
  (ARRAY (SIGNED-BYTE 31) (*c*)) ; where *c* has a non-negative integer value
 })

 <p>The @('typei') describes the objects which are expected to occupy the given
 field.  Those objects in @('fieldi') should satisfy @('typei').  We are more
 precise below about what we mean by ``expected.''  We first present the
 restrictions on @('typei') and @('vali').</p>

 <p>Non-Array Types</p>

 <p>When @('typei') is a @(tsee type-spec) it restricts the contents, @('x'),
 of @('fieldi') according to the ``meaning'' formula given in the table for
 @(tsee type-spec).  For example, the first @('typei') above restricts the
 field to be an integer between 0 and 31, inclusive.  The second restricts the
 field to be an integer between -2^30 and (2^30)-1, inclusive.</p>

 <p>The initial value, @('vali'), of a field description may be any ACL2 object
 but must satisfy @('typei').  Note that @('vali') is not a form to be
 evaluated but an object.  A form that evaluates to @('vali') could be written
 @(''vali'), but @('defstobj') does not expect you to write the quote mark.
 For example, the field description</p>

 @({
  (days-off :initially (saturday sunday))
 })

 <p>describes a field named @('days-off') whose initial value is the list
 consisting of the two symbols @('SATURDAY') and @('SUNDAY').  In particular,
 the initial value is NOT obtained by applying the function @('saturday') to
 the variable @('sunday')!  Had we written</p>

 @({
  (days-off :initially '(saturday sunday))
 })

 <p>it would be equivalent to writing</p>

 @({
  (days-off :initially (quote (saturday sunday)))
 })

 <p>which would initialize the field to a list of length two, whose first
 element is the symbol @('quote') and whose second element is a list containing
 the symbols @('saturday') and @('sunday').</p>

 <p>Array Types</p>

 <p>When @('typei') is of the form @('(ARRAY type-spec (max))'), the field is
 supposed to be a list of items, initially of length specified by @('max'),
 each of which satisfies the indicated @('type-spec').  @('Max') must be a
 non-negative integer or a defined constant evaluating to a non-negative
 integer. Thus, each of</p>

 @({
  (ARRAY (SIGNED-BYTE 31) (16))
  (ARRAY (SIGNED-BYTE 31) (*c*)) ; given previous event (defconst *c* 16)
 })

 <p>restricts the field to be a list of integers, initially of length 16, where
 each integer in the list is a @('(SIGNED-BYTE 31)').  We sometimes call such a
 list an ``array'' (because it is represented as an array in the underlying
 Common Lisp).  The elements of an array field are indexed by position,
 starting at 0.  Thus, the maximum legal index of an array field one less than
 is specified by @('max').  Note that the value of @('max') must be less than
 the Common Lisp constant @('array-dimension-limit'), and also (though this
 presumably follows) less than the Common Lisp constant
 @('array-total-size-limit').</p>

 <p>Note also that the @('ARRAY') type requires that the @('max') be enclosed
 in parentheses.  This makes ACL2's notation consistent with the Common Lisp
 convention of describing the (multi-)dimensionality of arrays.  But ACL2
 currently supports only single dimensional arrays in stobjs.</p>

 <p>For array fields, the initial value @('vali') must be an object satisfying
 the @(tsee type-spec) of the @('ARRAY') description.  The initial value of the
 field is a list of @('max') repetitions of @('vali').</p>

 <p>Array fields can be ``resized,'' that is, their lengths can be changed, if
 @(':resizable t') is supplied as shown in the example and General Form above.
 The new length must satisfy the same restriction as does @('max'), as
 described above.  Each array field in a @('defstobj') event gives rise to a
 length function, which gives the length of the field, and a resize function,
 which modifies the length of the field if @(':resizable t') was supplied with
 the field when the @('defstobj') was introduced and otherwise causes an error.
 If @(':resizable t') was supplied and the resize function specifies a new
 length @('k'), then: if @('k') is less than the existing array length, the
 array is shortened simply by dropping elements with index at least @('k');
 otherwise, the array is extended to length @('k') by mapping the new indices
 to the initial value (supplied by @(':initially'), else default @('nil')).</p>

 <p>Array resizing is relatively slow, so we recommend using it somewhat
 sparingly.</p>

 <p><i>The Default Function Names</i></p>

 <p>To recap, in</p>

 @({
  (defstobj name
            (field1 :type type1 :initially val1)
            ...
            (fieldk :type typek :initially valk)
            :renaming alist
            :doc doc-string
            :inline inline-flag)
 })

 <p>@('name') must be a new symbol, each @('fieldi') must be a symbol, each
 @('typei') must be a @(tsee type-spec) or @('(ARRAY type-spec (max))'), and
 each @('vali') must be an object satisfying @('typei').</p>

 <p>Roughly speaking, for each @('fieldi'), a @('defstobj') introduces a
 recognizer function, an accessor function, and an updater function.  The
 accessor function, for example, takes the stobj and returns the indicated
 component; the updater takes a new component value and the stobj and return a
 new stobj with the component replaced by the new value.  But that summary is
 inaccurate for array fields.</p>

 <p>The accessor function for an array field does not take the stobj and return
 the indicated component array, which is a list of length specified by
 @('max').  Instead, it takes an additional index argument and returns the
 indicated element of the array component.  Similarly, the updater function for
 an array field takes an index, a new value, and the stobj, and returns a new
 stobj with the indicated element replaced by the new value.</p>

 <p>These functions &mdash; the recognizer, accessor, and updater, and also
 length and resize functions in the case of array fields &mdash; have ``default
 names.''  The default names depend on the field name, @('fieldi'), and on
 whether the field is an array field or not.  For clarity, suppose @('fieldi')
 is named @('c'). The default names are shown below in calls, which also
 indicate the arities of the functions.  In the expressions, we use @('x') as
 the object to be recognized by field recognizers, @('i') as an array index,
 @('v') as the ``new value'' to be installed by an updater, and @('name') as
 the single-threaded object.</p>

 @({
                   non-array field        array field
  recognizer         (cP x)                (cP x)
  accessor           (c name)              (cI i name)
  updater            (UPDATE-c v name)     (UPDATE-cI i v name)
  length                                   (c-LENGTH name)
  resize                                   (RESIZE-c k name)
 })

 <p>Finally, a recognizer and a creator for the entire single-threaded object
 are introduced.  The creator returns the initial stobj, but may only be used
 in limited contexts; see @(see with-local-stobj).  If the single-threaded
 object is named @('name'), then the default names and arities are as shown
 below.</p>

 @({
  top recognizer     (nameP x)
  creator            (CREATE-name)
 })

 <p>For example, the event</p>

 @({
  (DEFSTOBJ $S
    (X :TYPE INTEGER :INITIALLY 0)
    (A :TYPE (ARRAY (INTEGER 0 9) (3)) :INITIALLY 9))
 })

 <p>introduces a stobj named @('$S').  The stobj has two fields, @('X') and
 @('A').  The @('A') field is an array.  The @('X') field contains an integer
 and is initially 0.  The @('A') field contains a list of integers, each
 between 0 and 9, inclusively.  Initially, each of the three elements of the
 @('A') field is 9.</p>

 <p>This event introduces the following sequence of definitions:</p>

 @({
  (DEFUN XP (X) ...)               ; recognizer for X field
  (DEFUN AP (X) ...)               ; recognizer of A field
  (DEFUN $SP ($S) ...)             ; top-level recognizer for stobj $S
  (DEFUN CREATE-$S () ...)         ; creator for stobj $S
  (DEFUN X ($S) ...)               ; accessor for X field
  (DEFUN UPDATE-X (V $S) ...)      ; updater for X field
  (DEFUN A-LENGTH ($S) ...)        ; length of A field
  (DEFUN RESIZE-A (K $S) ...)      ; resizer for A field
  (DEFUN AI (I $S) ...)            ; accessor for A field at index I
  (DEFUN UPDATE-AI (I V $S) ...)   ; updater for A field at index I
 })

 <p><i>Avoiding the Default Function Names</i></p>

 <p>If you do not like the default names listed above you may use the optional
 @(':renaming') alist to substitute names of your own choosing.  Each element
 of @('alist') should be of the form @('(fn1 fn2)'), where @('fn1') is a
 default name and @('fn2') is your choice for that name.</p>

 <p>For example</p>

 @({
  (DEFSTOBJ $S
    (X :TYPE INTEGER :INITIALLY 0)
    (A :TYPE (ARRAY (INTEGER 0 9) (3)) :INITIALLY 9)
    :renaming ((X XACCESSOR) (CREATE-$S MAKE$S)))
 })

 <p>introduces the following definitions</p>

 @({
  (DEFUN XP (X) ...)               ; recognizer for X field
  (DEFUN AP (X) ...)               ; recognizer of A field
  (DEFUN $SP ($S) ...)             ; top-level recognizer for stobj $S
  (DEFUN MAKE$S () ...)            ; creator for stobj $S
  (DEFUN XACCESSOR ($S) ...)       ; accessor for X field
  (DEFUN UPDATE-X (V $S) ...)      ; updater for X field
  (DEFUN A-LENGTH ($S) ...)        ; length of A field
  (DEFUN RESIZE-A (K $S) ...)      ; resizer for A field
  (DEFUN AI (I $S) ...)            ; accessor for A field at index I
  (DEFUN UPDATE-AI (I V $S) ...)   ; updater for A field at index I
 })

 <p>Note that even though the renaming alist substitutes ``@('XACCESSOR')'' for
 ``@('X')'' the updater for the @('X') field is still called ``@('UPDATE-X').''
 That is because the renaming is applied to the default function names, not to
 the field descriptors in the event.</p>

 <p>Use of the @(':renaming') alist may be necessary to avoid name clashes
 between the default names and and pre-existing function symbols.</p>

 <p><i>Constants</i></p>

 <p>@('Defstobj') events also introduce constant definitions (see @(see
 defconst)).  One constant is introduced for each accessor function by
 prefixing and suffixing a `@('*')' character on the function name.  The value
 of that constant is the position of the field being accessed.  For example, if
 the accessor functions are @('a'), @('b'), and @('c'), in that order, then the
 following constant definitions are introduced.</p>

 @({
  (defconst *a* 0)
  (defconst *b* 1)
  (defconst *c* 2)
 })

 <p>These constants are used for certain calls of @(tsee nth) and @(tsee
 update-nth) that are displayed to the user in proof output.  For example, for
 stobj @('st') with accessor functions @('a'), @('b'), and @('c'), in that
 order, the term @('(nth '2 st)') would be printed during a proof as @('(nth
 *c* st)').  Also see @(see term), in particular the discussion there of
 untranslated terms, and see @(see nth-aliases-table).</p>

 <p><i>Inspecting the Effects of a Defstobj</i></p>

 <p>Because the stobj functions are introduced as ``sub-events'' of the
 @('defstobj') the history commands @(':')@(tsee pe) and @(':')@(tsee pc) will
 not print the definitions of these functions but will print the superior
 @('defstobj') event.  To see the definitions of these functions use the
 history command @(':')@(tsee pcb!).</p>

 <p>To see an s-expression containing the definitions that constitute the raw
 Lisp implementation of the event, evaluate the form</p>

 @({
  (nth 4 (global-val 'cltl-command (w state)))
 })

 <p><i>immediately after</i> the @('defstobj') event has been processed.</p>

 <p>A @('defstobj') is considered redundant only if the name, field
 descriptors, renaming alist, and inline flag are identical to a previously
 executed @('defstobj').  Note that a redundant @('defstobj') does not reset
 the @(see stobj) fields to their initial values.</p>

 <p><i>Inlining and Performance</i></p>

 <p>The @(':inline') keyword argument controls whether or not accessor,
 updater, and length functions are inlined (as macros under the hood, in raw
 Lisp).  If @(':inline t') is provided then these are inlined; otherwise they
 are not.  The advantage of inlining is potentially better performance; there
 have been contrived examples, doing essentially nothing except accessing and
 updating array fields, where inlining reduced the time by a factor of 10 or
 more; and inlining has sped up realistic examples by a factor of at least 2.
 Inlining may get within a factor of 2 of C execution times for such contrived
 examples, and within a few percent of C execution times on realistic
 examples.</p>

 <p>A drawback to inlining is that redefinition may not work as expected, much
 as redefinition may not work as expected for macros: defined functions that
 call a macro, or inlined stobj function, will not see a subsequent
 redefinition of the macro or inlined function.  Another drawback to inlining
 is that because inlined functions are implemented as macros in raw Lisp,
 tracing (see @(see trace$)) will not show their calls.  These drawbacks are
 avoided by default, but the user who is not concerned about them is advised to
 specify @(':inline t').</p>

 <p><i>Specifying Congruent Stobjs</i></p>

 <p>Two stobjs are may be considered to be ``congruent'' if they have the same
 structure, that is, their @('defstobj') events are identical when ignoring
 field names.  In particular, every stobj is congruent to itself.  In order to
 tell ACL2 that a new stobj @('st2') is indeed to be considered as congruent to
 an existing stobj @('st1'), the @('defstobj') event introducing @('st2') is
 given the keyword argument @(':congruent-to st1').  Congruence is an
 equivalence relation: when you specify a new stobj to be congruent to an old
 one, you are also specifying that the new stobj is congruent to all other
 stobjs that are congruent to the old one.  Thus, continuing the example above,
 if you specify that @('st3') is @(':congruent-to st2'), then @('st1'),
 @('st2'), and @('st3') will all be congruent to each other.</p>

 <p>When two stobjs are congruent, ACL2 allows you to substitute one for
 another in a function call.  Any number of stobjs may be replaced with
 congruent stobjs in the call, provided no two get replaced with the same
 stobj.  The return values are correspondingly modified: if stobj @('st1') is
 replaced by @('st2') at an argument position, and if @('st1') is returned in
 the output @(see signature) of the function, then @('st2') is returned in
 place of @('st1').</p>

 <p>The following example illustrates congruent stobjs.  For more examples of
 how to take advantage of congruent stobjs, and also of how to misuse them, see
 community book @('books/misc/congruent-stobjs-test.lisp').</p>

 @({
  (defstobj st1 fld1)
  (defstobj st2 fld2 :congruent-to st1)
  (defstobj st3 fld3 :congruent-to st2) ; equivalently, :congruent-to st1
  (defun f (st1 st2 st3)
    (declare (xargs :stobjs (st1 st2 st3)))
    (list (fld2 st1) (fld3 st2) (fld1 st3)))
  (update-fld1 1 st1)
  (update-fld1 2 st2) ; notice use of update-fld1 on st2
  (update-fld1 3 st3) ; notice use of update-fld1 on st3
  (assert-event (equal (f st3 st2 st1) '(3 2 1)))
 })

 <p>The following example shows an error that occurs when stobj arguments are
 repeated, i.e., at least two stobj arguments (in this case, three) get
 replaced by the same stobj.</p>

 @({
  ACL2 !>(f st1 st1 st1)

  ACL2 Error in TOP-LEVEL:  The form ST1 is being used, as an argument
  to a call of F, where the single-threaded object ST2 was expected,
  even though these are congruent stobjs.  See :DOC defstobj, in particular
  the discussion of congruent stobjs.  Note:  this error occurred in
  the context (F ST1 ST1 ST1).

  ACL2 !>
 })")

(defxdoc defstub
  :parents (events)
  :short "Stub-out a function symbol"
  :long "@({
 Examples:
 ACL2 !>(defstub subr1 (* * state) => (mv * state))
 ACL2 !>(defstub add-hash (* * hashtable) => hashtable)

 General Form:
 (defstub name (args-sig) => output-sig)
 })

 <p>@('Name') must be a new function symbol, and @('args-sig') and
 @('output-sig') must be values such that @('((name . args-sig) =>
 output-sig)') would be a valid @(see signature).</p>

 <p>Note that while the @('defstub') syntax resembles a @(see signature), it is
 different; for example, @('name') occurs outside the parentheses containing
 @('args-sig'), and keyword arguments for specifying guards and formal argument
 names are not supported.  However, see the ``Old Style'' heading below for an
 alternative syntax which does allow you to name the formals.</p>

 <p>A @('defstub') macro call expands into an @(tsee encapsulate) event (see
 @(see encapsulate)).  Thus, no axioms are available about @('name') but it may
 be used wherever a function of the given signature is permitted.  Exception:
 if @('output-sig') is of the form @('(mv ...)'), then a @(':')@(tsee
 type-prescription) rule is introduced stating that @('name') returns a value
 satisfying @(tsee true-listp).</p>

 <p>Old Style:</p>

 @({
  Old Style General Form:
  (defstub name formals output)
 })

 <p>where @('name') is a new function symbol, @('formals') is its list of
 formal parameters, and @('output') is either a symbol (indicating that the
 function returns one result) or a term of the form @('(mv s1 ... sn)'), where
 each @('si') is a symbol (indicating that the function returns @('n')
 results).  Whether and where the symbol @(tsee state) occurs in @('formals')
 and @('output') indicates how the function handles @(see state).  It should be
 the case that @('(name formals output)') is in fact an old-style
 signature (see @(see signature)).</p>

 <p>Note that with the old style notation it is impossible to stub-out a
 function that uses any single-threaded object other than state.  The old style
 is preserved for compatibility with earlier versions of ACL2.</p>")

(defxdoc deftheory
  :parents (events theories)
  :short "Define a theory (to @(see enable) or @(see disable) a set of rules)"
  :long "@({
 Example:
 (deftheory interp-theory
            (set-difference-theories
              (universal-theory :here)
              (universal-theory 'interp-section)))

 General Forms:
 (deftheory name term)
 (deftheory name term :redundant-okp flg)
 })

 <p>where @('name') is a new symbolic name (see @(see name)), @('term') is a
 term that when evaluated will produce a theory (see @(see theories)), and
 @('flg') is expected to be Boolean.  Except for the variable @(tsee world),
 @('term') must contain no free variables.  @('Term') is evaluated with @(tsee
 world) bound to the current world (see @(see world)) and the resulting theory
 is then converted to a <i>runic theory</i> (see @(see theories)) and
 associated with @('name').  Henceforth, this runic theory is returned as the
 value of the theory expression @('(theory name)').</p>

 <p>The value returned is the length of the resulting theory.  For example, in
 the following, the theory associated with @(''FOO') has 54 @(see rune)s:</p>

 @({
  ACL2 !>(deftheory foo (union-theories '(binary-append)
                                        (theory 'minimal-theory)))

  Summary
  Form:  ( DEFTHEORY FOO ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   54
  ACL2 !>
 })

 <p>Note that the theory being defined depends on the context.  For example,
 consider the following (contrived) example book.</p>

 @({
    (in-package \"ACL2\")
    (defund foo (x) (consp x)) ; defund disables foo
    (local (in-theory (enable foo)))
    (deftheory my-theory (current-theory :here))
    (in-theory (disable foo))
    (defthm foo-property
      (implies (consp x)
               (foo x))
      :hints ((\"Goal\" :in-theory (enable my-theory))))
 })

 <p>At the time @('foo-property') is proved admissible during book
 certification (see @(see certify-book)), the @(tsee local) @(tsee in-theory)
 event has previously been evaluated, so the @(see definition) of @('foo') is
 @(see enable)d.  Thus, the @(':in-theory') hint on @('foo-property') will
 @(see enable) @('foo'), and the theorem proves.  HOWEVER, when the book is
 later included (see @(see include-book)), the @(tsee local) event is skipped,
 so the definition of @('foo') is @(see disable)d at the time the @(see theory)
 @('my-theory') is defined.  Hence, unlike the case for the admissibility pass
 of the book's certification, that theory does not include the definition of
 @('foo') when the book is included.</p>

 <p>There is, however, a way to ensure that a @(see theory) defined in a book
 is the same at @(tsee include-book) time as it was during the admissibility
 pass of the book's certification; see @(see deftheory-static).</p>

 <p>Note that a @('deftheory') event is never redundant unless
 @(':redundant-okp t') is specified, which supports a limited form of
 redundancy.  See @(see redundant-events).</p>")

(defxdoc deftheory-static
  :parents (events theories)
  :short "Define a `static' theory (to @(see enable) or @(see disable) a set of rules)"
  :long "<p>This macro provides a variant of @(tsee deftheory), such that the
 resulting theory is the same at @(tsee include-book) time as it was at @(tsee
 certify-book) time.</p>

 <p>We assume that the reader is familiar with @(see theories); see @(see
 deftheory).  We begin here by illustrating how @('deftheory-static') differs
 from @(tsee deftheory).  Suppose for example that the following events are the
 first two events in a book, where that book is certified in the initial ACL2
 @(see world) (see @(see ground-zero)).</p>

 @({
  (deftheory my-theory
    (current-theory :here))
  (deftheory-static my-static-theory
    (current-theory :here))
 })

 <p>Now suppose we include that book after executing the following event.</p>

 @({
  (in-theory (disable car-cons))
 })

 <p>Suppose that later we execute @('(in-theory (theory 'my-theory))').  Then
 the rule @('car-cons') will be disabled, because it was disabled at the time
 the expression @('(current-theory :here)') was evaluated when processing the
 @('deftheory') of @('my-theory') while including the book.  However, if we
 execute @('(in-theory (theory 'my-static-theory))'), then the rule
 @('car-cons') will be enabled, because the value of the theory
 @('my-static-theory') was saved at the time the book was certified.</p>

 @({
  General Form:
  (deftheory-static name term)
 })

 <p>The arguments are handled the same as for @(tsee deftheory).  Thus,
 @('name') is a new symbolic name (see @(see name)), and @('term') is a term
 that when evaluated will produce a theory (see @(see theories)).  Except for
 the variable @(tsee world), @('term') must contain no free variables.
 @('Term') is evaluated with @(tsee world) bound to the current world (see
 @(see world)) and the resulting theory is then converted to a <i>runic
 theory</i> (see @(see theories)) and associated with @('name').  Henceforth,
 this runic theory is returned as the value of the theory expression @('(theory
 name)').</p>

 <p>As for @(tsee deftheory), the value returned is the length of the resulting
 theory.</p>

 <p>We conclude with an optional discussion about the implementation of
 @('deftheory-static'), for those familiar with @(tsee make-event).  The
 following macroexpansion of the @('deftheory-static') form above shows how
 this works (see @(see trans1)).</p>

 @({
  ACL2 !>:trans1 (deftheory-static my-static-theory
                   (current-theory :here))
   (MAKE-EVENT (LET ((WORLD (W STATE)))
                    (LIST 'DEFTHEORY
                          'MY-STATIC-THEORY
                          (LIST 'QUOTE (CURRENT-THEORY :HERE)))))
  ACL2 !>
 })

 <p>The idea is that upon evaluation of this @('make-event') form, the first
 step is to evaluate the indicated @(tsee LET) expression to obtain a form
 @('(deftheory my-theory '(...))'), where ``@('(...)')'' is a list of all @(see
 rune)s in current theory.  If this form is in a book being certified, then the
 resulting @('deftheory') form is stored in the book's certificate, and is used
 when the book is included later.</p>")

(defxdoc defthm
  :parents (events)
  :short "Prove and name a theorem"
  :long "@({
  Examples:
  (defthm assoc-of-app
          (equal (app (app a b) c)
                 (app a (app b c))))
 })

 <p>The following nonsensical example illustrates all the optional arguments
 but is illegal because not all combinations are permitted.  See @(see hints)
 for a complete list of @(see hints).</p>

 @({
  (defthm main
          (implies (hyps x y z) (concl x y z))
         :rule-classes (:REWRITE :GENERALIZE)
         :instructions (induct prove promote (dive 1) x
                               (dive 2) = top (drop 2) prove)
         :hints ((\"Goal\"
                  :do-not '(generalize fertilize)
                  :in-theory (set-difference-theories
                               (current-theory :here)
                               '(assoc))
                  :induct (and (nth n a) (nth n b))
                  :use ((:instance assoc-of-append
                                   (x a) (y b) (z c))
                        (:functional-instance
                          (:instance p-f (x a) (y b))
                          (p consp)
                          (f assoc)))))
         :otf-flg t)

  General Form:
  (defthm name term
          :rule-classes rule-classes
          :instructions instructions
          :hints        hints
          :otf-flg      otf-flg)
 })

 <p>where @('name') is a new symbolic name (see @(see name)), @('term') is a
 term alleged to be a theorem, and @(tsee rule-classes), @(tsee instructions),
 @(tsee hints), and @(tsee otf-flg) are as described in their respective @(see
 documentation).  The keyword arguments above are all optional, however you may
 not supply both @(':')@(tsee instructions) and @(':')@(tsee hints), since one
 drives the interactive @(see proof-builder) and the other drives the theorem
 prover.  If @(':')@(tsee rule-classes) is not specified, the list
 @('(:rewrite)') is used; if you wish the theorem to generate no rules, specify
 @(':')@(tsee rule-classes) @('nil').</p>

 <p>When ACL2 processes a @('defthm') event, it first tries to prove the @(see
 term) using the indicated hints (see @(see hints)) or @(see instructions) (see
 @(see proof-builder)).  If it is successful, it stores the rules described by
 the rule-classes (see @(see rule-classes)), proving the necessary
 corollaries.</p>")

(defxdoc defthmd
  :parents (defthm events)
  :short "Prove and name a theorem and then disable it"
  :long "<p>Use @('defthmd') instead of @(tsee defthm) when you want to disable
 a theorem immediately after proving it.  This macro has been provided for
 users who prefer working in a mode where theorems are only enabled when
 explicitly directed by @(':')@(tsee in-theory).  Specifically, the form</p>

 @({
  (defthmd NAME TERM ...)
 })

 <p>expands to:</p>

 @({
  (progn
    (defthmd NAME TERM ...)
    (with-output
     :off summary
     (in-theory (disable NAME)))
    (value-triple '(:defthmd NAME))).
 })

 <p>Note that @('defthmd') commands are never redundant (see @(see
 redundant-events)).  Even if the @('defthm') event is redundant, then the
 @(tsee in-theory) event will still be executed.</p>

 <p>The summary for the @(tsee in-theory) event is suppressed.  See @(see
 defthm) for documentation of @('defthm').</p>")

(defxdoc defthy
  :parents (events theories deftheory)
  :short "Define a theory (to @(see enable) or @(see disable) a set of rules)"
  :long "<p>See @(see deftheory).  The @('defthy') macro is simply a convenient
 macro for @('deftheory') that supports a limited notion of redundancy; see
 @(see redundant-events).  Specifically: a call @('(defthy name expr)') expands
 to the corresponding event @('(deftheory name expr :redundant-okp t)').</p>")

(defxdoc defttag
  :parents (interfacing-tools events)
  :short "Introduce a trust tag (ttag)"
  :long "<p><b>Introduction</b>.  This event is intended for advanced users
 who, in essence, want to build extensions of ACL2.  The typical intended use
 is to create @(see books) that extend the functionality of ACL2 in ways not
 allowed without a so-called ``active trust tag''.  A trust tag thus represents
 a contract: The writer of such a book is guaranteeing that the book extends
 ACL2 in a ``correct'' way as defined by the writer of the book.  The writer of
 the book will often have a small section of the book in the scope of an active
 trust tag that can be inspected by potential users of that book:</p>

 @({
  <initial part of book, which does not use trust tags>
  (defttag :some-ttag) ; install :some-ttag as an active trust tag
  <various code that requires an active trust tag>
  (defttag nil)        ; remove active trust tag
  <final part of book, which does not use trust tags>
 })

 <p>Why might trust tags be needed?  The evaluation of certain functions can
 introduce bugs and even unsoundness, but can be useful in restricted ways that
 avoid such issues.  For example, @(tsee sys-call) can be used in an unsafe
 way, for example to overwrite files, or worse; see @(see sys-call) for a
 frightening example from Bob Boyer.  The following example shows that the
 function @(tsee sys-call) is restricted by default, but can be called after
 installing an active trust tag.</p>

 @({
  ACL2 !>(sys-call \"pwd\" nil)

  ACL2 Error in TOP-LEVEL:  The SYS-CALL function cannot be called unless
  a trust tag is in effect.  See :DOC defttag.

  ACL2 !>(defttag t) ; Install :T as an active trust tag.

  TTAG NOTE: Adding ttag :T from the top level loop.
   T
  ACL2 !>(sys-call \"pwd\" nil) ; print the current directory and return NIL
  /u/kaufmann
  NIL
  ACL2 !>(defttag nil) ; Remove the active trust tag (using value NIL).
   NIL
  ACL2 !>(sys-call \"pwd\" nil) ; Now we get the error again:

  ACL2 Error in TOP-LEVEL:  The SYS-CALL function cannot be called unless
  a trust tag is in effect.  See :DOC defttag.

  ACL2 !>
 })

 <p>Of course, using @(tsee sys-call) with the Linux command @('pwd') is not
 likely to cause any soundness problems!  So suppose we want to create a
 function that prints the working directory.  We might put the following @(see
 events) into a book that is to be certified.</p>

 @({
  (in-package \"ACL2\")
  (defttag :pwd-ttag)
  (defun print-working-dir ()
    (declare (xargs :mode :program))
    (sys-call \"pwd\" nil))
  (defttag nil) ; optional (books end with this implicitly)
 })

 <p>We can certify this book with a specification that @(':pwd-ttag') is a
 legal trust tag:</p>

 @({
  (certify-book \"pwd\" 0 t :ttags (:pwd-ttag))
 })

 <p>One can now use this book by executing @(tsee include-book) with keyword
 parameter @(':ttags (:pwd-ttag)') and then calling function
 @('print-working-dir'):</p>

 @({
  (include-book \"pwd\" :ttags (:pwd-ttag))
  (print-working-dir) ; working directory is printed to terminal
 })

 <p><b>Detailed documentation.</b></p>

 @({
  General Form:
  (defttag tag-name)
 })

 <p>where @('tag-name') is a symbol.</p>

 <p>Note however that if @('tag-name') is not @('nil'), then it is converted to
 a ``corresponding @(see keyword)'': a symbol in the @('\"KEYWORD\"') package
 with the same @(tsee symbol-name) as @('tag-name').  Thus, for example,
 @('(defttag foo)') is equivalent to @('(defttag :foo)').  Moreover, a
 non-@('nil') symbol with a @(tsee symbol-name) of @('\"NIL\"') is illegal for
 trust tags; thus, for example, @('(defttag :nil)') is illegal.</p>

 <p>This event introduces or removes a so-called active trust tag (or ``ttag'',
 pronounced ``tee tag'').  An active ttag is a @(see keyword) symbol that is
 associated with potentially unsafe evaluation.  For example, calls of @(tsee
 sys-call) are illegal unless there is an active trust tag.  An active trust
 tag can be installed using a @('defttag') event.  If one introduces an active
 ttag and then writes definitions with calls @(tsee sys-call), presumably in a
 defensibly ``safe'' way, then responsibility for those calls is attributed to
 that ttag.  This attribution (or blame!) is at the level of @(see books); a
 book's @(see certificate) contains a list of ttags that are active in that
 book, or in a book that is included (possibly @(see local)ly), or in a book
 included in a book that is included (either inclusion being potentially @(see
 local)), and so on.  We explain all this in more detail below.</p>

 <p>@('(Defttag :tag-name)') is essentially equivalent to</p>

 @({
  (table acl2-defaults-table :ttag :tag-name)
 })

 <p>and hence is @(tsee local) to any @(see books) and @(tsee encapsulate)
 @(see events) in which it occurs; see @(see acl2-defaults-table).  We say more
 about the scope of @('defttag') forms below.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless executes the above @(tsee table) event and hence changes the ACL2
 logical @(see world), and is so recorded.  Although no event summary is
 printed, it is important to note that the ``TTAG NOTE'', discussed below, is
 always printed for a non-nil @(':tag-name') (unless deferred; see @(see
 set-deferred-ttag-notes)).</p>

 <p><b>Active ttags.</b> Suppose @('tag-name') is a non-@('nil') symbol.  Then
 @('(defttag :tag-name)') sets @(':tag-name') to be the (unique) ``active
 ttag.''  There must be an active ttag in order for there to be any mention of
 certain function and macro symbols, including @(tsee sys-call); evaluate the
 form @('(strip-cars *ttag-fns-and-macros*)') to see the full list of such
 symbols.  On the other hand, @('(defttag nil)') removes the active ttag, if
 any; there is then no active ttag.  The scope of a @('defttag') form in a book
 being certified or included is limited to subsequent forms in the same book
 before the next @('defttag') (if any) in that book.  Similarly, if a
 @('defttag') form is evaluated in the top-level loop, then its effect is
 limited to subsequent forms in the top-level loop before the next @('defttag')
 in the top-level loop (if any).  Moreover, @(tsee certify-book) is illegal
 when a ttag is active; of course, in such a circumstance one can execute
 @('(defttag nil)') in order to allow book certification.</p>

 <p><b>Ttag notes and the ``certifier.''</b> When a @('defttag') is executed
 with an argument other than @('nil'), output is printed, starting on a fresh
 line with: @('TTAG NOTE').  For example:</p>

 @({
  ACL2 !>(defttag :foo)

  TTAG NOTE: Adding ttag :FOO from the top level loop.
   :FOO
  ACL2 !>
 })

 <p>If the @('defttag') occurs in an included book, the message looks like
 this.</p>

 @({
  TTAG NOTE (for included book): Adding ttag :FOO from file /u/smith/acl2/my-book.lisp.
 })

 <p>The ``@('TTAG NOTE')'' message is always printed on a single line.  The
 intention is that one can search the standard output for all such notes in
 order to find all <i>defttag</i> events.  In a sense, <i>defttag</i> events
 can allow you to define your own system on top of ACL2 (for example, see @(see
 progn!)).  So in order for someone else (who we might call the ``certifier'')
 to be confident that your collection of @(see books) is meaningful, that
 certifier should certify all the user-supplied books from scratch and check
 either that no @(':ttags') were supplied to @(tsee certify-book), or else look
 for every @('TTAG NOTE') in the standard output in order to locate all
 @('defttag') @(see events) with non-@('nil') tag name.  In this way, the
 certifier can in principle decide whether to be satisfied that those
 @('defttag') events did not allow inappropriate forms in the user-supplied
 books.</p>

 <p>In order to eliminate much of the output from @('TTAG NOTE')s, see @(see
 set-deferred-ttag-notes).  Note however that the resulting security is
 somewhat less; therefore, a @('TTAG NOTE') is printed when invoking
 @('set-deferred-ttag-notes') to defer printing of ttag notes.</p>

 <p><b>Allowed ttags when certifying and including books.</b> A @('defttag')
 form may not be evaluated unless its argument is a so-called ``allowed'' ttag.
 All ttags are allowed in the interactive top-level loop.  However, during
 @(tsee certify-book) and @(tsee include-book), the set of allowed ttags is
 restricted according to the @(':ttags') keyword argument.  If this argument is
 omitted then no ttag is allowed, so a @('defttag') call will fail during book
 certification or inclusion in this case.  This restriction applies even to
 @('defttag') forms already evaluated in the so-called certification @(see
 world) at the time @(tsee certify-book) is called.  But note that @('(defttag
 nil)') is always legal.</p>

 <p>A @(':ttags') argument of @(tsee certify-book) and @(tsee include-book) can
 have value @(':all'), indicating that every ttag is allowed, i.e., no
 restriction is being placed on the arguments, just as in the interactive
 top-level loop.  In the case of @('include-book'), an omitted @(':ttags')
 argument or an argument of @(':default') is treated as @(':all'), except that
 warnings will occur when the book's @(see certificate) includes ttags; but for
 @('certify-book'), an omitted @('ttags') argument is treated as @('nil').
 Otherwise, if the @(':ttags') argument is supplied but not @(':all'), then its
 value is a true list of ttag specifications, each having one of the following
 forms, where @('sym') is a non-@('nil') symbol which is treated as the
 corresponding @(see keyword).</p>

 <blockquote>

 <p>(1) @(':sym')</p>

 <p>(2) @('(:sym)')</p>

 <p>(3) @('(:sym x1 x2 ... xk)'), where k &gt; 0 and each @('xi') is a string,
 except that one @('xi') may be @('nil').</p></blockquote>

 <p>In Case (1), @('(defttag :sym)') is allowed to occur in at most one book or
 else in the top-level loop (i.e., the certification world for a book under
 certification or a book being included).  Case (2) allows @('(defttag :sym)')
 to occur in an unlimited number of books.  For case (3) the @('xi') specify
 where @('(defttag :sym)') may occur, as follows.  The case that @('xi') is
 @('nil') refers to the top-level loop, while all other @('xi') are filenames,
 where the @('\".lisp\"') extension is optional and relative pathnames are
 considered to be relative to the connected book directory (see @(see cbd)).
 Note that the restrictions on @('(defttag :sym)') apply equally to any
 equivalent for based on the notion of ``corresponding keyword'' discussed
 above, e.g., @('(defttag acl2::sym)').</p>

 <p>An error message, as shown below, illustrates how ACL2 enforces the notion
 of allowed ttags.  Suppose that you call @(tsee certify-book) with argument
 @(':ttags (:foo)'), where you have already executed @('(defttag :foo)') in the
 certification world (i.e., before calling @(tsee certify-book)).  Then ACL2
 immediately associates the ttag @(':foo') with @('nil'), where again, @('nil')
 refers to the top-level loop.  If ACL2 then encounters @('(defttag foo)')
 inside that book, you will get the following error (using the full book name
 for the book, as shown):</p>

 @({
  ACL2 Error in ( TABLE ACL2-DEFAULTS-TABLE ...):  The ttag :FOO associated
  with file /u/smith/work/my-book.lisp is not among the set of ttags permitted
  in the current context, specified as follows:
    ((:FOO NIL)).
  See :DOC defttag.
 })

 <p>In general the structure displayed by the error message, which is @('((:FOO
 NIL))') in this case, represents the currently allowed ttags with elements as
 discussed in (1) through (3) above.  In this case, that list's unique element
 is @('(:FOO NIL)'), meaning that ttag @(':FOO') is only allowed at the top
 level (as represented by @('NIL')).</p>

 <p><b>Associating ttags with books and with the top-level loop.</b> When a
 book is certified, each form @('(defttag tag)') that is encountered for
 non-@('nil') @('tag') in that book or an included book is recorded in the
 generated @(see certificate), which associates the keyword corresponding to
 @('tag') with the @(see full-book-name) of the book containing that
 @('defttag').  If such a @('defttag') form is encountered outside a book, hence
 in the @(see portcullis) of the book being certified or one of its included
 books, then that keyword is associated with @('nil') in the generated @(see
 certificate).  Note that the notion of ``included book'' here applies to the
 recursive notion of a book either included directly in the book being
 certified or else included in such a book, where we account even for @(see
 local)ly included books.</p>

 <p>For examples of ways to take advantage of ttags, see @(see hacker), @(see
 include-raw), @(see quicklisp), and more generally @(see interfacing-tools).
 See also @(see ttags-seen), @(see progn!), @(see remove-untouchable), @(see
 set-raw-mode), and @(see sys-call).</p>")

(defxdoc defun
  :parents (events programming)
  :short "Define a function symbol"
  :long "@({
  Examples:
  (defun app (x y)
    (if (consp x)
        (cons (car x) (app (cdr x) y))
        y))

  (defun fact (n)
    (declare (xargs :guard (and (integerp n)
                                (>= n 0))))
    (if (zp n)
        1
        (* n (fact (1- n)))))

  General Form:
  (defun fn (var1 ... varn) doc-string dcl ... dcl body),
 })

 <p>where @('fn') is the symbol you wish to define and is a new symbolic name
 (see @(see name)), @('(var1 ... varn)') is its list of formal parameters (see
 @(see name)), and @('body') is its body.  The definitional axiom is logically
 admissible provided certain restrictions are met.  These are sketched
 below.</p>

 <p>Note that ACL2 does not support the use of @('lambda-list') keywords (such
 as @('&optional')) in the formals list of functions.  We do support some such
 keywords in macros and often you can achieve the desired syntax by defining a
 macro in addition to the general version of your function.  See @(see
 defmacro).  @('Doc-string'), if non-@('nil'), is an optional string that can
 provide documentation but is essentially ignored by ACL2.</p>

 <p>The <i>declarations</i> (see @(see declare)), @('dcl'), are also optional.
 If more than one @('dcl') form appears, they are effectively grouped together
 as one.  Perhaps the most commonly used ACL2 specific declaration is of the
 form @('(declare (xargs :guard g :measure m))').  This declaration in the
 @('defun') of some function @('fn') has the effect of making the ``@(see
 guard)'' for @('fn') be the term @('g') and the ``measure'' be the term
 @('m').  The notion of ``measure'' is crucial to ACL2's definitional
 principle.  The notion of ``guard'' is not, and is discussed elsewhere; see
 @(see verify-guards) and see @(see set-verify-guards-eagerness).  Note that a
 @(':measure') is not allowed for a non-recursive definition unless it is part
 of a @(tsee mutual-recursion) (exception: a measure of @('nil') is treated as
 though the @('measure') was omitted); moreover, if a @(':measure') is
 supplied, then it must be a legal term.  Apart from these restrictions, the
 @(':measure') is ignored in @(':')@(tsee program) mode; see @(see
 defun-mode).</p>

 <p>We now briefly discuss the ACL2 definitional principle, using the following
 definition form which is offered as a more or less generic example.</p>

 @({
  (defun fn (x y)
    (declare (xargs :guard (g x y)
                    :measure (m x y)))
    (if (test x y)
        (stop x y)
      (step (fn (d x) y))))
 })

 <p>Note that in our generic example, @('fn') has just two arguments, @('x')
 and @('y'), the @(see guard) and measure terms involve both of them, and the
 body is a simple case split on @('(test x y)') leading to a ``non-recursive''
 branch, @('(stop x y)'), and a ``recursive'' branch.  In the recursive branch,
 @('fn') is called after ``decrementing'' @('x') to @('(d x)') and some step
 function is applied to the result.  Of course, this generic example is quite
 specific in form but is intended to illustrate the more general case.</p>

 <p>Provided this definition is admissible under the logic, as outlined below,
 it adds the following axiom to the logic.</p>

 @({
  Defining Axiom:
  (fn x y)
    =
  (if (test x y)
      (stop x y)
    (step (fn (d x) y)))
 })

 <p>Note that the @(see guard) of @('fn') has no bearing on this logical
 axiom.</p>

 <p>This defining axiom is actually implemented in the ACL2 system by a
 @(':')@(tsee definition) rule, namely</p>

 @({
  (equal (fn x y)
         (if (test a b)
             (stop a b)
           (step (fn (d a) b)))).
 })

 <p>See @(see definition) for a discussion of how definition rules are applied.
 Roughly speaking, the rule causes certain instances of @('(fn x y)') to be
 replaced by the corresponding instances of the body above.  This is called
 ``opening up'' @('(fn x y)').  The instances of @('(fn x y)') opened are
 chosen primarily by heuristics which determine that the recursive calls of
 @('fn') in the opened body (after simplification) are more desirable than the
 unopened call of @('fn').</p>

 <p>This discussion has assumed that the definition of @('fn') was admissible.
 Exactly what does that mean?  First, @('fn') must be a previously
 unaxiomatized function symbol (however, see @(see ld-redefinition-action)).
 Second, the formal parameters must be distinct variable names.  Third, the
 @(see guard), measure, and body should all be terms and should mention no free
 variables except the formal parameters.  Thus, for example, body may not
 contain references to ``global'' or ``special'' variables; ACL2 constants or
 additional formals should be used instead.</p>

 <p>The final conditions on admissibility concern the termination of the
 recursion.  Roughly put, all applications of @('fn') must terminate.  In
 particular, there must exist a binary relation, @('rel'), and some unary
 predicate @('mp') such that @('rel') is well-founded on objects satisfying
 @('mp'), the measure term @('m') must always produce something satisfying
 @('mp'), and the measure term must decrease according to @('rel') in each
 recursive call, under the hypothesis that all the tests governing the call are
 satisfied.  By the meaning of well-foundedness, we know there are no
 infinitely descending chains of successively @('rel')-smaller @('mp')-objects.
 Thus, the recursion must terminate.</p>

 <p>The only primitive well-founded relation in ACL2 is @(tsee o<) (see @(see
 o<)), which is known to be well-founded on the @(tsee o-p)s (see @(see o-p)).
 For the proof of well-foundedness, see @(see proof-of-well-foundedness).
 However it is possible to add new well-founded relations.  For details, see
 @(see well-founded-relation).  We discuss later how to specify which
 well-founded relation is selected by @('defun') and in the present discussion
 we assume, without loss of generality, that it is @(tsee o<) on the @(tsee
 o-p)s.</p>

 <p>For example, for our generic definition of @('fn') above, with measure term
 @('(m x y)'), two theorems must be proved.  The first establishes that @('m')
 produces an ordinal:</p>

 @({
  (o-p (m x y)).
 })

 <p>The second shows that @('m') decreases in the (only) recursive call of
 @('fn'):</p>

 @({
  (implies (not (test x y))
           (o< (m (d x) y) (m x y))).
 })

 <p>Observe that in the latter formula we must show that the ``@('m')-size'' of
 @('(d x)') and @('y') is ``smaller than'' the @('m')-size of @('x') and
 @('y'), provided the test, @('(test x y)'), in the body fails, thus leading to
 the recursive call @('(fn (d x) y)').</p>

 <p>See @(see o<) for a discussion of this notion of ``smaller than.''  It
 should be noted that the most commonly used ordinals are the natural numbers
 and that on natural numbers, @(tsee o<) is just the familiar ``less than''
 relation (@(tsee <)).  Thus, it is very common to use a measure @('m') that
 returns a nonnegative integer, for then @('(o-p (m x y))') becomes a simple
 conjecture about the type of @('m') and the second formula above becomes a
 conjecture about the less-than relationship of nonnegative integer
 arithmetic.</p>

 <p>The most commonly used measure function is @(tsee acl2-count), which
 computes a nonnegative integer size for all ACL2 objects.  See @(see
 acl2-count).</p>

 <p>Probably the most common recursive scheme in Lisp @(see programming) is
 when some formal is supposed to be a list and in the recursive call it is
 replaced by its @(tsee cdr).  For example, @('(test x y)') might be simply
 @('(atom x)') and @('(d x)') might be @('(cdr x)').  In that case,
 @('(acl2-count x)') is a suitable measure because the @(tsee acl2-count) of a
 @(tsee cons) is strictly larger than the @(tsee acl2-count)s of its @(tsee
 car) and @(tsee cdr).  Thus, ``recursion by @(tsee car)'' and ``recursion by
 @(tsee cdr)'' are trivially admitted if @(tsee acl2-count) is used as the
 measure and the definition protects every recursive call by a test insuring
 that the decremented argument is a @(tsee consp).  Similarly, ``recursion by
 @(tsee 1-)'' in which a positive integer formal is decremented by one in
 recursion, is also trivially admissible.  See @(see built-in-clause) to extend
 the class of trivially admissible recursive schemes.</p>

 <p>We now turn to the question of which well-founded relation @('defun') uses.
 It should first be observed that @('defun') must actually select both a
 relation (e.g., @(tsee o<)) and a domain predicate (e.g., @(tsee o-p)) on
 which that relation is known to be well-founded.  But, as noted elsewhere (see
 @(see well-founded-relation-rule)), every known well-founded relation has a
 unique domain predicate associated with it and so it suffices to identify
 simply the relation here.</p>

 <p>The @(tsee xargs) field of a @(tsee declare) permits the explicit
 specification of any known well-founded relation with the keyword
 @(':well-founded-relation').  An example is given below.  If the @(tsee xargs)
 for a @('defun') specifies a well-founded relation, that relation and its
 associated domain predicate are used in generating the termination conditions
 for the definition.</p>

 <p>If no @(':well-founded-relation') is specified, @('defun') uses the
 @(':well-founded-relation') specified in the @(tsee acl2-defaults-table).  See
 @(see set-well-founded-relation) to see how to set the default well-founded
 relation (and, implicitly, its domain predicate).  The initial default
 well-founded relation is @(tsee o<) (with domain predicate @(tsee o-p)).</p>

 <p>This completes the brief sketch of the ACL2 definitional principle.
 Optionally, see @(see rulers) for a more detailed discussion of the
 termination analysis and resulting proof obligations for admissibility, as
 well as a discussion of the relation to how ACL2 stores induction schemes.</p>

 <p>On very rare occasions ACL2 will seem to \"hang\" when processing a
 definition, especially if there are many subexpressions of the body whose
 function symbol is @(tsee if) (or which macroexpand to such an expression).
 In those cases you may wish to supply the following to @(tsee xargs):
 @(':normalize nil').  This is an advanced feature that turns off certain
 simplification of @(see definition) bodies and @(see guard)s; @(see
 normalize).</p>

 <p>When a @('defun') form is submitted, ACL2 sometimes computes and stores a
 @(see type-prescription) rule for the function.  See @(see
 type-prescription-debugging) for relevant discussion.</p>

 <p>The following example illustrates all of the available declarations and
 most hint keywords, but is completely nonsensical.  For documentation, see
 @(see xargs) and see @(see hints).</p>

 @({
  (defun example (x y z a b c i j)
    (declare (ignore a b c)
             (type integer i j)
             (xargs :guard (symbolp x)
                    :measure (- i j)
                    :ruler-extenders :basic
                    :well-founded-relation my-wfr
                    :hints ((\"Goal\"
                             :do-not-induct t
                             :do-not '(generalize fertilize)
                             :expand ((assoc x a) (member y z))
                             :restrict ((<-trans ((x x) (y (foo x)))))
                             :hands-off (length binary-append)
                             :in-theory (set-difference-theories
                                          (current-theory :here)
                                          '(assoc))
                             :induct (and (nth n a) (nth n b))
                             :use ((:instance assoc-of-append
                                              (x a) (y b) (z c))
                                   (:functional-instance
                                     (:instance p-f (x a) (y b))
                                     (p consp)
                                     (f assoc)))))
                    :guard-hints ((\"Subgoal *1/3'\"
                                   :use ((:instance assoc-of-append
                                                    (x a) (y b) (z c)))))
                    :mode :logic
                    :normalize nil
                    :verify-guards nil
                    :non-executable t
                    :otf-flg t))
    (example-body x y z i j))
 })")

(defxdoc defun-inline
  :parents (defun events)
  :short "Define a potentially inlined function symbol and associated macro"
  :long "<p>You may be able to improve performance by replacing an event
 @('(defun f ...)') with a corresponding event @('(defun-inline f ...)'), in
 order to encourage the host Lisp compiler to inline calls of @('f').</p>

 @({
  Example Form:
  (defun-inline lng (x)
    (declare (xargs :guard (true-listp x)))
    (if (endp x) 0 (1+ (lng (cdr x)))))

  General Form:
  (defun-inline fn (var1 ... varn) doc-string dcl ... dcl body)
 })

 <p>satisfying the same requirements as in the General Form for @(tsee defun).
 The effect is to define a macro @('fn') and a function @('fn$inline') (i.e., a
 symbol in the same package as @('fn') but whose @(tsee symbol-name) has the
 suffix @('\"$INLINE\"'), such that each call of @('fn') expands to a call of
 the function symbol @('fn$inline') on the same arguments.  Moreover, @(tsee
 table) @(see events) are generated that allow the use of @('fn') in @(see
 theory) expressions to represent @('fn$inline') and that cause any
 untranslated (user-level) call of @('fn$inline') to be printed as the
 corresponding call of @('fn').  @('Doc-string'), if non-@('nil'), is an
 optional string that can provide documentation but is essentially ignored by
 ACL2.</p>

 <p>A form @('(defun-inline f ...)') actually defines a function named
 @('f$inline') and a corresponding macro named @('f') whose calls expand to
 calls of @('f$inline'), while providing the illusion that there is just the
 ``function'' @('f').  For example, the Example Form above macroexpands in one
 step to the following form.</p>

 @({
  (progn (defmacro lng (non-stobj-var0)
           (list 'lng$inline non-stobj-var0))
         (add-macro-fn lng lng$inline)
         (defun lng$inline (x)
           (declare (xargs :guard (true-listp x)))
           (if (endp x) 0 (1+ (lng (cdr x))))))
 })

 <p>Note that the above call of @(tsee add-macro-fn) generates the
 aforementioned two table events (see @(see add-macro-fn)), which provide the
 illusion that we are just defining a function @('lng'), as you can see in the
 following log: @('lng') appears rather than @('lng$inline').</p>

 @({
  ACL2 !>(set-gag-mode nil)
  <state>
  ACL2 !>(thm (equal (lng (append x y))
                     (+ (lng x) (lng y)))
              :hints ((\"Goal\" :in-theory (enable lng))))

  [.. output omitted ..]

  Subgoal *1/2
  (IMPLIES (AND (NOT (ENDP X))
                (EQUAL (LNG (APPEND (CDR X) Y))
                       (+ (LNG (CDR X)) (LNG Y))))
           (EQUAL (LNG (APPEND X Y))
                  (+ (LNG X) (LNG Y)))).

  [.. output omitted ..]
 })

 <p>Under the hood, ACL2 arranges that every function symbol with suffix
 @('\"$INLINE\"') is presented to the compiler as one whose calls we would
 prefer to inline.  Technically: the Common Lisp form @('(declaim (inline
 f$inline))') is generated for a function symbol @('f$inline') before that
 symbol's definition is submitted.  However, the Common Lisp spec explicitly
 avoids requiring that the compiler respect this @('declaim') form.
 Fortunately, Common Lisp implementations often do respect it.</p>

 <p>Also see @(see defund-inline), see @(see defun-notinline), and see @(see
 defund-notinline).</p>

 <p><i>Remarks</i>.</p>

 <p>(1) None of these macros (including @('defun-inline')) is supported for use
 inside a @(tsee mutual-recursion).</p>

 <p>(2) Every function symbol defined in ACL2 whose @(tsee symbol-name) has the
 suffix @('\"$INLINE\"') is proclaimed to be inline; similarly for
 @('\"$NOTINLINE\"') and notinline.  These restrictions are explained in a
 comment in the ACL2 source definition of macro @('defun-inline').</p>

 <p>(3) No special treatment for inlining (or notinlining) is given for
 function symbols locally defined by @(tsee flet), with two exceptions: when
 explicitly declared @('inline') or @('notinline') by the @('flet') form, and
 for symbols discussed in (1) and (2) above that, at some point in the current
 ACL2 session, were defined as function symbols in ACL2 (even if not currently
 defined because of undoing or being @(see local)).</p>

 <p>(4) The function symbol actually being defined by @('(defun-inline foo
 ...)')  is @('foo$inline').  As mentioned above, one can be oblivious to this
 fact when writing @(see theory) expressions or perusing prover output.
 However, for other purposes (for example, @(tsee verify-guards) and @(tsee
 defabsstobj) @(':exports')) you will need to supply the name of the function
 symbol rather than the name of the macro; e.g., for the above form
 @('(defun-inline foo ...)'), you may subsequently issue the event
 @('(verify-guards foo$inline)') but not @('(verify-guards foo)').</p>

 <p>(5) Obscure Remark.  Suppose that you certify a book with compilation (the
 default) in one host Lisp, saving the expansion file.  Suppose that you then
 compile in another host Lisp by using @(tsee include-book) with argument
 @(':load-compiled-file :comp').  Then in subsequent sessions, including that
 book with the second host Lisp will not result in any inline or notinline
 behavior for functions defined in the book.  This may be fixed in a future
 release if someone complains.</p>")

(defxdoc defun-mode
  :parents (defun)
  :short "Determines whether a function definition is a logical act"
  :long "<p>Two ``@(see defun-mode)s'' are supported, @(':')@(tsee program) and
 @(':')@(tsee logic).  Roughly speaking, @(':')@(tsee program) mode allows you
 to prototype a function for execution without any proof burdens, while
 @(':')@(tsee logic) mode allows you to add a new definitional axiom to the
 logic.  The system comes up in @(':')@(tsee logic) mode.  Execution of
 functions whose @(see defun-mode) is @(':')@(tsee program) may render ACL2
 unsound!  See @(see defun-mode-caveat).</p>

 <p>Note that calls of @(tsee local) and of many @(see events) are skipped in
 @(':program') mode; see @(see program).</p>

 <p>When you define a function in the ACL2 logic, that function can be run on
 concrete data.  But it is also possible to reason deductively about the
 function because each definition extends the underlying logic with a
 definitional axiom.  To ensure that the logic is sound after the addition of
 this axiom, certain restrictions have to be met, namely that the recursion
 terminates.  This can be quite challenging.</p>

 <p>Because ACL2 is a @(see programming) language, you often may wish simply to
 program in ACL2.  For example, you may wish to define your system and test it,
 without any logical burden.  Or, you may wish to define ``utility'' functions
 &mdash; functions that are executed to help manage the task of building your
 system but functions whose logical properties are of no immediate concern.
 Such functions might be used to generate test data or help interpret the
 results of tests.  They might create files or explore the ACL2 database.  The
 termination arguments for such functions are an unnecessary burden provided no
 axioms about the functions are ever used in deductions.</p>

 <p>Thus, ACL2 introduces the idea of the ``@(see defun-mode)'' of a function.
 The @(':mode') keyword of @(tsee defun)'s @(tsee declare) @('xarg') allows you
 to specify the @(see defun-mode) of a given definition.  If no @(':mode')
 keyword is supplied, the default @(see defun-mode) is used; see @(see
 default-defun-mode).</p>

 <p>There are two @(see defun-mode)s, each of which is written as a
 keyword:</p>

 <p>@(':')@(tsee program) &mdash; logically undefined but executable outside
 deductive contexts.</p>

 <p>@(':')@(tsee logic) &mdash; axiomatically defined as per the ACL2
 definitional principle.</p>

 <p>It is possible to change the @(see defun-mode) of a function from
 @(':')@(tsee program) to @(':')@(tsee logic).  We discuss this below.</p>

 <p>We think of functions having @(':')@(tsee program) mode as ``dangerous''
 functions, while functions having @(':')@(tsee logic) mode are ``safe.''  The
 only requirement enforced on @(':')@(tsee program) mode functions is the
 syntactic one: each definition must be well-formed ACL2.  Naively speaking, if
 a @(':')@(tsee program) mode function fails to terminate then no harm is done
 because no axiom is added (so inconsistency is avoided) and some invocations
 of the function may simply never return.  This simplistic justification of
 @(':')@(tsee program) mode execution is faulty because it ignores the damage
 that might be caused by ``mis-guarded'' functions.  See @(see
 defun-mode-caveat).</p>

 <p>We therefore implicitly describe an imagined implementation of @(see
 defun-mode)s that is safe and, we think, effective.  But please see @(see
 defun-mode-caveat).</p>

 <p>The default @(see defun-mode) is @(':')@(tsee logic).  This means that when
 you @(tsee defun) a function the system will try to prove termination.  If you
 wish to introduce a function of a different @(see defun-mode) use the
 @(':mode') @(tsee xargs) keyword.  Below we show @('fact') introduced as a
 function in @(':')@(tsee program) mode.</p>

 @({
  (defun fact (n)
    (declare (xargs :mode :program))
    (if (or (not (integerp n)) (= n 0))
        1
      (* n (fact (1- n)))))
 })

 <p>No axiom is added to the logic as a result of this definition.  By
 introducing @('fact') in @(':')@(tsee program) mode we avoid the burden of a
 termination proof, while still having the option of executing the function.
 For example, you can type</p>

 @({
  ACL2 !>(fact 3)
 })

 <p>and get the answer @('6').  If you type @('(fact -1)') you will get a hard
 lisp error due to ``infinite recursion.''</p>

 <p>However, the ACL2 theorem prover knows no axioms about @('fact').  In
 particular, if the term @('(fact 3)') arises in a proof, the theorem prover is
 unable to deduce that it is @('6').  From the perspective of the theorem
 prover it is as though @('fact') were an undefined function symbol of arity
 @('1').  Thus, modulo certain important issues (see @(see defun-mode-caveat)),
 the introduction of this function in @(':')@(tsee program) mode does not
 imperil the soundness of the system &mdash; despite the fact that the
 termination argument for @('fact') was omitted &mdash; because nothing of
 interest can be proved about @('fact').  Indeed, we do not allow @('fact') to
 be used in logical contexts such as conjectures submitted for proof.</p>

 <p>It is possible to convert a function from @(':')@(tsee program) mode to
 @(':')@(tsee logic) mode at the cost of proving that it is admissible.  This
 can be done by invoking</p>

 @({
  (verify-termination fact)
 })

 <p>which is equivalent to submitting the @(tsee defun) of @('fact'), again,
 but in @(':')@(tsee logic) mode.</p>

 @({
  (defun fact (n)
    (declare (xargs :mode :logic))
    (if (or (not (integerp n)) (= n 0))
        1
      (* n (fact (1- n)))))
 })

 <p>This particular event will fail because the termination argument requires
 that @('n') be nonnegative.  A repaired @(tsee defun), for example with @(tsee
 =) replaced by @(tsee <=), will succeed, and an axiom about @('fact') will
 henceforth be available.</p>

 <p>Technically, @(tsee verify-termination) submits a redefinition of the
 @(':')@(tsee program) mode function.  This is permitted, even when @(tsee
 ld-redefinition-action) is @('nil'), because the new definition is identical
 to the old (except for its @(':mode') and, possibly, other non-logical
 properties).</p>

 <p>See @(see guard) for a discussion of how to restrict the execution of
 functions.  @(see Guard)s may be ``verified'' for functions in @(':')@(tsee
 logic) mode; see @(see verify-guards).</p>")

(defxdoc defun-mode-caveat
  :parents (common-lisp)
  :short "Potential soundness issue for functions with @(see defun-mode)
  @(':')@(tsee program)"
  :long "<p>See @(see raw-lisp-error) for a general discussion of raw Lisp
 errors.  Although the discussion below focuses on raw Lisp errors that arise
 from calls of @(':')@(tsee program) mode functions, the soundness concerns
 expressed below apply to all raw Lisp errors.</p>

 <p>Technically speaking, in the current implementation, the execution of
 functions having @(see defun-mode) @(':')@(tsee program) may damage the ACL2
 system in a way that renders it unsound.  In practice, we have never seen this
 happen; so, the explanations below can be viewed as extremely paranoid.
 Nevertheless, here we document this concern, even if it should be taken with
 more than a grain of salt.</p>

 <p>See @(see defun-mode) for a discussion of @(see defun-mode)s.  That
 discussion describes an imagined implementation that is slightly different
 from this one.  This note explains that the current implementation is open to
 unsoundness.</p>

 <p>For discussion of a different soundness issue that is also related to
 function execution, see @(see generalized-booleans).</p>

 <p>The execution of a function having @(see defun-mode) @(':')@(tsee program)
 may violate Common Lisp @(see guard)s on the subroutines used.  (This may be
 true even for calls of a function on arguments that satisfy its @(see guard),
 because ACL2 has not verified that its @(see guard) is sufficient to protect
 its subroutines.)  When a @(see guard) is violated at runtime all bets are
 off.  That is, no guarantees are made either about the answer being ``right''
 or about the continued rationality of the ACL2 system itself.</p>

 <p>For example, suppose you make the following @(tsee defun):</p>

 @({
  (defun crash (i)
    (declare (xargs :mode :program :guard (integerp i)))
    (car i))
 })

 <p>Note that the declared guard does not in fact adequately protect the
 subroutines in the body of @('crash'); indeed, satisfying the guard to
 @('crash') will guarantee that the @(tsee car) expression is in violation of
 its guard.  Because this function is admitted in @(':')@(tsee program)-mode,
 no checks are made concerning the suitability of the guard.  Furthermore, in
 the current ACL2 implementation, @('crash') is executed directly in Common
 Lisp.  Thus if you call @('crash') on an argument satisfying its guard you
 will cause an erroneous computation to take place.</p>

 @({
  ACL2 !>(crash 7)

  Error: Caught fatal error [memory may be damaged]
  ...
 })

 <p>There is no telling how much damage is done by this errant computation.  In
 some lisps your ACL2 job may actually crash back to the operating system.  In
 other lisps you may be able to recover from the ``hard error'' and resume ACL2
 in a damaged but apparently functional image.</p>

 <p>THUS, HAVING A FUNCTION WITH @(see DEFUN-MODE) @(':')@(tsee PROGRAM) IN
 YOUR SYSTEM ABSOLVES US, THE ACL2 IMPLEMENTORS, FROM RESPONSIBILITY FOR THE
 SOUNDNESS OF OUR SYSTEM.</p>

 <p>Furthermore</p>

 <p>ACL2 DOES NOT YET PROVIDE ANY MEANS OF REGAINING ASSURANCES OF SOUNDNESS
 AFTER THE INTRODUCTION OF A FUNCTION IN @(':')@(tsee PROGRAM) MODE, EVEN IF IT
 IS ULTIMATELY CONVERTED TO @(':')@(tsee LOGIC) MODE (since its execution could
 have damaged the system in a way that makes it possible to verify its
 termination and @(see guard)s unsoundly).</p>

 <p>Finally,</p>

 <p>THE VAST MAJORITY OF ACL2 SYSTEM CODE IS IN @(':')@(tsee PROGRAM) MODE AND
 SO ALL BETS ARE OFF FROM BEFORE YOU START!</p>

 <p>This hopeless state of current affairs will change, we think.  We think we
 have defined our functions ``correctly'' in the sense that they can be
 converted, without ``essential'' modification, to @(':')@(tsee logic) mode.
 We think it very unlikely that a mis-guarded function in @(':')@(tsee program)
 mode (whether ours or yours) will cause unsoundness without some sort of hard
 lisp error accompanying it.  We think that ultimately we can make it possible
 to execute your functions (interpretively) without risk to the system, even
 when some have @(':')@(tsee program) mode.  In that imagined implementation,
 code using functions having @(':')@(tsee program) mode would run more slowly,
 but safely.  These functions could be introduced into the logic ex post facto,
 whereupon the code's execution would speed up because Common Lisp would be
 allowed to execute it directly.  We therefore ask that you simply pretend that
 this is that imagined implementation, introduce functions in @(':')@(tsee
 program) mode, use them as convenient and perhaps ultimately introduce some of
 them in @(':')@(tsee logic) mode and prove their properties.  If you use the
 system this way we can develop (or dismiss) this style of formal system
 development.  BUT BE ON THE LOOKOUT FOR SCREWUPS DUE TO DAMAGE CAUSED BY THE
 EXECUTION OF YOUR FUNCTIONS HAVING @(':')@(tsee PROGRAM) MODE!</p>")

(defxdoc defun-notinline
  :parents (defun events)
  :short "Define a not-to-be-inlined function symbol and associated macro"
  :long "<p>See @(see defun-inline) for an analogous utility that supports
 inlining.  The present utility is probably far less useful; it tells the
 compiler <i>not</i> to inline calls of the function being defined.  Also see
 @(see defund-notinline) for a variant of this event that disables the
 newly-defined function symbol.</p>

 <p>Under the hood, @('(defun-inline f ...)') and @('(defun-notinline f ...)')
 cause evaluation of Common Lisp forms @('(declaim (inline f$inline))') and
 @('(declaim (notinline f$notinline))'), respectively.  According to the Common
 Lisp spec, the compiler need not respect the first of these (for @('inline')),
 but it must respect the second of these (for @('notinline')).  Fortunately,
 Common Lisp implementations often do respect the first of these as well.</p>")

(defxdoc defun-nx
  :parents (defun events)
  :short "Define a non-executable function symbol"
  :long "@({
  Example:

  (set-state-ok t)
  (defun-nx foo (x state)
    (mv-let (a b c)
            (cons x state)
            (list a b c b a)))
  ; Note ``ill-formed'' call of foo just below.
  (defun bar (state y)
    (foo state y))
 })

 <p>The macro @('defun-nx') introduces definitions using the @(tsee defun)
 macro, always in @(':')@(tsee logic) mode, such that the calls of the
 resulting function cannot be evaluated.  Such a definition is admitted without
 enforcing syntactic restrictions for executability, in particular for
 single-threadedness (see @(see stobj)) and multiple-values passing (see @(see
 mv) and see @(see mv-let)).  After such a definition is admitted, the usual
 syntactic rules for @(tsee state) and user-defined @(see stobj)s are relaxed
 for calls of the function it defines.  Also see @(see non-exec) for a way to
 designate subterms of function bodies, or subterms of code to be executed at
 the top level, as non-executable.</p>

 <p>The syntax of @('defun-nx') is identical to that of @(tsee defun).  A
 form</p>

 @({
  (defun-nx name (x1 ... xk) ... body)
 })

 <p>expands to the following form.</p>

 @({
  (defun name (x1 ... xk)
    (declare (xargs :non-executable t :mode :logic))
    ...
    (prog2$ (throw-nonexec-error 'name (list x1 ... xk))
            body))
 })

 <p>Note that because of the insertion of the above call of
 @('throw-nonexec-error'), no formal is ignored when using @('defun-nx').</p>

 <p>During proofs, the error is silent; it is ``caught'' by the proof mechanism
 and generally results in the introduction of a call of @(tsee hide) during a
 proof.  If an error message is produced by evaluating a call of the function
 on a list of arguments that includes @('state') or user-defined @(tsee
 stobj)s, these arguments will be shown as symbols such as @('|<state>|') in
 the error message.  In the case of a user-defined stobj bound by @(tsee
 with-local-stobj) or @(tsee stobj-let), the symbol printed will include the
 suffix @('{instance}'), for example, @('|<st>{instance}|').</p>

 <p>It is harmless to include @(':non-executable t') in your own @(tsee xargs)
 @(tsee declare) form; @('defun-nx') will still lay down its own such
 declaration, but ACL2 can tolerate the duplication.</p>

 <p>Note that @('defund-nx') is also available.  It has an effect identical to
 that of @('defun-nx') except that as with @(tsee defund), it leaves the
 function disabled.</p>

 <p>If you use guards (see @(see guard)), please be aware that even though
 syntactic restrictions are relaxed for @('defun-nx'), guard verification
 proceeds exactly as for @(tsee defun).  If you want ACL2 to skip a form for
 purposes of generating guard proof obligations, use the macro @(tsee
 non-exec), which generates a call of @('throw-nonexec-error') that differs
 somewhat from the one displayed above.  See @(see non-exec).</p>

 <p>See @(see defun) for documentation of @('defun').</p>")

(defxdoc defun-sk
  :parents (events)
  :short "Define a function whose body has an outermost quantifier"
  :long "@({
  Examples:
  (defun-sk exists-x-p0-and-q0 (y z)
    (exists x
            (and (p0 x y z)
                 (q0 x y z))))

  (defun-sk exists-x-p0-and-q0 (y z) ; equivalent to the above
    (exists (x)
            (and (p0 x y z)
                 (q0 x y z))))

  (defun-sk forall-x-y-p0-and-q0 (z)
    (forall (x y)
            (and (p0 x y z)
                 (q0 x y z)))
    :strengthen t)

  General Form:
  (defun-sk fn (var1 ... varn)
    dcl_1 dcl_2 ... dcl_k
    body
    &key rewrite quant-ok skolem-name thm-name witness-dcls strengthen)
 })

 <p>where @('fn') is the symbol you wish to define and is a new symbolic @(see
 name), @('(var1 ... varn)') is its list of formal parameters, the optional
 @('dcl_i') forms are @(tsee declare) forms, and @('body') is its body, which
 must be quantified as described below.  The other arguments are explained
 below.</p>

 <p>For a simple example, see @(see defun-sk-example).  For a more elaborate
 example, see @(see Tutorial4-Defun-Sk-Example).  See @(see
 quantifier-tutorial) for a careful beginner's introduction that takes you
 through typical kinds of quantifier-based reasoning in ACL2.  Also see @(see
 quantifiers) for an example illustrating how the use of recursion, rather than
 explicit quantification with @('defun-sk'), may be preferable.</p>

 <p>Below we describe the @('defun-sk') event precisely.  First, let us
 consider the examples above.  The first example, again, is:</p>

 @({
  (defun-sk exists-x-p0-and-q0 (y z)
    (exists x
            (and (p0 x y z)
                 (q0 x y z))))
 })

 <p>It is intended to represent the predicate with formal parameters @('y') and
 @('z') that holds when for some @('x'), @('(and (p0 x y z) (q0 x y z))')
 holds.  In fact @('defun-sk') is a macro that adds the following two @(see
 events), as shown just below.  The first event guarantees that if this new
 predicate holds of @('y') and @('z'), then the term shown,
 @('(exists-x-p0-and-q0-witness y z)'), is an example of the @('x') that is
 therefore supposed to exist.  (Intuitively, we are axiomatizing
 @('exists-x-p0-and-q0-witness') to pick a witness if there is one.  We comment
 below on the use of @(tsee defun-nx); for now, consider @('defun-nx') to be
 @(tsee defun).)  Conversely, the second event below guarantees that if there
 is any @('x') for which the term in question holds, then the new predicate
 does indeed hold of @('y') and @('z').</p>

 @({
  (defun-nx exists-x-p0-and-q0 (y z)
    (let ((x (exists-x-p0-and-q0-witness y z)))
      (and (p0 x y z) (q0 x y z))))
  (defthm exists-x-p0-and-q0-suff
    (implies (and (p0 x y z) (q0 x y z))
             (exists-x-p0-and-q0 y z)))
 })

 <p>Now let us look at the third example from the introduction above:</p>

 @({
  (defun-sk forall-x-y-p0-and-q0 (z)
    (forall (x y)
            (and (p0 x y z)
                 (q0 x y z))))
 })

 <p>The intention is to introduce a new predicate @('(forall-x-y-p0-and-q0 z)')
 which states that the indicated conjunction holds of all @('x') and all @('y')
 together with the given @('z').  This time, the axioms introduced are as shown
 below.  The first event guarantees that if the application of function
 @('forall-x-y-p0-and-q0-witness') to @('z') picks out values @('x') and @('y')
 for which the given term @('(and (p0 x y z) (q0 x y z))') holds, then the new
 predicate @('forall-x-y-p0-and-q0') holds of @('z').  Conversely, the
 (contrapositive of) the second axiom guarantees that if the new predicate
 holds of @('z'), then the given term holds for all choices of @('x') and
 @('y') (and that same @('z')).</p>

 @({
  (defun-nx forall-x-y-p0-and-q0 (z)
    (mv-let (x y)
            (forall-x-y-p0-and-q0-witness z)
            (and (p0 x y z) (q0 x y z))))
  (defthm forall-x-y-p0-and-q0-necc
    (implies (not (and (p0 x y z) (q0 x y z)))
             (not (forall-x-y-p0-and-q0 z))))
 })

 <p>The examples above suggest the critical property of @('defun-sk'): it
 indeed does introduce the quantified notions that it claims to introduce.</p>

 <p>Notice that the @(tsee defthm) event just above,
 @('forall-x-y-p0-and-q0-necc'), may not be of optimal form as a rewrite rule.
 Users sometimes find that when the quantifier is @('forall'), it is useful to
 state this rule in a form where the new quantified predicate is a hypothesis
 instead.  In this case that form would be as follows:</p>

 @({
  (defthm forall-x-y-p0-and-q0-necc
    (implies (forall-x-y-p0-and-q0 z)
             (and (p0 x y z) (q0 x y z))))
 })

 <p>ACL2 will turn this into one @(':')@(tsee rewrite) rule for each conjunct,
 @('(p0 x y z)') and @('(q0 x y z)'), with hypothesis @('(forall-x-y-p0-and-q0
 z)') in each case.  In order to get this effect, use @(':rewrite :direct'), in
 this case as follows.</p>

 @({
  (defun-sk forall-x-y-p0-and-q0 (z)
    (forall (x y)
            (and (p0 x y z)
                 (q0 x y z)))
    :rewrite :direct)
 })

 <p>We now turn to a detailed description of @('defun-sk'), starting with a
 discussion of its arguments as shown in the \"General Form\" above.</p>

 <p>The third argument, @('body'), must be of the form</p>

 @({
  (Q bound-vars term)
 })

 <p>where: @('Q') is the symbol @(tsee forall) or @(tsee exists), in the
 \"ACL2\" package; @('bound-vars') is a variable or true list of variables
 disjoint from @('(var1 ... varn)') and not including @(tsee state); and
 @('term') is a term.  The case that @('bound-vars') is a single variable
 @('v') is treated exactly the same as the case that @('bound-vars') is
 @('(v)').</p>

 <p>The result of this event is to introduce a ``Skolem function,'' whose name
 is the keyword argument @('skolem-name') if that is supplied, and otherwise is
 the result of modifying @('fn') by suffixing \"-WITNESS\" to its name.  The
 following definition and one of the following two theorems (as indicated) are
 introduced for @('skolem-name') and @('fn') in the case that @('bound-vars')
 (see above) is a single variable @('v').  The name of the @(tsee defthm) event
 may be supplied as the value of the keyword argument @(':thm-name'); if it is
 not supplied, then it is the result of modifying @('fn') by suffixing
 \"-SUFF\" to its name in the case that the quantifier is @(tsee exists), and
 \"-NECC\" in the case that the quantifier is @(tsee forall).</p>

 @({
  (defun-nx fn (var1 ... varn)
    (let ((v (skolem-name var1 ... varn)))
      term))

  (defthm fn-suff ;in case the quantifier is EXISTS
    (implies term
             (fn var1 ... varn)))

  (defthm fn-necc ;in case the quantifier is FORALL
    (implies (not term)
             (not (fn var1 ... varn))))
 })

 <p>In the @('forall') case, however, the keyword pair @(':rewrite :direct')
 may be supplied after the body of the @('defun-sk') form, in which case the
 contrapositive of the above form is used instead:</p>

 @({
  (defthm fn-necc ;in case the quantifier is FORALL
    (implies (fn var1 ... varn)
             term))
 })

 <p>This is often a better choice for the \"-NECC\" rule, provided ACL2 can
 parse @('term') as a @(':')@(tsee rewrite) rule.  A second possible value of
 the @(':rewrite') argument of @('defun-sk') is @(':default'), which gives the
 same behavior as when @(':rewrite') is omitted.  Otherwise, the value of
 @(':rewrite') should be the term to use as the body of the @('fn-necc')
 theorem shown above; ACL2 will attempt to do the requisite proof in this case.
 If that term is weaker than the default, the properties introduced by
 @('defun-sk') may of course be weaker than they would be otherwise.  Finally,
 note that the @(':rewrite') keyword argument for @('defun-sk') only makes
 sense if the quantifier is @('forall'); it is thus illegal if the quantifier
 is @('exists').  Enough said about @(':rewrite')!</p>

 <p>In the case that @('bound-vars') is a list of at least two variables, say
 @('(bv1 ... bvk)'), the definition above (with no keywords) is the following
 instead, but the theorem remains unchanged.</p>

 @({
  (defun-nx fn (var1 ... varn)
    (mv-let (bv1 ... bvk)
            (skolem-name var1 ... varn)
            term))
 })

 <p>In order to emphasize that the last element of the list, @('body'), is a
 term, @('defun-sk') checks that the symbols @(tsee forall) and @(tsee exists)
 do not appear anywhere in it.  However, on rare occasions one might
 deliberately choose to violate this convention, presumably because @(tsee
 forall) or @(tsee exists) is being used as a variable or because a macro call
 will be eliminating ``calls of'' @(tsee forall) and @(tsee exists).  In these
 cases, the keyword argument @('quant-ok') may be supplied a non-@('nil')
 value.  Then @('defun-sk') will permit @(tsee forall) and @(tsee exists) in
 the body, but it will still cause an error if there is a real attempt to use
 these symbols as quantifiers.</p>

 <p>The use of @(tsee defun-nx) above, rather than @(tsee defun), disables
 certain checks that are required for evaluation, in particular the
 single-threaded use of @(tsee stobj)s.  However, there is a price: calls of
 these defined functions cannot be evaluated; see @(see defun-nx).  Normally
 that is not a problem, since these notions involve quantifiers.  But you are
 welcome to replace this @(tsee declare) form with your own @('declare') forms.
 These may be given either as the @('dcl_i') as shown above, or (using an older
 notation that might some day be deprecated) as a list of @('declare') supplied
 as the value of keyword argument @(':witness-dcls'); or, both.  These will
 become the @('declare') forms in the generated @(tsee defun).  Note that if at
 least one declare form is supplied, but none of those forms contain the form
 @('(declare (xargs :non-executable t))'), then the appropriate wrapper for
 non-executable functions will not be added, i.e., @(tsee defun) will be used
 in place of @(tsee defun-nx).</p>

 <p>@(csee Guard) verification is handled specially for @('defun-sk') events.
 Unlike @(tsee defun), the value of @('verify-guards-eagerness') is irrelevant
 for @('defun-sk').  Instead, guard verification will be attempted exactly when
 @('type'), @(':guard'), or @(':verify-guards t') (or more than one of these)
 is specified in a declaration (that is, in some @('dcl_i') or in the
 @(':witness-dcls') argument).  Technical note: unless @(':verify-guards t') is
 specified explicitly, such guard verification is implemented through a
 generated call of @(tsee verify-guards) after the @('encapsulate') that
 surrounds the definitions introduced; use @(':')@(tsee trans1) to see the
 expansion.</p>

 <p>@('Defun-sk') is a macro implemented using @(tsee defchoose).  Hence, it
 should only be executed in @(see defun-mode) @(':')@(tsee logic); see @(see
 defun-mode) and see @(see defchoose).  Advanced feature: If argument
 @(':strengthen t') is passed to @('defun-sk'), then @(':strengthen t') will
 generate the extra constraint that is generated for the corresponding
 @('defchoose') event; see @(see defchoose).  (The name of that generated
 theorem will be obtained by adding the suffix @('\"-STRENGTHEN\"') to the
 function symbol being defined, in the same package).  You can use the command
 @(':')@(tsee pcb!) to see the event generated by a call of the @('defun-sk')
 macro.</p>

 <p>If you find that the rewrite rules introduced with a particular use of
 @('defun-sk') are not ideal, even when using the @(':rewrite') keyword
 discussed above (in the @('forall') case), then at least two reasonable
 courses of action are available for you.  Perhaps the best option is to prove
 the @(tsee rewrite) rules you want.  If you see a pattern for creating rewrite
 rules from your @('defun-sk') events, you might want to write a macro that
 executes a @('defun-sk') followed by one or more @(tsee defthm) events.
 Another option is to write your own variant of the @('defun-sk') macro, say,
 @('my-defun-sk'), for example by modifying a copy of the definition of
 @('defun-sk') from the ACL2 sources.</p>

 <p>If you want to represent nested quantifiers, you can use more than one
 @('defun-sk') event.  For example, in order to represent</p>

 @({
  (forall x (exists y (p x y z)))
 })

 <p>you can use @('defun-sk') twice, for example as follows.</p>

 @({
  (defun-sk exists-y-p (x z)
    (exists y (p x y z)))

  (defun-sk forall-x-exists-y-p (z)
    (forall x (exists-y-p x z)))
 })

 <p>Some distracting and unimportant warnings are inhibited during
 @('defun-sk').</p>

 <p>Note for ACL2(r) users (see @(see real)): In ACL2(r), the keyword
 @(':CLASSICALP') is also supported.  Its legal values are @('t') (the default)
 and @('nil'), and it determines whether or not (respectively) ACL2(r) will
 consider @('fn') to be a classical function.  It must be the case that the
 value is @('t') (perhaps implicitly, by default) if and only if @('body') is
 classical.</p>

 <p>Note that this way of implementing quantifiers is not a new idea.  Hilbert
 was certainly aware of it 60 years ago!  Also see @(see
 conservativity-of-defchoose) for a technical argument that justifies the
 logical conservativity of the @(tsee defchoose) event in the sense of the
 paper by Kaufmann and Moore entitled ``Structured Theory Development for a
 Mechanized Logic'' (Journal of Automated Reasoning 26, no. 2 (2001),
 pp. 161&ndash;203).</p>")

(defxdoc defun-sk-example
  :parents (defun-sk)
  :short "A simple example using @(tsee defun-sk)"
  :long "<p>For a more through, systematic beginner's introduction to
 quantification in ACL2, see @(see quantifier-tutorial).</p>

 <p>The following example illustrates how to do proofs about functions defined
 with @(tsee defun-sk).  The events below can be put into a certifiable book
 (see @(see books)).  The example is contrived and rather silly, in that it
 shows how to prove that a quantified notion implies itself, where the
 antecedent and conclusion are defined with different @(tsee defun-sk) events.
 But it illustrates the formulas that are generated by @(tsee defun-sk), and
 how to use them.  Thanks to Julien Schmaltz for presenting this example as a
 challenge.</p>

 @({
  (in-package \"ACL2\")

  (encapsulate
   (((p *) => *)
    ((expr *) => *))

   (local (defun p (x) x))
   (local (defun expr (x) x)))

  (defun-sk forall-expr1 (x)
    (forall (y) (implies (p x) (expr y))))

  (defun-sk forall-expr2 (x)
    (forall (y) (implies (p x) (expr y)))))

  ; We want to prove the theorem my-theorem below.  What axioms are there that
  ; can help us?  If you submit the command

  ; :pcb! forall-expr1

  ; then you will see the following two key events.  (They are completely
  ; analogous of course for FORALL-EXPR2.)

  ;   (DEFUN FORALL-EXPR1 (X)
  ;     (LET ((Y (FORALL-EXPR1-WITNESS X)))
  ;          (IMPLIES (P X) (EXPR Y))))
  ;
  ;   (DEFTHM FORALL-EXPR1-NECC
  ;     (IMPLIES (NOT (IMPLIES (P X) (EXPR Y)))
  ;              (NOT (FORALL-EXPR1 X)))
  ;     :HINTS
  ;     ((\"Goal\" :USE FORALL-EXPR1-WITNESS)))

  ; We see that the latter has value when FORALL-EXPR1 occurs negated in a
  ; conclusion, or (therefore) positively in a hypothesis.  A good rule to
  ; remember is that the former has value in the opposite circumstance: negated
  ; in a hypothesis or positively in a conclusion.

  ; In our theorem, FORALL-EXPR2 occurs positively in the conclusion, so its
  ; definition should be of use.  We therefore leave its definition enabled,
  ; and disable the definition of FORALL-EXPR1.

  ;   (thm
  ;     (implies (and (p x) (forall-expr1 x))
  ;              (forall-expr2 x))
  ;     :hints ((\"Goal\" :in-theory (disable forall-expr1))))
  ;
  ;   ; which yields this unproved subgoal:
  ;
  ;   (IMPLIES (AND (P X) (FORALL-EXPR1 X))
  ;            (EXPR (FORALL-EXPR2-WITNESS X)))

  ; Now we can see how to use FORALL-EXPR1-NECC to complete the proof, by
  ; binding y to (FORALL-EXPR2-WITNESS X).

  ; We use defthmd below so that the following doesn't interfere with the
  ; second proof, in my-theorem-again that follows.
  (defthmd my-theorem
    (implies (and (p x) (forall-expr1 x))
             (forall-expr2 x))
    :hints ((\"Goal\"
             :use ((:instance forall-expr1-necc
                              (x x)
                              (y (forall-expr2-witness x)))))))

  ; The following illustrates a more advanced technique to consider in such
  ; cases.  If we disable forall-expr1, then we can similarly succeed by having
  ; FORALL-EXPR1-NECC applied as a :rewrite rule, with an appropriate hint in how
  ; to instantiate its free variable.  See :doc hints.

  (defthm my-theorem-again
    (implies (and (P x) (forall-expr1 x))
             (forall-expr2 x))
    :hints ((\"Goal\"
             :in-theory (disable forall-expr1)
             :restrict ((forall-expr1-necc
                         ((y (forall-expr2-witness x))))))))
 })")

(defxdoc defund
  :parents (defun events)
  :short "Define a function symbol and then disable it"
  :long "<p>Use @('defund') instead of @(tsee defun) when you want to disable a
 function immediately after its definition in @(':')@(tsee logic) mode.  This
 macro has been provided for users who prefer working in a mode where functions
 are only enabled when explicitly directed by @(':')@(tsee in-theory).
 Specifically, the form</p>

 @({
  (defund NAME FORMALS ...)
 })

 <p>expands to:</p>

 @({
  (progn
    (defun NAME FORMALS ...)
    (with-output
     :off summary
     (in-theory (disable NAME)))
    (value-triple '(:defund NAME))).
 })

 <p>Only the @(':')@(tsee definition) rule (and, for recursively defined
 functions, the @(':')@(tsee induction) rule) for the function are disabled.
 In particular, @('defund') does not disable either the @(':')@(tsee
 type-prescription) or the @(':')@(tsee executable-counterpart) rule.  Also,
 the summary for the @(tsee in-theory) event is suppressed.</p>

 <p>If the function is defined in @(':')@(tsee program) mode, either because
 the @(see default-defun-mode) is @(':')@(tsee program) or because @(':mode
 :program') has been specified in an @(tsee xargs) form of a @(tsee declare)
 form, then no @(tsee in-theory) event is executed.  (More precisely, @(tsee
 in-theory) events are ignored when the @(see default-defun-mode) is
 @(':')@(tsee program), and if @(':mode :program') is specified then
 @('defund') does not generate an @(tsee in-theory) event.)</p>

 <p>Note that @('defund') commands are never redundant (see @(see
 redundant-events)) when the @(see default-defun-mode) is @(':')@(tsee logic),
 because the @(tsee in-theory) event will always be executed.</p>

 <p>See @(see defun) for documentation of @('defun').</p>")

(defxdoc defund-inline
  :parents (defun events)
  :short "Define a potentially disabled, inlined function symbol and associated macro"
  :long "<p>@('Defund-inline') is a variant of @(tsee defun-inline), the
 difference being that @('defund-inline') disables the newly-defined function
 symbol.  See @(see defun-inline).</p>")

(defxdoc defund-notinline
  :parents (defun events)
  :short "Define a disabled, not-to-be-inlined function symbol and associated macro"
  :long "<p>@('Defund-notinline') is a variant of @(tsee defun-notinline), the
 difference being that @('defund-notinline') disables the newly-defined
 function symbol.  See @(see defun-notinline).</p>")

(defxdoc defund-nx
  :parents (defun events)
  :short "Define a disabled non-executable function symbol"
  :long "<p>Use @('defund-nx') instead of @('defun-nx') when you want to @(see
  disable) a function immediately after its definition in @(':')@(tsee logic)
  mode.  See @(see defun-nx) and see @(see defund).</p>")

(defxdoc defuns
  :parents (mutual-recursion)
  :short "An alternative to @(tsee mutual-recursion)"
  :long "@({
  Example:
  (DEFUNS
   (evenlp (x)
     (if (consp x) (oddlp (cdr x)) t))
   (oddlp (x)
     (if (consp x) (evenlp (cdr x)) nil)))

  General Form:
  (DEFUNS defuns-tuple1 ... defuns-tuplen)
 })

 <p>is equivalent to</p>

 @({
  (MUTUAL-RECURSION
    (DEFUN . defuns-tuple1)
    ...
    (DEFUN . defuns-tuplen))
 })

 <p>In fact, @('defuns') is the more primitive of the two and @(tsee
 mutual-recursion) is just a macro that expands to a call of @('defuns')
 after stripping off the @(tsee defun) at the @(tsee car) of each argument to
 @(tsee mutual-recursion).  We provide and use @(tsee mutual-recursion) rather
 than @('defuns') because by leaving the @(tsee defun)s in place, @(tsee
 mutual-recursion) forms can be processed by the Emacs @('tags') program.  See
 @(see mutual-recursion).</p>")

(defxdoc delete-assoc
  :parents (alists acl2-built-ins)
  :short "Remove the first pair from an association list for a given key"
  :long "@({
  General Forms:
  (delete-assoc key alist)
  (delete-assoc key alist :test 'eql)   ; same as above (eql as equality test)
  (delete-assoc key alist :test 'eq)    ; same, but eq is equality test
  (delete-assoc key alist :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Delete-assoc key alist)') returns an alist that is the same as the list
 @('alist'), except that the first pair in @('alist') with a @(tsee car) of
 @('key') is deleted, if there is one; otherwise @('alist') is returned.  Note
 that the order of the elements of @('alist') is unchanged (though one may be
 deleted).</p>

 <p>The @(see guard) for a call of @('delete-assoc') depends on the test.  In
 all cases, the second argument must satisfy @(tsee alistp).  If the test is
 @(tsee eql), then either the first argument must be suitable for @(tsee eql)
 (see @(see eqlablep)) or the second argument must satisfy @(tsee
 eqlable-alistp).  If the test is @(tsee eq), then either the first argument
 must be a symbol or the second argument must satisfy @(tsee
 symbol-alistp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('delete-assoc') and its variants:</p>

 <blockquote><p>@('(delete-assoc-eq key alist)') is equivalent to
 @('(delete-assoc key alist :test 'eq)');</p>

 <p>@('(delete-assoc-equal key alist)') is equivalent to @('(delete-assoc key
 alist :test 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('delete-assoc-equal').</p>

 @(def delete-assoc-equal)")

(defxdoc delete-file$
  :parents (io)
  :short "Delete a file"
  :long "<p>This analogue of the Common Lisp function, @('delete-file'), uses
 that function under the hood to delete a given file.  The @(tsee guard) of
 @('delete-file$') requires that the first argument is a string; the second
 argument is the ACL2 @(tsee state).  The logical definition does not actually
 look at the file and hence is not useful for reasoning.</p>

 @(def delete-file$)")

(defxdoc delete-include-book-dir
  :parents (books-reference)
  :short "Unlink keyword for @(':dir') argument of @(tsee ld) and @(tsee
include-book)"
  :long "@({
 Example Forms:
 ; Remove association of a directory with :smith for include-book and ld:
 (delete-include-book-dir :smith)

 General Form:
 (delete-include-book-dir kwd)
 })

 <p>where @('kwd') is a @(tsee keywordp).  The effect of this event is to
 modify the meaning of the @(':dir') keyword argument of @(tsee include-book)
 and @(tsee ld) as indicated by the example above, namely by removing
 association of a directory with the indicated keyword for purposes of the
 @(':dir') argument of @(tsee include-book) and @(tsee ld).  See @(tsee
 add-include-book-dir) for how to associate a new directory with a keyword.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 <p>This macro is @(tsee local) to any @(see books) and @(tsee encapsulate)
 @(see events) in which it occurs; see @(see add-include-book-dir) for a
 discussion of this aspect of both macros.  For non-local associations of
 keywords with directories, see @(see add-include-book-dir!) and @(see
 delete-include-book-dir!).  Note that @('delete-include-book-dir') may only be
 used to remove keywords added by calls of @(tsee add-include-book-dir), and
 @(tsee delete-include-book-dir!) may only be used to remove keywords added by
 calls of @(tsee add-include-book-dir!)</p>")

(defxdoc delete-include-book-dir!
  :parents (books-reference)
  :short "Non-@(tsee local)ly unlink keyword for @(':dir') argument of @(tsee
ld) and @(tsee include-book)"
  :long "<p>Please see @(see delete-include-book-dir), which has completely
 analogous syntax and semantics, but is used for removing associations
 previously placed by @(tsee add-include-book-dir).  By contrast,
 @('delete-include-book-dir!') removes associations previously placed by
 @(tsee add-include-book-dir!).</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 <p>This macro is essentially a @(tsee table) event that updates the table
 @('include-book-dir!-table'), which associates keywords with absolute
 pathnames.  However, as with @(tsee delete-include-book-dir), direct table
 updates are disallowed; you must use @('delete-include-book-dir!') to remove
 from the table and @(tsee add-include-book-dir!) to add to the table.</p>

 <p>It is illegal to call @('delete-include-book-dir!') in a @(tsee local)
 context.  For an explanation, see @(see add-include-book-dir!).</p>")

(defxdoc denominator
  :parents (numbers acl2-built-ins)
  :short "Divisor of a ratio in lowest terms"
  :long "<p>Completion Axiom (@('completion-of-denominator')):</p>

 @({
  (equal (denominator x)
         (if (rationalp x)
             (denominator x)
           1))
 })

 <p>@(see Guard) for @('(denominator x)'):</p>

 @({
  (rationalp x)
 })")

(defxdoc digit-char-p
  :parents (characters acl2-built-ins)
  :short "The number, if any, corresponding to a given character"
  :long "<p>@('(digit-char-p ch)') is the integer corresponding to the
 character @('ch') in base @('10').  For example, @('(digit-char-p #\\3)') is
 equal to the integer @('3').  More generally, an optional second argument
 specifies the radix (default @('10'), as indicated above).</p>

 <p>The @(see guard) for @('digit-char-p') (more precisely, for the function
 @('our-digit-char-p') that calls of this macro expand to) requires its second
 argument to be an integer between 2 and 36, inclusive, and its first argument
 to be a character.</p>

 <p>@('Digit-char-p') is a Common Lisp function, though it is implemented in
 the ACL2 logic as an ACL2 macro.  See any Common Lisp documentation for more
 information.</p>

 @(def digit-char-p)
 @(def our-digit-char-p)")

(defxdoc digit-to-char
  :parents (characters acl2-built-ins)
  :short "Map a digit to a character"
  :long "@({
  Example:
  ACL2 !>(digit-to-char 8)
  #\\8
 })

 <p>For an integer @('n') from 0 to 15, @('(digit-to-char n)') is the character
 corresponding to @('n') in hex notation, using uppercase letters for digits
 exceeding 9.  If @('n') is in the appropriate range, that result is of course
 also the binary, octal, and decimal digit.</p>

 <p>The @(see guard) for @('digit-to-char') requires its argument to be an
 integer between 0 and 15, inclusive.</p>

 @(def digit-to-char)")

(defxdoc dimensions
  :parents (arrays acl2-built-ins)
  :short "Return the @(':dimensions') from the @(see header) of a 1- or
  2-dimensional array"
  :long "@({
  Example Form:
  (dimensions 'delta1 a)

  General Form:
  (dimensions name alist)
 })

 <p>where @('name') is arbitrary and @('alist') is a 1- or 2-dimensional array.
 This function returns the dimensions list of the array @('alist').  That list
 will either be of the form @('(dim1)') or @('(dim1 dim2)'), depending on
 whether @('alist') is a 1- or 2-dimensional array.  @('Dim1') and @('dim2')
 will be integers and each exceed by 1 the maximum legal corresponding index.
 Thus, if @('dimensions') returns, say, @(''(100)') for an array @('a') named
 @(''delta1'), then @('(aref1 'delta1 a 99)') is legal but @('(aref1 'delta1 a
 100)') violates the @(see guard)s on @(tsee aref1).  @('Dimensions') operates
 in virtually constant time if @('alist') is the semantic value of @('name').
 See @(see arrays).</p>

 @(def dimensions)")

(defxdoc disable
  :parents (theories theory-functions)
  :short "Deletes names from current theory"
  :long "@({
  Example:
  (disable fact (fact) associativity-of-app)

  General Form:
  (disable name1 name2 ... namek)
 })

 <p>where each @('namei') is a runic designator; see @(see theories).  The
 result is the theory that contains all the names in the current theory except
 those listed.  Note that this is merely a function that returns a theory.  The
 result is generally a very long list of @(see rune)s and you will probably
 regret printing it.</p>

 <p>For related utilities, see @(see enable) and see @(see e/d).</p>

 <p>The standard way to ``disable'' a fixed set of names, is as follows; see
 @(see hints) and see @(see in-theory).</p>

 @({
  :in-theory (disable name1 name2 ... namek)    ; in a hint
  (in-theory (disable name1 name2 ... namek))   ; as an event
  (local ; often desirable, to avoid exporting from the current context
   (in-theory (disable name1 name2 ... namek)))
 })

 <p>Note that all the names are implicitly quoted.  If you wish to disable a
 computed list of names, @('lst'), use the theory expression
 @('(set-difference-theories (current-theory :here) lst)').</p>")

(defxdoc disable-forcing
  :parents (force)
  :short "To disallow forced case-splits"
  :long "@({
  General Form:
  ACL2 !>:disable-forcing   ; disallow forced case splits
 })

 <p>See @(see force) and see @(see case-split) for a discussion of forced case
 splits, which are inhibited by this command.</p>

 <p>@('Disable-forcing') is actually a macro that @(see disable)s the @(see
 executable-counterpart) of the function symbol @('force'); see @(see force).
 When you want to use @(see hints) to turn off forced case splits, use a form
 such as one of the following (these are equivalent).</p>

 @({
  :in-theory (disable (:executable-counterpart force))
  :in-theory (disable (force))
 })

 <p>The following example shows how this works.  First evaluate these
 forms.</p>

 @({
  (defstub f1 (x) t)
  (defstub f2 (x) t)
  (defaxiom ax (implies (case-split (f2 x)) (f1 x)))
  (thm (f1 x))
 })

 <p>You will see the application of the rule, @('ax'), in the proof of the
 @(tsee thm) call above.  However, if you first evaluate
 @('(disable-forcing)'), then there will be no application of @('ax').  To
 restore forced case splitting, see @(see enable-forcing).</p>")

(defxdoc disable-immediate-force-modep
  :parents (force)
  :short "@(see force)d hypotheses are not attacked immediately"
  :long "@({
  General Form:
  ACL2 !>:disable-immediate-force-modep
 })

 <p>This event causes ACL2 to delay @(see force)d hypotheses to the next
 forcing round, rather than attacking them immediately.  See @(see
 immediate-force-modep).  Or for more basic information, first see @(see force)
 for a discussion of @(see force)d case splits.</p>

 <p>Disable-immediate-force-modep is a macro that @(see disable)s the @(see
 executable-counterpart) of the function symbol @(tsee immediate-force-modep).
 When you want to @(see disable) this mode in @(see hints), use a form such as
 one of the following (these are equivalent).</p>

 @({
  :in-theory (disable (:executable-counterpart immediate-force-modep))
  :in-theory (disable (immediate-force-modep))
 })")

(defxdoc disabledp
  :parents (theories)
  :short "Determine whether a given name or rune is disabled"
  :long "<code>
 Examples:

 :disabledp foo   ; returns a list of all disabled runes whose base
                  ; symbol is foo (see @(see rune))
 (disabledp 'foo) ; same as above (i.e., :disabledp foo)
 :disabledp (:rewrite bar . 1) ; returns t if the indicated rune is
                               ; disabled, else nil
 (disabledp (:rewrite bar . 1)); same as immediately above
 (disabledp '(:definition binary-append))
     ; returns t if the indicated definition is disabled, else nil
 (disabledp '(:d append))
     ; same as above
 </code>

 <p>Also see @(see pr), which gives much more information about the rules
 associated with a given event.</p>

 <p>@('Disabledp') takes one argument, which is a symbol, a @(see rune), or a
 runic abbreviation such as @('(:d append)') (see @(see theories)).  In the
 former case it returns the list of disabled runes associated with that name,
 in the sense that the rune's ``base symbol'' is that name (see @(see rune))
 or, if the event named is a @(tsee defmacro) event, then the list of disabled
 runes associated with the function corresponding to that macro name, if
 any (see @(see macro-aliases-table)).  In the other cases, where the argument
 is a @(see rune) or a runic abbreviation for a rune, @('disabledp') returns
 @('t') if the rune is disabled, and @('nil') otherwise.</p>

 <p>Remark for users of the @(see break-rewrite) utility.  Inside the
 @(':')@(tsee brr) loop, the computation performed by @('disabledp') takes
 place with respect to the state of the proof that is currently underway,
 rather than the global state.  For example, if you break while the prover is
 working on Subgoal 3, and the @(see hints) supplied for the proof specify
 @('(\"Subgoal 3\" :in-theory (disable foo))'), then @('disabled') will
 return the runes associated with @('foo'), regardless of whether or not those
 runes are disabled globally.</p>")

(defxdoc disassemble$
  :parents (compilation debugging)
  :short "Disassemble a function"
  :long "<p>The macro @('disassemble$') provides a convenient interface to the
 underlying @('disassemble') utility of the host Common Lisp implementation,
 which prints assembly code for a given function symbol at the terminal.  If
 the argument is instead a macro alias for a function symbol (see @(see
 macro-aliases-table)), then it prints assembly code for that function symbol
 instead.</p>

 <p>@('Disassemble$') works by including the community book
 @('books/misc/disassemble.lisp'), which defines the supporting function
 @('disassemble$-fn'), and then by calling that function.  Note that the
 arguments to @('disassemble$') are evaluated.  Also note that
 @('disassemble$') is intended as a top-level utility for the ACL2 loop, not to
 be called in code; for such a purpose, include the above book and call
 @('disassemble$-fn') directly.</p>

 @({
  Example Forms:

  (disassemble$ 'foo)
  (disassemble$ 'foo :recompile t)

  General Forms:
  (disassemble$ form)
  (disassemble$ form :recompile flg)
 })

 <p>where @('form') evaluates to a function symbol or a macro alias for a
 function symbol and @('flg') evaluates to any value.  If @('flg') is @('nil'),
 then the existing definition of that function symbol is disassembled.  But if
 @('flg') is supplied and has a value other than @('nil') or @(':default'), and
 if that function symbol is defined in the ACL2 loop (not merely in raw Lisp;
 for example, see @(see set-raw-mode)), then the disassembly will be based on a
 recompilation of that ACL2 definition.  Normally this recompilation is not
 necessary, but for some host Lisps, it may be useful; in particular, for CCL
 the above book arranges that source code information is saved, so that the
 output is annotated with such information.  When recompilation takes place,
 the previous definition is restored after disassembly is complete.  Finally,
 if @('flg') is omitted or has the value @(':default') &mdash; i.e., in the
 default case &mdash; then recompilation may take place or not, depending on
 the host Lisp.  The values of @('(@ host-lisp)') for which recompilation takes
 place by default may be found by looking at the above book, or by including it
 and evaluating the constant @('*host-lisps-that-recompile-by-default*').  As
 of this writing, CCL is the only such Lisp (because that is the one for which
 we can obtain source annotation in the output by recompiling).</p>")

(defxdoc dive-into-macros-table
  :parents (proof-builder acl2-pc::dv)
  :short "Right-associated function information for the @(see proof-builder)"
  :long "@({
  Examples:
  ACL2 !>(dive-into-macros-table (w state))
  ((CAT . EXPAND-ADDRESS-CAT)
   (LXOR . EXPAND-ADDRESS-LXOR)
 })

 <p>This table associates macro names with functions used by the interactive
 @(see proof-builder)'s @('DV') and numeric diving commands (e.g., @('3')) in
 order to dive properly into subterms.  See @(see proof-builder), in particular
 the documentation for @('DV').</p>

 <p>This table can be extended easily.  See @(see add-dive-into-macro) and also
 see @(see remove-dive-into-macro).</p>

 <p>The symbol associated with a macro should be a function symbol taking four
 arguments, in this order:</p>

 <ul>
 <li>@('car-addr')<br/>
     <blockquote>the first number in the list given to the interactive @(see
     proof-builder)'s @('DV') command</blockquote></li>
 <li>@('raw-term')<br/>
     <blockquote>the untranslated term into which we will
     dive</blockquote></li>
 <li>@('term')
     <blockquote>the translated term into which we will dive</blockquote></li>
 <li>@('wrld')
     <blockquote>the current ACL2 logical @(see world)</blockquote></li>
 </ul>

 <p>The function will normally return a list of positive integers, representing
 the (one-based) address for diving into @('term') that corresponds to the
 single-address dive into @('raw-term') by @('car-address').  However, it can
 return @('(cons str alist)'), where @('str') is a string suitable for @(tsee
 fmt) and @('args') is the corresponding alist for @(tsee fmt).</p>

 <p>Referring to the example above, @('expand-address-cat') would be such a
 function, which will be called on @('raw-term') values that are calls of
 @('cat').  See the community book @('books/misc/rtl-untranslate.lisp') for the
 definition of such a function.</p>

 <p>See @(see table) for a general discussion of tables.</p>")

(defxdoc dmr
  :parents (debugging break-rewrite accumulated-persistence)
  :short "Dynamically monitor rewrites and other prover activity"
  :long "<p>In addition to utilities that allow you to set breakpoints or print
 rewriting information to the screen &mdash; see @(see break-rewrite) &mdash;
 ACL2 provides a utility for watching the activity of the rewriter and some
 other proof processes, in real time.  This utility is called ``dmr'', which is
 an acronym for ``dynamically monitor rewrites''.  The utility comes in two
 parts: an ACL2 component that frequently updates a file (the ``dmr file'')
 containing the relevant information, and an Emacs component that frequently
 updates an Emacs buffer (the ``dmr buffer'') with the contents of that
 file.  Other editors could, in principle, be programmed to display that file;
 anyone developing such a capability is invited to contribute it to the ACL2
 community.</p>

 <p>The dmr utility can be extremely helpful for expensive proofs, especially
 when ACL2 is not providing any output to the terminal.  The @(see
 break-rewrite) and @(tsee accumulated-persistence) utilities may be a bit
 easier to use, so you might want to try those first.  But the dmr utility can
 be a very helpful debugging aide, as it can visually give you a sense of where
 ACL2 is spending its time.</p>

 <p>The Emacs portion of this utility is already loaded if you load the
 distributed Emacs file @('emacs/emacs-acl2.el').  Otherwise, invoke the
 following Emacs command, say by typing @('Control-X Control-E') after the
 right parenthesis, where @('DIR') is the directory of your ACL2
 distribution.</p>

 @({
  (load \"<DIR>/emacs/monitor.el\") ; absolute pathnames might work best
 })

 <p>You only need to do that once.  Then each time you want to observe the
 rewriter in action, invoke the following to see it displayed in a buffer,
 which we call the ``dmr buffer'':</p>

 @({
  Control-t 1
 })

 <p>But first you will need to enable monitoring at the ACL2 level:</p>

 @({
  (dmr-start)
 })

 <p>Monitoring has some cost.  So if you have started it, then at some point
 you may want to turn it off when not using it.  Any time the dmr buffer
 (generally called @('\"acl2-dmr-<user_name>\"')) is not visible, Emacs
 monitoring is turned off.  You can also turn off Emacs monitoring explicitly,
 with:</p>

 @({
  Control-t 2
 })

 <p>At the ACL2 level you can disable monitoring as follows:</p>

 @({
  (dmr-stop)
 })

 <p><i>Interpreting the dmr buffer display.</i></p>

 <p>We explain the dmr buffer display by way of the following example.  It is a
 snapshot of a dmr buffer taken from one of the community books,
 @('books/workshops/2004/legato/support/proof-by-generalization-mult.lisp').</p>

 @({
   0. (DEFTHM . WP-ZCOEF-G-MULTIPLIES)
   1. SIMPLIFY-CLAUSE
     2. Rewriting (to simplify) the atom of literal 18; argument(s) 1
     4. Rewriting (to simplify) the expansion; argument(s) 3|2
     7. Applying (:DEFINITION WP-ZCOEF-G)
  *  8. Rewriting (to simplify) the rewritten body; argument(s) 2|1|2|2
  *  13. Applying (:REWRITE MOD-ZERO . 2)
  *    14. Rewriting (to establish) the atom of hypothesis 4
  *    15. Applying (:META META-INTEGERP-CORRECT)
 })

 <p>Each line indicates an ACL2 activity that leads to the activity shown on
 the line just below it.  Moreover, lines are sometimes collapsed to make the
 display more compact.  Consider for example the first few lines.  Above, we
 are proving a theorem named @('WP-ZCOEF-G-MULTIPLIES').  Lines 1 and 2 show
 the clause simplification process invokes the rewriter on the 18th literal.
 (Recall that a clause is a disjunction of literals; for example the clause
 @('{(NOT A), (NOT B), C}') would be displayed as @('(IMPLIES (AND A B) C)').)
 This 18th literal mentioned on line 2 is a function call @('(f arg1 ...)'),
 and ``@('argument(s) 1')'' indicates that the rewriter, which works
 inside-out, is considering the first argument (``@('arg1')'').  Thus the
 display could instead have shown the following.</p>

 @({
     2. Rewriting (to simplify) the atom of literal 18
     3. Rewriting (to simplify) the first argument
     4. Rewriting (to simplify) the expansion; argument(s) 3|2
 })

 <p>But it saved space to combine lines 2 and 3.  Line 4 suggests that the
 above @('arg1') is a function call that has been opened up because of an
 @(':expand') hint or, perhaps, an expansion directed explicitly by the prover
 (as can happen during induction).  The annotation ``@('argument(s) 3|2')''
 then indicates that the rewriter is diving into the third argument of the
 expansion, and then into the second argument of that.  Let us call the result
 @('term7') (since it is the one to be considered on line 7).</p>

 <p>Now consider the next two lines:</p>

 @({
     7. Applying (:DEFINITION WP-ZCOEF-G)
  *  8. Rewriting (to simplify) the rewritten body; argument(s) 2|1|2|2
 })

 <p>Line 7 is saying that @('term7') (defined above) is modified by applying
 the definition of @('WP-ZCOEF-G') to it.  Line 8 then says that the body of
 this definition has been rewritten (with its formals bound to the actuals from
 @('term7')) and the rewriter is diving into the subterms of that rewritten
 body, as indicated.  Notice also that line 8 is the first line marked with an
 asterisk (``@('*')'') in the margin.  This line is the first that is different
 from what was shown the previous time the display was updated (about 1/10
 second earlier, by default).  When a line is marked with an asterisk, so are
 all the lines below it; so the lines without an asterisk are those that have
 been stable since the last display.  In this example we may see line 7 marked
 without an asterisk for a while, which suggests that the rule @('(:DEFINITION
 WP-ZCOEF-G)') is expensive.  (Also see @(see accumulated-persistence).)  In
 general, a line that persists for awhile without a leading asterisk can
 suggest why the proof is taking a long time.</p>

 <p>Finally let us consider line 13 and the two lines below it.  The phrase
 @('\"'Applying (:REWRITE MOD-ZERO . 2)\"') says that the indicated rewrite
 rule is being considered for application to the current term.  There are very
 weak criteria for ``Applying'' to be printed: the rule must be enabled, and
 top-level function symbols much suitably match for the term and the rule.  In
 particular, the ``Applying'' line does not imply that the rule actually
 matches the term.  That said: in the case of line 13, matching clearly was
 successful, since line 14 indicates an attempt to establish the rule's fourth
 hypothesis.</p>

 <p>Finally, note the indentation of line 14 relative to line 13.  Extra
 indentation occurs when an attempt is being made to relieve a hypothesis
 (i.e., rewrite it to @('t')).  In particular, rewrites that will be
 incorporated directly into a (top-level) literal are all indented just two
 spaces, starting with the first rewrite directly under a process such as
 @('SIMPLIFY-CLAUSE') (shown line 1 above).  If the indentation is at least the
 value of raw Lisp variable @('*dmr-indent-max*') (by default, 20), then the
 indentation is restricted to that column, but ACL2 prints @('{n}') where n is
 the column that would have been used for indentation if there were no
 maximum.</p>

 <p>You can move the cursor around in the dmr buffer even while it is being
 updated.  But emacs will attempt to keep the cursor no later than the first
 asterisk (``@('*')'') in the margin.  Thus, you can move the cursor around in
 the stable part of the display, and emacs will keep the cursor in that stable
 part.</p>

 <p>WARNING: Things could go terribly wrong if the same user runs two different
 ACL2 sessions with dmr active, because the same file will be written by two
 different ACL2 processes.</p>

 <p>WARNING: For dmr to work, emacs and ACL2 need to be run on the same machine
 because the file used to communicate between ACL2 and emacs is under
 @('/tmp').  Except, you can probably hack around that restriction by changing
 @('*dmr-file-name*') in ACL2 (in raw Lisp) and correspondingly in Emacs file
 @('monitor.el').</p>

 <p>More generally, advanced users are welcome to search for the string</p>

 @({
  User-settable dmr variables
 })

 <p>in ACL2 files @('interface-raw.lisp') and @('emacs/monitor.el') in order to
 customize their dmr environments.</p>

 <p>In order to update the dmr file with the latest stack information,
 interrupt ACL2 and then evaluate: @('(dmr-flush)').  In order to support
 resumption of the interrupted proof (assuming your host Common Lisp supports
 resumption), evaluation of @('(dmr-start)') will automatically enable the
 debugger if it is not already enabled and not fully disabled with value
 @(':never') (see @(see set-debugger-enable)).  If such automatic enabling
 takes place, then @('(dmr-stop)') will restore the old setting of the debugger
 unless, after @('(dmr-start)') enables the debugger but before @('(dmr-stop)')
 is called, you call @(tsee set-debugger-enable) (or more precisely: function
 @('set-debugger-enable-fn') is called).</p>

 <p>Note for users of the experimental extension ACL2(p) (see @(see
 parallelism)): when waterfall-parallelism has been set to a non-@('nil') value
 (see @(see set-waterfall-parallelism)), statistics about parallel execution
 are printed instead of the usual information.</p>")

(defxdoc do-not
  :parents (hints)
  :short "Instruct the theorem prover not to do certain things."

  :long "<p>See @(see hints) for documentation about the @(':do-not') keyword
 for prover @(':hints').</p>

 <p>See @(see do-not-hint) for documentation about the @('do-not') macro that
 controls a mechanism for automatically suggesting @(':do-not') and
 @(':do-not-induct') hints.</p>")

(defxdoc doc

; To see why we say "Usually" below, for accessing book documentation, consider
; the following examples.  At the terminal, execute:

; (include-book "ihs/basic-definitions" :dir :system)

; Then execute:

; :doc ihs

; You'll see a response that says that there is no documentation for IHS.  Now
; execute:

; (include-book "ihs/ihs-doc-topic" :dir :system)

; This time, execution of :doc ihs provides a good result.

  :parents (documentation)
  :short "@(see Documentation) at the terminal"
  :long "<p>The @(':doc') command may be used at the ACL2 prompt to access the
 ACL2 system @(see documentation).  Usually it may also access documentation
 defined in books.  However, most users will probably access the ACL2
 documentation in other ways; see @(see documentation).  In particular,
 consider using the @(`(:raw (combined-manual-ref))`), for topics documented in
 the ACL2 community @(see books) or in the ACL2 system (where the latter are
 rearranged).</p>

 <p>Alternatively, consider using the ACL2-doc Emacs browser; see @(see
 acl2-doc).</p>

 @({
  Examples:
  ACL2 !>:doc DEFTHM          ; print documentation of DEFTHM
  ACL2 !>:doc logical-name    ; print documentation of LOGICAL-NAME

  General Form:
  ACL2>:doc name
 })

 <p>Note that links are always printed with respect to the @('\"ACL2\"')
 package (that is, as though the current package were @('\"ACL2\"')).  So for
 example, a link to the present topic will be displayed as @('[doc]'), not as
 @('[acl2::doc]'), regardless of the current package or the package of the
 topic being displayed.  Such links can thus take you to topics in the acl2-doc
 Emacs browser (see @(see acl2-doc)).</p>")

(defxdoc documentation

; This Lisp comment documents source files that mention locations of various
; manuals (web-based and text-based).  All relative file names are with respect
; to the ACL2 sources directory.  In some cases the reference won't be to the
; word "documentation", but rather, to a doc topic, e.g.,
; "href="http://www.cs.utexas.edu/users/moore/acl2...".

; - This file (books/system/doc/acl2-doc.lisp), in particular where it mentions
;   "ACL2+Books Manual" near the top
; - doc/home-page.lisp
; - emacs/acl2-doc.el
; - installation/*.html
; - At UT, /u/www/users/moore/publications/, in particular, hyper-card.html.
; - books/Readme.html

  :parents (acl2)
  :short "Information about options for downloading and viewing the ACL2
 documentation, contributing documentation, and the available tools for
 documenting your own books."

  :long "<h3>Available Documentation</h3>

 <p>If you are new to ACL2, see the @(see acl2-tutorial) for introductory
 tours, tutorials, and information about textbooks about ACL2.  The <a
 href='http://www.cs.utexas.edu/users/moore/acl2'>ACL2 home page</a> also
 provides many links to academic publications about ACL2, including the ACL2
 Workshop series.</p>

 <p>Beyond these resources, there is a vast <b>ACL2+Books Manual</b> with
 reference material covering the ACL2 system itself and also many @(see
 community-books).  There are a few ways to access the manual:</p>

 <ul>

 <li><b>The online version (recommended).</b> If you expect to have an internet
 connection while using the documentation, you may prefer to use the online
 version of the @(`(:raw (combined-manual-ref))`).</li>

 <li><b>A local version.</b> If you sometimes work without an internet
 connection, you can <a href='download/'>download</a> a local copy of any
 web-based XDOC manual using the \"down arrow\" icon at the top of the page.
 You can alternately build your own copy of the manual; see <i>Building
 the manual</i> in @(see books-certification).</li>

 <li><b>The ACL2-Doc Emacs version.</b> If you would like to view the
 documentation using Emacs instead of a web browser, there is a feature-rich
 Emacs-based documentation browser provided by the ACL2 system.  See @(see
 acl2::acl2-doc) for details.</li>

 </ul>

 <p>While you are using ACL2, you can get documentation at the terminal with
 the @(':')@(tsee doc) command, e.g., by typing @(':doc rewrite').  This is
 often handy, but note that it won't show you any documentation for books that
 you haven't loaded yet!</p>

 <p>Separately from the ACL2+Books Manual, the <u>ACL2 User's Manual</u> is
 distributed with ACL2.  This is much like the ACL2+Books Manual but it does
 not include documentation from the books.  A web-based copy is included with
 the ACL2 distribution in directory @('doc/manual/'), and you can easily get to
 it by opening file @('doc/home-page.html') in your browser.</p>


 <h3>Documenting Your Books</h3>

 <p>Documentation is written using @(see xdoc), and may be found in the @(see
 community-books).  Everyone is welcome to edit and contribute to that
 documentation.  In particular, you are welcome to edit the book that contains
 ACL2 system documentation, @('books/system/doc/acl2-doc.lisp').  (Please do
 not edit ACL2 source file @('doc.lisp'), which is generated from that book.
 More generally, edit only files under the @('books/') directory.)</p>

 <p>You can also use XDOC to document your own books and to build custom manuals
 for your organization.</p>

 <h3>Other Resources</h3>

 <p>If you want documentation on an ACL2 function or macro that is not
 documented, there are still several alternatives.</p>

 @({
  ACL2 !>:args fn
 })

 <p>will print the arguments and some other relevant information about the
 named function or macro.  This information is all gleaned from the definition
 and hence this is a definitive way to determine if @('fn') is defined as a
 function or macro.</p>

 <p>You might also want to type:</p>

 @({
  ACL2 !>:pc fn
 })

 <p>which will print the @(see command) that introduced @('fn').  You should
 see @(see command-descriptor) for details on the kinds of input you can give
 the @(':')@(tsee pc) command.</p>")

(defxdoc documentation-copyright
  :parents (copyright documentation)
  :short "Copyright and authorship of documentation"
  :long "<p>There are two manuals associated with ACL2: the ACL2 User's Manual
 and the ACL2+Books Manual.  See @(see documentation).  The former is
 distributed with ACL2, you can reach many links into it from the ACL2 home
 page.  The latter may be preferred for routine browsing, since it extends the
 ACL2 User's Manual with documentation obtained from the @(see
 community-books).</p>

 <p>The ACL2 User's Manual is copyrighted under the terms of the @('LICENSE')
 file distributed with ACL2.  Its original authors are the ACL2 authors, but it
 is now defined in an ACL2 community book, @('books/system/doc/acl2-doc.lisp'),
 so that members of the ACL2 community may contribute to it.</p>

 <p>The ACL2+Books Manual is a mechanically generated mashup derived from both
 the ACL2 User's Manual and the @(see community-books).  The ACL2+Books Manual
 thus has contributions from many authors.  At the top of each topic, in a line
 under the topic name, you will generally find either ``ACL2 Sources'' or the
 name of a Community Book.  In the former case, the text is from the ACL2
 User's Manual and is authored, copyrighted, and licensed as per the ACL2 @(see
 copyright).  When a book is named, the content was extracted from that book
 which may be inspected for authorship, copyright, and license terms.</p>

 <p>There are two standard tools for browsing these manuals, other than using
 the @(':')@(tsee doc) command at the terminal.</p>

 <ul>

 <li><b>The ACL2 @(csee xdoc) Fancy Viewer.</b> This tool, written by Jared
 Davis, is included with the web-based version of each manual.  Information on
 copyright and licensing are provided in <a href='LICENSE'>its LICENSE
 file</a>.</li>

 <li><b>The @(see acl2-doc) Emacs browser.</b> This tool, authored by Matt
 Kaufmann and J Strother Moore, is distributed with ACL2 and is licensed under
 the terms of the @('LICENSE') file distributed with ACL2.</li>

 </ul>")

(defxdoc double-rewrite
  :parents (rewrite)
  :short "Cause a term to be rewritten twice"
  :long "<p>Logically, @('double-rewrite') is the @(tsee identity) function:
 @('(double-rewrite x)') is equal to @('x').  However, the ACL2 rewriter treats
 calls of @('double-rewrite') in the following special manner.  When it
 encounters a term @('(double-rewrite u)'), it first rewrites @('u') in the
 current context, and then the rewriter rewrites the result.</p>

 <p>Such double-rewriting is rarely necessary, but it can be useful when
 rewriting under non-trivial equivalence relations (see @(see equivalence)).
 The following example will illustrate the issue.</p>

 @({
  ; Define an equivalence relation.
  (defun my-equiv (x y)
    (equal x y))
  (defequiv my-equiv)

  ; Define a unary function whose argument is preserved by my-equiv.
  (defun foo (x)
    (declare (ignore x))
    t)
  (defcong my-equiv equal (foo x) 1)

  ; Define some other unary functions.
  (defun g (x) x)
  (defun h1 (x) x)
  (defun h2 (x) x)

  ; Prove some lemmas and then disable the functions above.
  (defthm lemma-1
    (my-equiv (h1 x) (h2 x)))
  (defthm lemma-2
    (foo (h2 x)))
  (defthm lemma-3
    (implies (foo x)
             (equal (g x) x)))
  (in-theory (union-theories (theory 'minimal-theory)
                             '(lemma-1 lemma-2 lemma-3
                               my-equiv-implies-equal-foo-1)))

  ; Attempt to prove a simple theorem that follows ``obviously'' from the
  ; events above.
  (thm (equal (g (h1 a)) (h1 a)))
 })

 <p>We might expect the proof of this final @('thm') to succeed by the
 following reasoning.  It is immediate from @('lemma-3') provided we can
 establish @('(foo (h1 a))').  By the @('defcong') event above, we know that
 @('(foo (h1 a))') equals @('(foo (h2 a))') provided @('(my-equiv (h1 a) (h2
 a))'); but this is immediate from @('lemma-1').  And finally, @('(foo (h2
 a))') is true by @('lemma-2').</p>

 <p>Unfortunately, the proof fails.  But fortunately, ACL2 gives the following
 useful warning when @('lemma-3') is submitted:</p>

 @({
  ACL2 Warning [Double-rewrite] in ( DEFTHM LEMMA-3 ...):  In the :REWRITE
  rule generated from LEMMA-3, equivalence relation MY-EQUIV is maintained
  at one problematic occurrence of variable X in hypothesis (FOO X),
  but not at any binding occurrence of X.  Consider replacing that occurrence
  of X in this hypothesis with (DOUBLE-REWRITE X).  See :doc double-
  rewrite for more information on this issue.
 })

 <p>We can follow the warning's advice by changing @('lemma-3') to the
 following.</p>

 @({
  (defthm lemma-3
    (implies (foo (double-rewrite x))
             (equal (g x) x)))
 })

 <p>With this change, the proof succeeds for the final @('thm') above.</p>

 <p>In practice, it should suffice for users to follow the advice given in the
 ``@('Double-rewrite')'' warnings, by adding calls of @('double-rewrite')
 around certain variable occurrences.  But this can cause inefficiency in large
 proof efforts.  For that reason, and for completeness, it seems prudent to
 explain more carefully what is going on; and that is what we do for the
 remainder of this @(see documentation) topic.  Optionally, also see the paper
 ``Double Rewriting for Equivalential Reasoning in ACL2'' by Matt Kaufmann and
 J Strother Moore, in the proceedings of the 2006 ACL2 Workshop (paper is
 published in the <a href='http://portal.acm.org/toc.cfm?id=1217975'>ACM
 Digital Library</a>); you might also find it for free <a
 href='http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.90.7190&rep=rep1&type=pdf'>here</a>.</p>

 <p><b>Suggesting congruence rules.</b></p>

 <p>Sometimes the best way to respond to a ``@('Double-rewrite')'' warning may
 be to prove a congruence rule.  Consider for example this rule.</p>

 @({
  (defthm insert-sort-is-id
    (perm (insert-sort x) x))
 })

 <p>Assuming that @('perm') has been identified as an @(see equivalence)
 relation (see @(see defequiv)), we will get the following warning.</p>

 @({
  ACL2 Warning [Double-rewrite] in ( DEFTHM INSERT-SORT-IS-ID ...):
  In a :REWRITE rule generated from INSERT-SORT-IS-ID, equivalence relation
  PERM is maintained at one problematic occurrence of variable X in the
  right-hand side, but not at any binding occurrence of X.  Consider
  replacing that occurrence of X in the right-hand side with
  (DOUBLE-REWRITE X).  See :doc double-rewrite for more information on
  this issue.
 })

 <p>The problem is that the second occurrence of @('x') (the right-hand side of
 the rule @('insert-sort-is-id')) is in a context where @('perm') is to be
 maintained, yet in this example, the argument @('x') of @('insert-sort') on
 the left-hand side of that rule is in a context where @('perm') will not be
 maintained.  This can lead one to consider the possibility that @('perm')
 could be maintained in that left-hand side occurrence of @('x'), and if so, to
 prove the following congruence rule.</p>

 @({
  (defcong perm perm (insert-sort x) 1)
 })

 <p>This will eliminate the above warning for @('insert-sort-is-id').  More
 important, this @(tsee defcong) event would probably be useful, since it would
 allow rewrite rules with equivalence relation @('perm') to operate on the
 first argument of any call of @('insert-sort') whose context calls for
 maintaining @('perm').</p>

 <p><b>Details on double-rewrite.</b></p>

 <p>The reader who wants these details may first wish to see @(see equivalence)
 for relevant review.</p>

 <p>The ACL2 rewriter takes a number of contextual arguments, including the
 generated equivalence relation being maintained (see @(see congruence)) and an
 association list that maps variables to terms.  We call the latter alist the
 @('unify-subst') because it is produced by unifying (actually matching) a
 pattern against a current term; let us explain this point by returning to the
 example above.  Consider what happens when the rewriter is given the top-level
 goal of the @('thm') above.</p>

 @({
  (equal (g (h1 a)) (h1 a))
 })

 <p>This rewrite is performed with the empty alist (@('unify-subst')), and is
 begun by rewriting the first argument (in that same empty
 @('unify-subst')):</p>

 @({
  (g (h1 a))
 })

 <p>Note that the only equivalence relation being maintained at this point is
 @('equal').  Now, the rewriter notices that the left-hand side of
 @('lemma-3'), which is @('(g x)'), matches @('(g (h1 a))').  The rewriter thus
 creates a @('unify-subst') binding @('x') to @('(h1 a)'): @('((x . (h1 a)))').
 It now attempts to rewrite the hypothesis of @('lemma-3') to @('t') under this
 @('unify-subst').</p>

 <p>Consider what happens now if the hypothesis of @('lemma-3') is @('(foo
 x)').  To rewrite this hypothesis under a @('unify-subst') of @('((x . (h1
 a)))'), it will first rewrite @('x') under this @('unify-subst').  The key
 observation here is that this rewrite takes place simply by returning the
 value of @('x') in the @('unify-subst'), namely @('(h1 a)').  No further
 rewriting is done!  The efficiency of the ACL2 rewriter depends on such
 caching of previous rewriting results.</p>

 <p>But suppose that, instead, the hypothesis of @('lemma-3') is @('(foo
 (double-rewrite x))').  As before, the rewriter dives to the first argument of
 this call of @('foo').  But this time the rewriter sees the call
 @('(double-rewrite x)'), which it handles as follows.  First, @('x') is
 rewritten as before, yielding @('(h1 a)').  But now, because of the call of
 @('double-rewrite'), the rewriter takes @('(h1 a)') and rewrites it under the
 empty @('unify-subst').  What's more, because of the @('defcong') event above,
 this rewrite takes place in a context where it suffices to maintain the
 equivalence relation @('my-equiv').  This allows for the application of
 @('lemma-1'), hence @('(h1 a)') is rewritten (under @('unify-subst') =
 @('nil')) to @('(h2 a)').  Popping back up, the rewriter will now rewrite the
 call of @('foo') to @('t') using @('lemma-2').</p>

 <p>The example above explains how the rewriter treats calls of
 @('double-rewrite'), but it may leave the unfortunate impression that the user
 needs to consider each @(':')@(tsee rewrite) or @(':')@(tsee linear) rule
 carefully, just in case a call of @('double-rewrite') may be appropriate.
 Fortunately, ACL2 provides a ``[Double-rewrite]'' warning to inform the user
 of just this sort of situation.  If you don't see this warning when you submit
 a (@(':')@(tsee rewrite) or @(':')@(tsee linear)) rule, then the issue
 described here shouldn't come up for that rule.  Such warnings may appear for
 hypotheses or right-hand side of a @(':')@(tsee rewrite) rule, and for
 hypotheses or full conclusion (as opposed to just the trigger term) of a
 @(':')@(tsee linear) rule.</p>

 <p>If you do see a ``[Double-rewrite]'' warning, then should you add the
 indicated call(s) of @('double-rewrite')?  At the time of writing this @(see
 documentation), the answer is not clear.  Early experiments with double
 rewriting suggested that it may be too expensive to call @('double-rewrite')
 in every instance where a warning indicates that there could be an advantage
 to doing so.  And at the time of this writing, the ACL2 regression suite has
 about 1900 such warnings (but note that books were developed before
 @('double-rewrite') or the ``[Double-rewrite]'' warning were implemented),
 which suggests that one can often do fine just ignoring such warnings.
 However, it seems advisable to go ahead and add the calls of
 @('double-rewrite') indicated by the warnings unless you run across efficiency
 problems caused by doing so.  Of course, if you decide to ignore all such
 warnings you can execute the event:<br></br>

 @('(')@(tsee set-inhibit-warnings)@(' \"Double-rewrite\")').</p>

 <p>Finally, we note that it is generally not necessary to call
 @('double-rewrite') in order to get its effect in the following case, where
 the discussion above might have led one to consider a call of
 @('double-rewrite'): a hypothesis is a variable, or more generally, we are
 considering a variable occurrence that is a branch of the top-level @('IF')
 structure of a hypothesis.  The automatic handling of this case, by a form of
 double rewriting, was instituted in ACL2 Version_2.9 and remains in place with
 the introduction of @('double-rewrite').  Here is a simple illustrative
 example.  Notice that @('foo-holds') applies to prove the final @(tsee thm)
 below, even without a call of @('double-rewrite') in the hypothesis of
 @('foo-holds'), and that there is no ``[Double-rewrite]'' warning when
 submitting @('foo-holds').</p>

 @({
  (encapsulate
   (((foo *) => *)
    ((bar *) => *))

   (local (defun foo (x) (declare (ignore x)) t))
   (local (defun bar (x) (declare (ignore x)) t))

   (defthm foo-holds
     (implies x
              (equal (foo x) t)))
   (defthm bar-holds-propositionally
     (iff (bar x) t)))

  (thm (foo (bar y)))
 })")

(defxdoc e/d
  :parents (theories theory-functions)
  :short "Enable/disable rules"
  :long "<p>The macro @('e/d') creates theory expressions for use in @(tsee
 in-theory) hints and events.  It provides a convenient way to @(tsee enable)
 and @(tsee disable) simultaneously, without having to write arcane theory
 expressions.  For related utilities, see @(see enable) and see @(see
 disable).</p>

 @({
  Examples:
  (e/d (lemma1 lemma2))          ; equivalent to (enable lemma1 lemma2)
  (e/d () (lemma))               ; equivalent to (disable lemma)
  (e/d (lemma1) (lemma2 lemma3)) ; Enable lemma1 then disable lemma2, lemma3.
  (e/d () (lemma1) (lemma2))     ; Disable lemma1 then enable lemma2.

  General Form:
  (e/d enables-0 disables-0 ... enables-n disables-n)
 })

 <p>where each @('enables-i') and @('disables-i') is a list of runic
 designators; see @(see theories), see @(see enable), and see @(see
 disable).</p>

 <p>The @('e/d') macro takes any number of lists suitable for the @(tsee
 enable) and @(tsee disable) macros, and creates a theory that is equal to
 @('(current-theory :here)') after executing the following commands.</p>

 @({
  (in-theory (enable . enables-0))
  (in-theory (disable . disables-0))
  ...
  (in-theory (enable . enables-n))
  (in-theory (disable . disables-n))
 })")

(defxdoc early-termination
  :parents (parallel-programming)
  :short "Early termination for @(tsee pand) and @(tsee por)."
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 <p>The evaluation of @('(and expr1 expr2)') returns @('nil') if @('expr1')
 evaluates to @('nil'), avoiding the evaluation of @('expr2').  More generally,
 the evaluation of @('(and expr1 expr2 ... exprk)') terminates with a return
 value of @('nil') as soon as any @('expri') evaluates to @('nil') &mdash; no
 @('exprj') is evaluated in this case for @('j > i').  This so-called ``lazy
 evaluation'' of @(tsee and) terms can thus save some computation; roughly
 speaking, the smaller the @('i'), the more computation is saved.</p>

 <p>If the above call of @(tsee and) is replaced by its parallel version,
 @(tsee pand), then there can be even more opportunity for skipping work.  The
 arguments to @(tsee pand) can be evaluated in parallel, in which case the
 first such evaluation that returns with a value of @('nil'), if any, causes
 the remaining such evaluations to abort.</p>

 <p>Consider the following functions that compute whether a tree is valid (see
 @(see granularity) for a discussion of the granularity form).</p>

 @({
  (defun valid-tip (x)
    (declare (xargs :guard t))
    (or (eq x 'A)
        (eq x 'T)
        (eq x 'C)
        (eq x 'G)))

  (defun pvalid-tree (x depth)
    (declare (xargs :guard (natp depth)))
    (if (atom x)
        (valid-tip x)
      (pand (declare (granularity (< depth 10)))
            (pvalid-tree (car x) (1+ depth))
            (pvalid-tree (cdr x) (1+ depth)))))
 })

 <p>We would like to stop execution as soon as any tip is found to be invalid.
 So, when computing the conjunction of terms by using @(tsee pand), once one of
 those terms evaluates to @('nil'), the computations for the other terms are
 aborted and the @(tsee pand) call returns @('nil').  By using @(tsee pand), we
 can in principle attain a speedup factor greater than the number of available
 cores.</p>

 <p>The concept of early termination also applies to @(tsee por), except that
 early termination occurs when an argument evaluates to non-@('nil').</p>")

(defxdoc ec-call
  :parents (guard acl2-built-ins)
  :short "Execute a call in the ACL2 logic instead of raw Lisp"
  :long "<p>The name ``@('ec-call')'' represents ``executable-counterpart
 call.''  This utility is intended for users who are familiar with guards.  See
 @(see guard) for a general discussion of guards.</p>

 <p>Logically, @('ec-call') behaves like the identity macro; during proofs,
 @('(ec-call TERM)') is typically replaced quickly by @('TERM') during a proof
 attempt.  However, @('ec-call') causes function calls to be evaluated in the
 ACL2 logic rather than raw Lisp, as explained below.</p>

 @({
  General Form:
  (ec-call (fn term1 ... termk))
 })

 <p>where @('fn') is a known function symbol other than those in the list that
 is the value of the constant @('*ec-call-bad-ops*').  (But see the Final Note
 below for an exception pertaining to inlining.)  In particular, @('fn') is not
 a macro.  Semantically, @('(ec-call (fn term1 ... termk))') equals @('(fn
 term1 ... termk)').  However, this use of @('ec-call') has two effects.</p>

 <blockquote>

 <p>(1) @(see Guard) verification generates no proof obligations from the guard
 of @('fn') for this call.  Indeed, guards need not have been verified for
 @('fn').</p>

 <p>(2) During evaluation, after the arguments of @('fn') are evaluated as
 usual, the executable-counterpart of @('fn') is called, rather than its
 submitted version (see @(see evaluation)).  That is, the call of @('fn') is
 made on its evaluated arguments as though this call is being made in the ACL2
 top-level loop, rather than in raw Lisp.  In particular, the @(see guard) of
 @('fn') is checked, at least by default (see @(see
 set-guard-checking)).</p></blockquote>

 <p>The use of @('ec-call') does not turn off guard-checking, but that can be
 accomplished by using @(tsee with-guard-checking) as well.  Consider the
 following example.</p>

 @({
 (defun f1 (x)
   (declare (xargs :guard t))
   (ec-call (nth t x)))
 })

 <p>This definition is admitted, but evaluation of @('(f1 '(a b c))')
 nevertheless causes a guard violation (at least, by default).  However, if
 instead we submit the following definition, then there is no guard violation
 for that call of @('f1').</p>

 @({
 (defun f1 (x)
   (declare (xargs :guard t))
   (with-guard-checking nil (ec-call (nth t x))))
 })

 <p>Note that in the term @('(ec-call (fn term1 ... termk))'), only the
 indicated call of @('fn') is made in the logic; each @('termi') is evaluated
 in the normal manner.  If you want an entire term evaluated in the logic, wrap
 @('ec-call') around each function call in the term (other than calls of
 @('if') and @('ec-call')).</p>

 <p><b>Technical Remark</b> (probably best ignored).  During evaluation of a
 call of @(tsee defconst) or @(tsee defpkg) in raw Lisp, a form @('(ec-call (fn
 term1 ... termk))') is treated as @('(fn term1 ... termk)'), that is, without
 calling the executable-counterpart of @('fn').  This situation occurs when
 loading a compiled file (or expansion file) on behalf of an @(tsee
 include-book) event.  The reason is technical: executable-counterparts are
 defined below a book's events in the book's compiled file.  End of Technical
 Remark.</p>

 <p>Here is another small example.  We define @('foo') recursively but with
 guard verification inhibited on the recursive call, which is to be evaluated
 in the ACL2 logic.</p>

 @({
  ACL2 !>(defun foo (x y)
          (declare (xargs :guard (consp y)))
          (if (consp x)
              (cons (car x) (ec-call (foo (cdr x) (cdr y))))
            (car y)))

  The admission of FOO 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 could deduce no constraints on the type of FOO.

  Computing the guard conjecture for FOO....

  The guard conjecture for FOO is trivial to prove.  FOO is compliant
  with Common Lisp.

  Summary
  Form:  ( DEFUN FOO ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FOO
  ACL2 !>(foo '(2 3 4 5) '(6 7))

  ACL2 Error in TOP-LEVEL:  The guard for the function call (FOO X Y),
  which is (CONSP Y), is violated by the arguments in the call
  (FOO '(4 5) NIL).  To debug see :DOC print-gv, see :DOC trace, and
  see :DOC wet.  See :DOC set-guard-checking for information about suppressing
  this check with (set-guard-checking :none), as recommended for new
  users.

  ACL2 !>
 })

 <p>The error above arises because eventually, @('foo') recurs down to a value
 of parameter @('y') that violates the guard.  This is clear from tracing (see
 @(see trace$) and see @(see trace)).  Each call of the executable-counterpart
 of @('foo') checks the guard and then invokes the submitted version of
 @('foo') (see @(see evaluation)).  The submitted version calls the
 executable-counterpart on the recursive call.  When the guard check fails we
 get a violation.</p>

 @({
  ACL2 !>(trace$ foo)
   ((FOO))
  ACL2 !>(foo '(2 3 4 5) '(6 7))
  1> (ACL2_*1*_ACL2::FOO (2 3 4 5) (6 7))
    2> (FOO (2 3 4 5) (6 7))
      3> (ACL2_*1*_ACL2::FOO (3 4 5) (7))
        4> (FOO (3 4 5) (7))
          5> (ACL2_*1*_ACL2::FOO (4 5) NIL)

  ACL2 Error in TOP-LEVEL:  The guard for the function call (FOO X Y),
  which is (CONSP Y), is violated by the arguments in the call
  (FOO '(4 5) NIL).  To debug see :DOC print-gv, see :DOC trace, and
  see :DOC wet.  See :DOC set-guard-checking for information about suppressing
  this check with (set-guard-checking :none), as recommended for new
  users.

  ACL2 !>
 })

 <p>If we turn off guard errors then we can see the trace as above, but where
 we avoid calling the raw Lisp function when the guard fails to hold.</p>

 @({
  ACL2 !>:set-guard-checking nil

  Masking guard violations but still checking guards except for self-
  recursive calls.  To avoid guard checking entirely, :SET-GUARD-CHECKING
  :NONE.  See :DOC set-guard-checking.

  ACL2 >(foo '(2 3 4 5) '(6 7))
  1> (ACL2_*1*_ACL2::FOO (2 3 4 5) (6 7))
    2> (FOO (2 3 4 5) (6 7))
      3> (ACL2_*1*_ACL2::FOO (3 4 5) (7))
        4> (FOO (3 4 5) (7))
          5> (ACL2_*1*_ACL2::FOO (4 5) NIL)
            6> (ACL2_*1*_ACL2::FOO (5) NIL)
              7> (ACL2_*1*_ACL2::FOO NIL NIL)
              <7 (ACL2_*1*_ACL2::FOO NIL)
            <6 (ACL2_*1*_ACL2::FOO (5))
          <5 (ACL2_*1*_ACL2::FOO (4 5))
        <4 (FOO (3 4 5))
      <3 (ACL2_*1*_ACL2::FOO (3 4 5))
    <2 (FOO (2 3 4 5))
  <1 (ACL2_*1*_ACL2::FOO (2 3 4 5))
  (2 3 4 5)
  ACL2 >
 })

 <p>Final note: although in general, the form @('(ec-call (fn term1
 ... termk))') is only legal if @('fn') is a function symbol, such a form is
 also legal if @('fn') is introduced with @(tsee defun-inline), or with @(tsee
 define) using keyword argument @(':inline t').  In those cases, @('fn') is a
 macro whose calls expand to corresponding calls of @('fn$INLINE'), the symbol
 in the same package as @('fn') but with the string @('\"$INLINE\"') added as a
 suffix to the @(tsee symbol-name) of @('fn').  We do not however extend this
 exception to macros in general, even when @(tsee add-macro-fn) has been
 invoked.  Consider the following example.</p>

 @({
 (encapsulate
  ()
  (defun foo () nil)
  (defun bar () t)
  (defmacro mac () nil)
  (add-macro-alias mac foo)
  (local (add-macro-alias mac bar))
  (defun h () (ec-call (mac)))
  (defthm bad (h)))
 })

 <p>Consider what would happen if this were legal, where @('(ec-call (mac))')
 used the macro-alias, @('foo'), for @('mac').  Then in the first pass of the
 @(tsee encapsulate) form above, the final @(tsee defthm) event would prove,
 since (ec-call (mac)) is treated as (ec-call (bar)).  But on the second pass,
 ACL2 would store @('bad') as a theorem even though @('(h)') would evaluate to
 @('nil'), since the macro-alias of @('mac') is @('foo') on the second
 pass.</p>")

(defxdoc eighth
  :parents (nth acl2-built-ins)
  :short "Eighth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc elim
  :parents (rule-classes)
  :short "Make a destructor elimination rule"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 <p>The following example of an @(':elim') rule is an important one, and is
 built into ACL2.</p>

 @({
  (defaxiom car-cdr-elim
    (implies (consp x)
             (equal (cons (car x) (cdr x)) x))
    :rule-classes :elim)
 })

 <p>The class of @(':elim') rules is fundamentally quite different from the
 more common class of @(':')@(tsee rewrite) rules.  Briefly put, a
 @(':rewrite') rule replaces instances of its left-hand side with corresponding
 instances of its right-hand side.  But an @(':elim') rule, on the other hand,
 has the effect of generalizing so-called ``destructor'' function applications
 to variables.  In essence, applicability of a @(':rewrite') rule is based on
 matching its left-hand side, while applicability of an @(':elim') rule is
 based on the presence of at least one destructor term.</p>

 <p>For example, a conjecture about @('(car x)') and @('(cdr x)') can be
 replaced by a conjecture about new variables @('x1') and @('x2'), as shown in
 the following example.  (Run the command @(':mini-proveall') and search for
 @('CAR-CDR-ELIM') to see the full proof containing this excerpt.)</p>

 @({
  Subgoal *1/1'
  (IMPLIES (AND (CONSP X)
                (TRUE-LISTP (REV (CDR X))))
           (TRUE-LISTP (APP (REV (CDR X)) (LIST (CAR X))))).

  The destructor terms (CAR X) and (CDR X) can be eliminated by using
  CAR-CDR-ELIM to replace X by (CONS X1 X2), (CAR X) by X1 and (CDR X)
  by X2.  This produces the following goal.

  Subgoal *1/1''
  (IMPLIES (AND (CONSP (CONS X1 X2))
                (TRUE-LISTP (REV X2)))
           (TRUE-LISTP (APP (REV X2) (LIST X1)))).

  This simplifies, using primitive type reasoning, to

  Subgoal *1/1'''
  (IMPLIES (TRUE-LISTP (REV X2))
           (TRUE-LISTP (APP (REV X2) (LIST X1)))).
 })

 <p>The resulting conjecture is often simpler and hence more amenable to
 proof.</p>

 <p>The application of an @(':elim') rule thus replaces a variable by a term
 that contains applications of so-called ``destructor'' functions to that
 variable.  The example above is typical: the variable @('x') is replaced by
 the term @('(cons (car x) (cdr x))'), which applies a so-called
 ``constructor'' function, @(tsee cons), to applications @('(car x)') and
 @('(cdr x)') of destructor functions @(tsee car) and @(tsee cdr) to that same
 variable, @('x').  But that is only part of the story.  ACL2 then generalizes
 the destructor applications @('(car x)') and @('(cdr x)') to new variables
 @('x1') and @('x2'), respectively, and ultimately the result is a simpler
 conjecture.</p>

 <p>More generally, the application of an @(':elim') rule replaces a variable
 by a term containing applications of destructors; there need not be a
 clear-cut notion of ``constructor.''  But the situation described above is
 typical, and we will focus on it, giving full details when we introduce the
 ``General Form'' below.</p>

 <p>Notice that the situation can be complicated a bit by a rule's hypotheses.
 For example, the replacement specified by the rule @('car-cdr-elim') (shown
 near the beginning of this discussion) is only valid if the variable being
 replaced is a cons structure.  Thus, when ACL2 applies @('car-cdr-elim') to
 replace a variable @('v'), it will split into two cases: one case in which
 @('(consp v)') is true, in which @('v') is replaced by @('(cons (car v) (cdr
 v))') and then @('(car v)') and @('(cdr v)') are generalized to new variables;
 and one case in which @('(consp v)') is false.  In practice, @('(consp v)') is
 often provable, perhaps even literally present as a hypotheses; then of course
 there is no need to introduce the second case.  That is why there is no such
 second case in the example above.</p>

 <p>You might find @(':elim') rules to be useful whenever you have in mind a
 data type that can be built up from its fields with a ``constructor'' function
 and whose fields can be accessed by corresponding ``destructor'' functions.
 So for example, if you have a ``house'' data structure that represents a house
 in terms of its address, price, and color, you might have a rule like the
 following.</p>

 @({
  Example:
  (implies (house-p x)
           (equal (make-house (address x)
                              (price x)
                              (color x))
                  x))
 })

 <p>The application of such a rule is entirely analogous to the application of
 the rule @('car-cdr-elim') discussed above.  We discuss such rules and their
 application more carefully below.</p>

 @({
  General Form:
  (implies hyp (equiv lhs x))
 })

 <p>where @('equiv') is a known equivalence relation (see @(see defequiv));
 @('x') is a variable symbol; and @('lhs') contains one or more terms (called
 ``destructor terms'') of the form @('(fn v1 ... vn)'), where @('fn') is a
 function symbol and the @('vi') are distinct variable symbols, @('v1'), ...,
 @('vn') include all the variable symbols in the formula, no @('fn') occurs in
 @('lhs') in more than one destructor term, and all occurrences of @('x') in
 @('lhs') are inside destructor terms.</p>

 <p>To use an @(':elim') rule, the theorem prover waits until a conjecture has
 been maximally simplified.  It then searches for an instance of some
 destructor term @('(fn v1 ... vn)') in the conjecture, where the instance for
 @('x') is some variable symbol, @('vi'), and every occurrence of @('vi')
 outside the destructor terms is in an @('equiv')-hittable position.  If such
 an instance is found, then the theorem prover instantiates the @(':elim')
 formula as indicated by the destructor term matched; splits the conjecture
 into two goals, according to whether the instantiated hypothesis, @('hyp'),
 holds; and in the case that it does hold, generalizes all the instantiated
 destructor terms in the conjecture to new variables and then replaces @('vi')
 in the conjecture by the generalized instantiated @('lhs').  An occurrence of
 @('vi') is ``@('equiv')-hittable'' if sufficient congruence rules (see @(see
 defcong)) have been proved to establish that the propositional value of the
 clause is not altered by replacing that occurrence of @('vi') by some
 @('equiv')-equivalent term.</p>

 <p>If an @(':elim') rule is not applied when you think it should have been,
 and the rule uses an equivalence relation, @('equiv'), other than @('equal'),
 it is most likely that there is an occurrence of the variable that is not
 @('equiv')-hittable.  Easy occurrences to overlook are those in the governing
 hypotheses.  If you see an unjustified occurrence of the variable, you must
 prove the appropriate congruence rule to allow the @(':elim') to fire.</p>

 <p>Further examples of how ACL2 @(':elim') rules are used may be found in the
 corresponding discussion of ``Elimination of Destructors'' for Nqthm, in
 Section 10.4 of A Computational Logic Handbook.</p>")

(defxdoc emacs
  :parents (acl2-tutorial)
  :short "Emacs support for ACL2"
  :long "<p>Many successful ACL2 users run in an shell under the Emacs editor.
 If you do so, then you may wish to load the distributed file
 @('emacs/emacs-acl2.el').  The file begins with considerable comments
 describing what it offers.  It is intended to work both with GNU Emacs and
 XEmacs.</p>

 <p>In particular, the above file provides the ACL2-Doc browser, a convenient
 tool for viewing, in Emacs, documentation for both the ACL2 system and the
 documented community books, as well as custom manuals.  See @(see
 ACL2-Doc).</p>

 <p>If you are not comfortable with Emacs, you may prefer to use an
 Eclipse-based interface; see @(see acl2-sedan).</p>")

(defxdoc embedded-event-form
  :parents (events)
  :short "Forms that may be embedded in other @(see events)"
  :long "@({
  Examples:
  (defun hd (x) (if (consp x) (car x) 0))
  (local (defthm lemma23 ...))
  (progn (defun fn1 ...)
         (local (defun fn2 ...))
         ...)

  General Form:
  An embedded event form is a term, x, such that:
 })

 <ul>

 <li>@('x') is a call of an event function other than @(tsee DEFPKG) (see
 @(see events) for a listing of the event functions);</li>

 <li>@('x') is of the form @('(LOCAL x1)') where @('x1') is an
 embedded event form;</li>

 <li>@('x') is of the form @('(SKIP-PROOFS x1)') where @('x1') is
 an embedded event form;</li>

 <li>@('x') is of the form @('(MAKE-EVENT &)'), where @('&') is any term whose
 expansion is an embedded event (see @(see make-event));</li>

 <li>@('x') is of the form @('(WITH-OUTPUT ... x1)'),
 @('(WITH-PROVER-STEP-LIMIT ... x1 ...)'), or @('(WITH-PROVER-TIME-LIMIT
 ... x1)'), where @('x1') is an embedded event form;</li>

 <li>@('x') is of the form @('(WITH-GUARD-CHECKING-EVENT c x1)') or
 @('(WITH-GUARD-CHECKING-EVENT (QUOTE c) form)'), where @('c') is a member of
 the list @(`*guard-checking-values*`) and @('x1') is an embedded event
 form;</li>

 <li>@('x') is a call of @(tsee ENCAPSULATE), @(tsee PROGN), @(tsee PROGN!),
 or @(tsee INCLUDE-BOOK);</li>

 <li>@('x') macroexpands to one of the forms above; or</li>

 <li>[intended only for the implementation] @('x') is @('(RECORD-EXPANSION x1
 x2)'), where @('x1') and @('x2') are embedded event forms.</li>

 </ul>

 <p>However, we add the following restrictions for @(tsee local) contexts.</p>

 <ul>

 <li>An embedded event form may not set the @(tsee acl2-defaults-table) when in
 the context of @(tsee local).  Thus for example, the form

 @({
  (local (table acl2-defaults-table :defun-mode :program))
 })

 is not an embedded event form, nor is the form @('(local (program))'),
 since the latter sets the @(tsee acl2-defaults-table) implicitly.  An example
 at the end of the discussion below illustrates why there is this
 restriction.</li>

 <li>A call of @(tsee defaxiom) is illegal in the context of @(tsee local).
 Without this restriction, one could locally assert a strong axiom like
 @('(equal t nil)') and then non-locally prove that formula, leaving you in an
 ACL2 logical @(see world) in which it appears that the formula is actually
 provable without such an axiom.</li>

 <li>A call of @(tsee add-include-book-dir!) or @(tsee
 delete-include-book-dir!) is illegal in the context of @(tsee local).  For an
 explanation, see @(see add-include-book-dir!).</li>

 </ul>

 <p>Only embedded event forms are allowed in a book after its initial @(tsee
 in-package) form.  See @(see books).  However, you may find that @(tsee
 make-event) allows you to get the effect you want for a form that is not an
 embedded event form.  For example, you can put the following into a book,
 which assigns the value 17 to @(tsee state) global variable @('x'):</p>

 @({
  (make-event (er-progn (assign x 17)
                        (value '(value-triple nil)))
              :check-expansion t)
 })

 <p>When an embedded event is executed while @(tsee ld-skip-proofsp) is
 @(''')@(tsee include-book), those parts of it inside @(tsee local) forms are
 ignored.  Thus,</p>

 @({
     (progn (defun f1 () 1)
            (local (defun f2 () 2))
            (defun f3 () 3))
 })

 <p>will define @('f1'), @('f2'), and @('f3') when @(tsee ld-skip-proofsp) is
 @('nil') or @('t'), but will define only @('f1') and @('f3') when @(tsee
 ld-skip-proofsp) is @(''')@(tsee include-book).</p>

 <p><i>Discussion:</i></p>

 <p>@(tsee Encapsulate), @(tsee progn), and @(tsee include-book) place
 restrictions on the kinds of forms that may be processed.  These restrictions
 ensure that the non-local @(see events) are indeed admissible provided that
 the sequence of @(tsee local) and non-local @(see events) is admissible when
 proofs are done, i.e., when @('ld-skip-proofs') is @('nil').  But @(tsee
 progn!) places no such restrictions, hence is potentially dangerous and should
 be avoided unless you understand the ramifications; so it is illegal unless
 there is an active trust tag (see @(see defttag)).</p>

 <p>@(tsee Local) permits the hiding of an event or group of @(see events) in
 the sense that @(tsee local) @(see events) are processed when we are trying to
 establish the admissibility of a sequence of @(see events) embedded in @(tsee
 encapsulate) forms or in @(see books), but are ignored when we are
 constructing the @(see world) produced by assuming that sequence.  Thus, for
 example, a particularly ugly and inefficient @(':')@(tsee rewrite) rule might
 be made @(tsee local) to an @(see encapsulate) that ``exports'' a desirable
 theorem whose proof requires the ugly lemma.</p>

 <p>To see why we can't allow just anything as an embedded event, consider
 allowing the form</p>

 @({
  (if (ld-skip-proofsp state)
      (defun foo () 2)
      (defun foo () 1))
 })

 <p>followed by</p>

 @({
  (defthm foo-is-1 (equal (foo) 1)).
 })

 <p>When we process the @(see events) with @(tsee ld-skip-proofsp) is @('nil'),
 the second @(tsee defun) is executed and the @(tsee defthm) succeeds.  But
 when we process the @(see events) with @(tsee ld-skip-proofsp) @(''')@(tsee
 include-book), the second @(tsee defun) is executed, so that @('foo') no
 longer has the same definition it did when we proved @('foo-is-1').  Thus, an
 invalid formula is assumed when we process the @(tsee defthm) while skipping
 proofs.  Thus, the first form above is not a legal embedded event form.</p>

 <p>If you encounter a situation where these restrictions seem to prevent you
 from doing what you want to do, then you may find @('make-event') to be
 helpful.  See @(see make-event).</p>

 <p>@(tsee Defpkg) is not allowed because it affects how things are read after
 it is executed.  But all the forms embedded in an event are read before any
 are executed.  That is,</p>

 @({
  (encapsulate nil
               (defpkg \"MY-PKG\" nil)
               (defun foo () 'my-pkg::bar))
 })

 <p>makes no sense since @('my-pkg::bar') must have been read before the @(tsee
 defpkg) for @('\"MY-PKG\"') was executed.</p>

 <p>Finally, let us elaborate on the restriction mentioned earlier related to
 the @(tsee acl2-defaults-table).  Consider the following form.</p>

 @({
  (encapsulate
   ()
   (local (program))
   (defun foo (x)
     (if (equal 0 x)
         0
       (1+ (foo (- x))))))
 })

 <p>See @(see local-incompatibility) for a discussion of how @(tsee
 encapsulate) processes event forms.  Briefly, on the first pass through the
 @(see events) the definition of @('foo') will be accepted in @(tsee defun)
 mode @(':')@(tsee program), and hence accepted.  But on the second pass the
 form @('(local (program))') is skipped because it is marked as @(tsee local),
 and hence @('foo') is accepted in @(tsee defun) mode @(':')@(tsee logic).
 Yet, no proof has been performed in order to admit @('foo'), and in fact, it
 is not hard to prove a contradiction from this definition!</p>")

(defxdoc enable
  :parents (theories theory-functions)
  :short "Adds names to current theory"
  :long "@({
  Example:
  (enable fact (fact) associativity-of-app)

  General Form:
  (enable name1 name2 ... namek)
 })

 <p>where each @('namei') is a runic designator; see @(see theories).  The
 result is the theory that contains all the names in the current theory plus
 those listed.  Note that this is merely a function that returns a theory.  The
 result is generally a very long list of @(see rune)s and you will probably
 regret printing it.</p>

 <p>For related utilities, see @(see disable) and see @(see e/d).</p>

 <p>The standard way to ``enable'' a fixed set of names, is as follows; see
 @(see hints) and see @(see in-theory).</p>

 @({
  :in-theory (enable name1 name2 ... namek)  ; in a hint
  (in-theory (enable name1 name2 ... namek)) ; as an event
  (local ; often desirable, to avoid exporting from the current context
   (in-theory (enable name1 name2 ... namek)))
 })

 <p>Note that all the names are implicitly quoted.  If you wish to enable a
 computed list of names, @('lst'), use the theory expression @('(union-theories
 (current-theory :here) lst)').</p>")

(defxdoc enable-forcing
  :parents (force)
  :short "To allow forced case splits"
  :long "@({
  General Form:
  ACL2 !>:enable-forcing    ; allowed forced case splits
 })

 <p>See @(see force) and see @(see case-split) for a discussion of forced case
 splits, which are turned back on by this command.  See @(see disable-forcing)
 for an example showing how to turn off forced case splits.</p>

 <p>@('Enable-forcing') is actually a macro that @(see enable)s the @(see
 executable-counterpart) of the function symbol @('force'); see @(see force).
 When you want to use @(see hints) to turn on forced case splits, use a form
 such as one of the following (these are equivalent).</p>

 @({
  :in-theory (enable (:executable-counterpart force))
  :in-theory (enable (force))
 })")

(defxdoc enable-immediate-force-modep
  :parents (force)
  :short "@(see force)d hypotheses are attacked immediately"
  :long "@({
  General Form:
  ACL2 !>:enable-immediate-force-modep
 })

 <p>This event causes ACL2 to attack @(see force)d hypotheses immediately
 instead of delaying them to the next forcing round.  See @(see
 immediate-force-modep).  Or for more basic information, first see @(see force)
 for a discussion of @(see force)d case splits.</p>

 <p>Enable-immediate-force-modep is a macro that @(see enable)s the @(see
 executable-counterpart) of the function symbol @(tsee immediate-force-modep).
 When you want to @(see enable) this mode in @(see hints), use a form such as
 one of the following (these are equivalent).</p>

 @({
  :in-theory (enable (:executable-counterpart immediate-force-modep))
  :in-theory (enable (immediate-force-modep))
 })")

(defxdoc encapsulate
  :parents (events)
  :short "Hide some @(see events) and/or constrain some functions"
  :long "<p>@('Encapsulate') provides a way to execute a sequence of @(see
 events) and then hide some of the resulting effects.  There are two kinds of
 encapsulations: ``trivial'' and ``non-trivial''.  We discuss these briefly
 before providing detailed @(see documentation).</p>

 <p>A trivial encapsulation is an event of the following form.</p>

 @({
  (encapsulate
   () ; nil here indicates \"trivial\"
   <event-1>
   ...
   <event-k>)
 })

 <p>We use the term ``sub-events'' to refer to @('<event-1>') through
 @('<event-k>').  Each sub-event @('<event-i>') may be ``@(see local)'', that
 is, of the form @('(local <event-i'>)'); the other sub-events are called
 ``non-local''.  When this @('encapsulate') form is submitted to ACL2, it is
 processed in two passes.  On the first pass, each sub-event is printed (by
 default) and processed in sequence; admission of the @('encapsulate') fails if
 any @('<event-i>') fails to be admitted.  Then a second pass is made after
 rolling back the logical @(see world) to what it was just before executing the
 @('encapsulate') form.  In the second pass, only the non-@(see local) forms
 @('<event-i>') are evaluated, again in order, and proofs are skipped.</p>

 <p>For example, the following trivial encapsulation exports a single event,
 @('member-equal-reverse').  The lemma @('member-revappend') is used (as a
 @(see rewrite) rule) to prove @('member-equal-reverse') on the first pass, but
 since @('member-revappend') is @(see local), it is ignored on the second
 (final) pass.</p>

 @({
  (encapsulate
   ()

   (local
    (defthm member-revappend
      (iff (member-equal a (revappend x y))
           (or (member-equal a x)
               (member-equal a y)))
      :hints ((\"Goal\" :induct (revappend x y)))))

   (defthm member-equal-reverse
     (iff (member-equal a (reverse x))
          (member-equal a x))))
 })

 <p>Of course, one might prefer to prove these @(see events) at the top level,
 rather than within an encapsulation; but the point here is to illustrate that
 you can have @(see local) @(see events) that do not become part of the logical
 @(see world).  (Such a capability is also provided at the level of @(see
 books); in particular, see @(see include-book).)</p>

 <p>Note that trivial encapsulates must introduce at least one sub-event, or
 else they are treated as no-ops, with no effect on the logical @(see world).
 Consider the following example.</p>

 @({
 ACL2 !>(encapsulate nil (local (defun f (x) x)))

 To verify that the encapsulated event correctly extends the current
 theory we will evaluate it.  The theory thus constructed is only ephemeral.

 Encapsulated Event:


 ACL2 !>>(LOCAL (DEFUN F (X) X))

 Since F is non-recursive, its admission is trivial.  We observe that
 the type of F is described by the theorem (EQUAL (F X) X).

 Summary
 Form:  ( DEFUN F ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
 F

 End of Encapsulated Event.

 ACL2 Observation in ( ENCAPSULATE NIL (LOCAL ...) ...):  The submitted
 encapsulate event has created no new ACL2 events, and thus is leaving
 the ACL2 logical world unchanged.  See :DOC encapsulate.

 Summary
 Form:  ( ENCAPSULATE NIL (LOCAL ...) ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  :EMPTY-ENCAPSULATE
 ACL2 !>
 })

 <p>After the above evaluation, we are left in the @(see world) with which we
 began.  For example, if you evaluate the above form in the initial ACL2 world,
 you can see the following both before and after that evaluation.</p>

 @({
 ACL2 !>:pbt 0
            0:x(EXIT-BOOT-STRAP-MODE)
 ACL2 !>
 })

 <p>On the other hand, non-trivial encapsulations provide a way to introduce
 axioms about new function symbols, without introducing inconsistency and
 without introducing complete definitions.  The following example illustrates
 how that works.</p>

 @({
  (encapsulate

  ; The following list has a single signature, introducing a function foo of
  ; one argument that returns one value.  (The list is non-empty, so we call
  ; this a \"non-trivial\" encapsulation.)
   ( ((foo *) => *) )

  ; Introduce a ``witness'' (example) for foo, marked as local so that
  ; it is not exported:
   (local (defun foo (x) x))

  ; Introduce a non-local property to be exported:
   (defthm foo-preserves-consp
     (implies (consp x)
              (consp (foo x))))
  )
 })

 <p>The form above introduces a new function symbol, @('foo'), with the
 indicated property and no definition.  In fact, the output from ACL2 concludes
 as follows.</p>

 @({
  The following constraint is associated with the function FOO:

  (IMPLIES (CONSP X) (CONSP (FOO X)))
 })

 <p>To understand this example, we consider how non-trivial encapsulations are
 processed.  The same two passes are made as for trivial encapsulations, and
 the (@(see local)) definition of @('foo') is ignored on the second pass, and
 hence does not appear in the resulting ACL2 logical @(see world).  But before
 the second pass, each @(see signature) is stored in the @(see world).  Thus,
 when the theorem @('foo-preserves-consp') is encountered in the second pass,
 @('foo') is a known function symbol with the indicated signature.</p>

 <p>If any event fails while evaluating a call of @('encapsulate'), the entire
 @('encapsulate') call is deemed to have failed, and the logical @(see world)
 is rolled back to what it was immediately before the @('encapsulate')
 call.</p>

 <p>We now provide detailed documentation.  But discussion of redundancy for
 @('encapsulate') events may be found elsewhere; see @(see
 redundant-encapsulate).</p>

 @({
  Other Examples:
  (encapsulate (((an-element *) => *))

  ; The list of signatures above could also be written
  ;            ((an-element (lst) t))

    (local (defun an-element (lst)
             (if (consp lst) (car lst) nil)))
    (local (defthm member-equal-car
              (implies (and lst (true-listp lst))
                       (member-equal (car lst) lst))))
    (defthm thm1
       (implies (null lst) (null (an-element lst))))
    (defthm thm2
       (implies (and (true-listp lst)
                     (not (null lst)))
                (member-equal (an-element lst) lst))))

  (encapsulate
   () ; empty signature: no constrained functions indicated

   (local (defthm hack
            (implies (and (syntaxp (quotep x))
                          (syntaxp (quotep y)))
                     (equal (+ x y z)
                            (+ (+ x y) z)))))

   (defthm nthcdr-add1-conditional
     (implies (not (zp (1+ n)))
              (equal (nthcdr (1+ n) x)
                     (nthcdr n (cdr x))))))

  General Form:
  (encapsulate (signature ... signature)
    ev1
    ...
    evn)
 })

 <p>where each @(tsee signature) is a well-formed signature, each
 @('signature') describes a different function symbol, and each @('evi') is an
 embedded event form (See @(see embedded-event-form)).  Also see @(see
 signature), in particular for a discussion of how a signature can assign a
 @(see guard) to a function symbol.  There must be at least one @('evi').  The
 @('evi') inside @(tsee local) special forms are called ``local'' @(see events)
 below.  @(see Events) that are not @(tsee local) are sometimes said to be
 ``exported'' by the encapsulation.  We make the further restriction that no
 @(tsee defaxiom) event may be introduced in the scope of an @('encapsulate')
 (not even by @('encapsulate') or @(tsee include-book) events that are among
 the @('evi')).  Furthermore, no non-@(tsee local) @(tsee include-book) event
 is permitted in the scope of any @('encapsulate') with a non-empty list of
 signatures.</p>

 <p>To be well-formed, an @('encapsulate') event must have the properties that
 each event in the body (including the @(tsee local) ones) can be successfully
 executed in sequence and that in the resulting theory, each function mentioned
 among the @(see signature)s was introduced via a @(tsee local) event and has
 the @(see signature) listed.  (A utility is provided to assist in debugging
 failures of such execution; see @(see redo-flat).)  In addition, the body may
 contain no ``local incompatibilities'' which, roughly stated, means that the
 @(see events) that are not @(tsee local) must not syntactically require
 symbols defined by @(tsee local) @(tsee events), except for the functions
 listed in the @(see signature)s.  See @(see local-incompatibility).  Finally,
 no non-@(tsee local) recursive definition in the body may involve in its
 suggested induction scheme any function symbol listed among the @(see
 signature)s.  See @(see subversive-recursions).</p>

 <p>Observe that if the @(see signature)s list is empty, the resulting
 ``trivial'' @('encapsulate') may still be useful for deriving theorems to be
 exported whose proofs require lemmas you prefer to hide (i.e., made @(tsee
 local)).  Whether trivial or not (i.e., whether the signature is empty or
 not), @('encapsulate') exports the results of evaluating its non-@(tsee local)
 @(see events), but its @(tsee local) @(see events) are ignored for the
 resulting logical @(see world).</p>

 <p>The result of a non-trivial @('encapsulate') event is an extension of the
 logic in which, roughly speaking, the functions listed in the @(see
 signature)s are constrained to have the @(see signature)s listed and to
 satisfy the non-@(tsee local) theorems proved about them.  In fact, other
 functions introduced in the @('encapsulate') event may be considered to have
 ``@(see constraint)s'' as well.  (See @(see constraint) for details, which are
 only relevant to functional instantiation.)  Since the @(see constraint)s were
 all theorems in the ``ephemeral'' or ``local'' theory, we are assured that the
 extension produced by @('encapsulate') is sound.  In essence, the @(tsee
 local) definitions of the constrained functions are just ``witness functions''
 that establish the consistency of the @(see constraint)s.  Because those
 definitions are @(tsee local), they are not present in the theory produced by
 encapsulation.  After a non-trivial @('encapsulate') event is admitted,
 theorems about the constrained function symbols may then be proved &mdash;
 theorems whose proofs necessarily employ only the @(see constraint)s.  Thus,
 those theorems may be later functionally instantiated, as with the
 @(':functional-instance') lemma instance (see @(see lemma-instance)), to
 derive analogous theorems about different functions, provided the constraints
 (see @(see constraint)) can be proved about the new functions.</p>

 <p>The @(see default-defun-mode) for the first event in an encapsulation is
 the default @(see defun-mode) ``outside'' the encapsulation.  But since @(see
 events) changing the @(see defun-mode) are permitted within the body of an
 @('encapsulate'), the default @(see defun-mode) may be changed.  However,
 @(see defun-mode) changes occurring within the body of the @('encapsulate')
 are not exported.  In particular, the @(tsee acl2-defaults-table) after an
 @('encapsulate') is always the same as it was before the @('encapsulate'),
 even though the @('encapsulate') body might contain @(see defun-mode) changing
 @(see events), @(':')@(tsee program) and @(':')@(tsee logic).  See @(see
 defun-mode).  More generally, after execution of an @('encapsulate') event,
 the value of @(tsee acl2-defaults-table) is restored to what it was
 immediately before that event was executed.  See @(see
 acl2-defaults-table).</p>

 <p>We make some remarks on @(see guard)s and evaluation.  Calls of functions
 introduced in the @(see signature)s list cannot be evaluated in the ACL2
 read-eval-print loop.  See @(see defattach) for a way to overcome this
 limitation.  Moreover, any @(':')@(tsee guard) supplied in the signature is
 automatically associated in the @(see world) with its corresponding function
 symbol, with no requirement beyond what is required for a legal @(see
 signature) other than that all of the guard's function symbols are in
 @(':')@(tsee logic) mode with their @(see guard)s verified.  In particular,
 there need not be any relationship between a guard in a signature and the
 guard in a @('local') witness function.  Finally, note that for functions
 introduced non-@(see local)ly inside a non-trivial @('encapsulate') event,
 @(see guard) verification is illegal unless ACL2 determines that the proof
 obligations hold outside the @(tsee encapsulate) event as well.</p>

 @({
  (encapsulate
   ((f (x) t))
   (local (defun f (x) (declare (xargs :guard t)) (consp x)))
   ;; ERROR!
   (defun g (x)
     (declare (xargs :guard (f x)))
     (car x)))
 })

 <p>The order of the @(see events) in the vicinity of an @('encapsulate') is
 confusing.  We discuss it in some detail here because when logical names are
 being used with theory functions to compute sets of rules, it is sometimes
 important to know the order in which @(see events) were executed.  (See @(see
 logical-name) and see @(see theory-functions).)  What, for example, is the set
 of function names extant in the middle of an encapsulation?</p>

 <p>If the most recent event is @('previous') and then you execute an
 @('encapsulate') constraining @('an-element') with two non-@(tsee local) @(see
 events) in its body, @('thm1') and @('thm2'), then the order of the @(see
 events) after the encapsulation is (reading chronologically forward):
 @('previous'), @('thm1'), @('thm2'), @('an-element') (the @('encapsulate')
 itself).  Actually, between @('previous') and @('thm1') certain extensions
 were made to the @(see world) by the superior @('encapsulate'), to permit
 @('an-element') to be used as a function symbol in @('thm1').</p>

 <p>Remark for ACL2(r) (see @(see real)).  For ACL2(r), @(tsee encapsulate) can
 be used to introduce classical and non-classical functions, as determined by
 the signatures; see @(see signature).  Those marked as classical (respectively
 non-classical) must have classical (respectively, non-classical) @(tsee local)
 witness functions.  A related requirement applies to functional instantiation;
 see @(see lemma-instance).</p>")

(defxdoc endp
  :parents (lists acl2-built-ins)
  :short "Recognizer for empty lists"
  :long "<p>In the ACL2 logic, @('(endp x)') is the same as @('(atom x)').  See
 @(see atom).</p>

 <p>Unlike @(tsee atom), the @(see guard) for @('endp') requires that @('x') is
 a @(tsee cons) pair or is @('nil').  Thus, @('endp') is typically used as a
 termination test for functions that recur on a @(tsee true-listp) argument.
 See @(see guard) for general information about @(see guard)s.</p>

 <p>@('Endp') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def endp)")

(defxdoc enter-boot-strap-mode
  :parents (history)
  :short "The first millisecond of the Big Bang"
  :long "<p>ACL2 functions, e.g., @(tsee if), that show
 @('enter-boot-strap-mode') as their defining @(see command) are in fact @(see
 primitive)s.  It is impossible for the system to display defining axioms about
 these symbols.</p>

 <p>@('Enter-boot-strap-mode') is a Common Lisp function but not an ACL2
 function.  It magically creates from @('nil') an ACL2 property list @(see
 world) that lets us start the boot-strapping process.  That is, once
 @('enter-boot-strap-mode') has created its @(see world), it is possible to
 process the @(tsee defconst)s, @(tsee defun)s, and @(tsee defaxiom)s,
 necessary to bring up the rest of the system.  Before that @(see world) is
 created, the attempt by ACL2 even to translate a @(tsee defun) form, say,
 would produce an error because @(tsee defun) is undefined.</p>

 <p>Several ACL2 functions show @('enter-boot-strap-mode') as their defining
 @(see command).  Among them are @(tsee if), @(tsee cons), @(tsee car), and
 @(tsee cdr).  These functions are characterized by axioms rather than
 definitional equations &mdash; axioms that in most cases are built into our
 code and hence do not have any explicit representation among the rules and
 formulas in the system.</p>")

(defxdoc eq
  :parents (equal equality-variants acl2-built-ins)
  :short "Equality of symbols"
  :long "<p>@('Eq') is the function for determining whether two objects are
 identical (i.e., have the exact same store address in the current von Neumann
 implementation of Common Lisp).  It is the same as @(tsee equal) in the ACL2
 logic.</p>

 <p>@('Eq') is a Common Lisp function.  In order to ensure conformance with
 Common Lisp, the ACL2 @(see guard) on @('eq') requires at least one of the
 arguments to @('eq') to be a symbol.  Common Lisp guarantees that if @('x') is
 a symbol, then @('x') is @('eq') to @('y') if and only if @('x') is @(tsee
 equal) to @('y').  Thus, the ACL2 user should think of @('eq') as nothing
 besides a fast means for checking @(tsee equal) when one argument is known to
 be a symbol.  In particular, it is possible that an @('eq') test will not even
 require the cost of a function call but will be as fast as a single machine
 instruction.</p>

 @(def eq)")

(defxdoc eql
  :parents (equal equality-variants acl2-built-ins)
  :short "Test equality (of two numbers, symbols, or @(see characters))"
  :long "<p>@('(eql x y)') is logically equivalent to @('(equal x y)').</p>

 <p>Unlike @(tsee equal), @('eql') has a @(see guard) requiring at least one of
 its arguments to be a number, a symbol, or a character.  Generally, @('eql')
 is executed more efficiently than @(tsee equal).</p>

 <p>For a discussion of the various ways to test against 0, See @(see
 zero-test-idioms).</p>

 <p>@('Eql') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def eql)")

(defxdoc eqlable-alistp
  :parents (alists acl2-built-ins)
  :short "Recognizer for a true list of pairs whose @(tsee car)s are suitable for @(tsee eql)"
  :long "<p>The predicate @('eqlable-alistp') tests whether its argument is a
 @(tsee true-listp) of @(tsee consp) objects whose @(tsee car)s all satisfy
 @(tsee eqlablep).</p>

 @(def eqlable-alistp)")

(defxdoc eqlable-listp
  :parents (eqlablep equal lists acl2-built-ins)
  :short "Recognizer for a true list of objects each suitable for @(tsee eql)"
  :long "<p>The predicate @('eqlable-listp') tests whether its argument is a
 @(tsee true-listp) of objects satisfying @(tsee eqlablep).</p>

 @(def eqlable-listp)")

(defxdoc eqlablep
  :parents (equal acl2-built-ins)
  :short "The @(see guard) for the function @(tsee eql)"
  :long "<p>The predicate @('eqlablep') tests whether its argument is suitable
 for @(tsee eql), at least one of whose arguments must satisfy this predicate
 in Common Lisp.  @('(Eqlablep x)') is true if and only if its argument is a
 number, a symbol, or a character.</p>

 @(def eqlablep)")

(defxdoc equal
  :parents (basics acl2-built-ins)
  :short "True equality"
  :long "<p>@('(equal x y)') is equal to @('t') or @('nil'), according to
 whether or not @('x') and @('y') are the same value.</p>

 <p>For a discussion of the various idioms for testing against 0, See @(see
 zero-test-idioms).</p>")

(defxdoc equality-variants

; Consider position, remove-duplicates, and remove.  In Common Lisp, all three
; of these primitives can take strings.  Through Version_4.2, position and
; remove-duplicates supported string arguments, while remove did not.  Note
; however that remove-duplicates-eql and remove-duplicates-equal did not
; support string arguments.  For backward compatibility with Version_4.2 and
; earlier, we leave remove-duplicates-equal unchanged.  When there is
; sufficient demand we can extend remove.

  :parents (programming)
  :short "Versions of a function using different equality tests"
  :long "<p>The ACL2 environment includes not only a logic but also a
 programming language, which is based on Common Lisp.  Execution efficiency may
 be increased by using fast equality tests: @(tsee eq) for symbols and @(tsee
 eql) for numbers, symbols, and characters (see @(see eqlablep)).  Several
 list-processing functions built into ACL2 thus have three variants, depending
 on whether the equality function used is @(tsee eq), @(tsee eql), or @(tsee
 equal); a list is provided below.  ACL2 has taken measures to ensure that one
 can reason about a single logical function even when one uses these different
 variants.</p>

 <p>Consider for example the case of list membership.  Common Lisp provides a
 utility for this purposes, @(tsee member), which can take a @(':TEST') keyword
 argument, default @(tsee eql).  So for example, one might write</p>

 @({
  (member a x :TEST 'eq)
 })

 <p>if either @('a') is a symbol or @('x') is a list of symbols, so that the
 fastest equality test (@(tsee eq)) may be used when comparing @('a') to
 successive elements of the list, @('x').  One might elsewhere write @('(member
 b (foo y))'), which is equivalent to @('(member b (foo y) :TEST 'eql)'), for
 example if @('b') is a number.  If one wants to reason about both @('(member a
 x :TEST 'eq)') and @('(member b y)'), it might be helpful for both calls of
 @('member') to be the same logically, even though Common Lisp will execute
 them differently (using @(tsee eq) or @(tsee eql), respectively).  ACL2
 arranges that in fact, both references to @(tsee member) generate calls of
 @(tsee member-equal) in the theorem prover.</p>

 <p>In fact, since @(tsee member) can take the optional @(':TEST') keyword
 argument, then in ACL2 it must be defined as a macro, not a function (see
 @(see defun)).  ACL2 arranges that a call of @('member') generates a
 corresponding call of the function @(tsee member-equal), regardless of the
 value of @('TEST'), in a manner that produces @(tsee member-equal) in prover
 output.  More generally, you can expect ACL2 to treat your use of @(tsee
 member) as though you had written @(tsee member-equal), for example in the way
 it stores @(tsee rewrite) rules and other kinds of rules as well (see @(see
 rule-classes)).  We say little here about how this is all arranged by ACL2,
 other than to mention that @(tsee mbe) is utilized (so, you might see mention
 in proof logs) of the function @(tsee return-last) that implements @(tsee
 mbe).  Such details, which involve a notion of ``macro alias'' and probably
 can be ignored by most users, may be found elsewhere; see @(see
 equality-variants-details).</p>

 <p>As a convenience to the user, the macro @('member-eq') is provided that
 expands to a corresponding call of @('member') with @(':TEST 'eq'), as
 follows.</p>

 @({
  ACL2 !>:trans1 (member-eq (foo x) (bar y))
   (MEMBER (FOO X) (BAR Y) :TEST 'EQ)
  ACL2 !>
 })

 <p>For efficiency we recommend using the @('-equal') equality variant, for
 example @(tsee member-equal) or @('(')@(tsee member)@(' ... :TEST 'equal)'),
 in certain contexts: @(tsee defmacro), @(tsee defpkg), @(tsee defconst), and
 @(tsee value-triple) forms.  However, the implementation of equality variants
 has been designed so that when defining a function, one may choose freely in a
 definition an equality variant of primitive @('F'), to get efficient execution
 but where subsequent reasoning is about @('F-equal').  For details about the
 above recommendation and for a discussion of the implementation, see @(see
 equality-variants-details).</p>

 <p>The following alphabetical list includes all primitives that have equality
 variants.  Each macro @('F') listed below takes an optional @(':TEST') keyword
 argument of @(''eq'), @(''eql'), or @(''equal'), where @(''eql') is the
 default.  For each such @('F'), a function @('F-equal') is defined such that
 for logical purposes (in particular theorem proving), each call of @('F')
 expands to a corresponding call of @('F-equal').  For convenience, a macro
 @('F-eq') is also defined, so that a call of @('F-eq') expands to a
 corresponding call of @('F') with @(':TEST 'eq').</p>

 <code>
 @(tsee add-to-set)
 @(tsee assoc)
 @(tsee delete-assoc)
 @(tsee intersection$) ; (see Note below)
 @(tsee intersectp)
 @(tsee member)
 @(tsee no-duplicatesp)
 @('position-ac')
 @(tsee position)
 @(tsee put-assoc)
 @(tsee rassoc)
 @(tsee remove-duplicates)
 @(tsee remove1)
 @(tsee remove)
 @(tsee set-difference$) ; (see Note below)
 @(tsee subsetp)
 @(tsee union$) ; (see Note below)
 </code>

 <p>Note: Three of the macros above have names ending with the character,
 `@('$')': @(tsee intersection$), @(tsee set-difference$), and @(tsee union$).
 In each case there is a corresponding Common Lisp primitive without the
 trailing `@('$')': @('intersection'), @('set-difference'), and @('union').
 However, Common Lisp does not specify the order of elements in the list
 returned by those primitives, so ACL2 has its own.  Nevertheless, the only use
 of the trailing `@('$')' is to distinguish the primitives; associated
 functions and macros, for example @('union-eq') and @('intersection-equal'),
 do not include the `@('$')' character in their names.</p>

 <p>We conclude with a brief discussion of @(see guards).  The expansion of any
 of the above macros depends on the keyword argument, which generates a
 function call with a guard suitable for the equality test being used.
 Consider for example the call @('(member x lst :test 'eq)'), or equivalently,
 @('(member-eq x lst)').  Expanding these macros leads to a call of @(tsee
 mbe); you can see how that goes by using @(':')@(tsee trans1).  Ultimately,
 the guard being checked is that of the function @('member-eq-exec'), which is
 as follows.</p>

 @({
  (if (symbolp x)
      (true-listp lst)
    (symbol-listp lst))
 })

 <p>Care has been taken to ensure that this guard is checked during evaluation
 and also that it generates suitable proof obligations for guard verification
 (see @(see verify-guards)).  A guard violation might look something like
 this:</p>

 @({
   ACL2 !>(member-eq 3 '(4 5))


   ACL2 Error in TOP-LEVEL:  The guard for the function call
   (MEMBER-EQ-EXEC$GUARD-CHECK X LST), which is
   (IF (SYMBOLP X) (TRUE-LISTP LST) (SYMBOL-LISTP LST)), is violated by
   the arguments in the call (MEMBER-EQ-EXEC$GUARD-CHECK 3 '(4 5)).
   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 !>
 })

 <p>Above, @('member-eq-exec$guard-check') is a function generated as part of
 ACL2's expansion of @('member') with @(':test 'eq'), and this function symbol
 can be quite reasonably ignored.  The important thing is that it refers to the
 guard for @('member-eq-exec'), which as the name may suggest is intended to
 guard the execution of a call of @(tsee member-eq), or a call of @(tsee
 member) with @(':test 'eq').  The important part of the message above is the
 guard actually being violated: @('(IF (SYMBOLP X) (TRUE-LISTP
 LST) (SYMBOL-LISTP LST))').</p>")

(defxdoc equality-variants-details
  :parents (equality-variants)
  :short "Details about @(see equality-variants)"
  :long "<p>Here we present details about equality variants, none of which is
 likely to be important to the majority of ACL2 users.  Please see @(see
 equality-variants) for relevant background.</p>

 <p>We begin by presenting @(see events) that implement the equality variants
 for @(tsee member), as these illustrate the events introduced for all macros
 having equality variants.  The definition of @(tsee member), just below, calls
 the macro @('let-mbe'), which in turn is just an abbreviation for a
 combination of @(tsee let) and @(tsee mbe).  Here is a simplified version of
 the definition of this macro.  For relevant background, see @(tsee mbe).</p>

 @({
  (defmacro let-mbe (bindings &key logic exec)
    `(let ,bindings
       (mbe :logic ,logic
            :exec ,exec)))
 })

 <p>This use of @(tsee let) arranges that each argument of a call of
 @('member') is evaluated only once.</p>

 <p>The actual definition of the macro @('let-mbe') is a bit more complex, in
 order to guarantee that @(see guard)s are appropriately checked.  For purposes
 of this discussion we ignore this simplification.  (You can find the
 definition of @('let-mbe') in ACL2 source file @('axioms.lisp').)</p>

 <p>Consider the following definition from ACL2 source file @('axioms.lisp').
 Notice that it invokes the macro @('let-mbe'), discussed above.</p>

 @({
  (defmacro member (x l &key (test ''eql))
    (declare (xargs :guard (or (equal test ''eq)
                               (equal test ''eql)
                               (equal test ''equal))))
    (cond
     ((equal test ''eq)
      `(let-mbe ((x ,x) (l ,l))
                :logic (member-equal x l)
                :exec  (member-eq-exec x l)))
     ((equal test ''eql)
      `(let-mbe ((x ,x) (l ,l))
                :logic (member-equal x l)
                :exec  (member-eql-exec x l)))
     (t ; (equal test 'equal)
      `(member-equal ,x ,l))))
 })

 <p>Inspection of the definition above shows that every call of @(tsee member)
 expands to one that is logically equivalent to the corresponding call of
 @(tsee member-equal), which is defined as follows.</p>

 @({
  (defun member-equal (x lst)
    (declare (xargs :guard (true-listp lst)))
    (cond ((endp lst) nil)
          ((equal x (car lst)) lst)
          (t (member-equal x (cdr lst)))))
 })

 <p>The following two definitions model equality variants of @(tsee member) for
 tests @(tsee eq) and @(tsee eql), respectively.</p>

 @({
  (defun member-eq-exec (x lst)
    (declare (xargs :guard (if (symbolp x)
                               (true-listp lst)
                             (symbol-listp lst))))
    (cond ((endp lst) nil)
          ((eq x (car lst)) lst)
          (t (member-eq-exec x (cdr lst)))))

  (defun member-eql-exec (x lst)
    (declare (xargs :guard (if (eqlablep x)
                               (true-listp lst)
                             (eqlable-listp lst))))
    (cond ((endp lst) nil)
          ((eql x (car lst)) lst)
          (t (member-eql-exec x (cdr lst)))))
 })

 <p>At this point the user can write @('(member x y)') or @('(member-equal x
 y)') to call equality variants of @('member') with test @('eql') or
 @('equal'), respectively.  We thus provide the following macro for the @('eq')
 variant.</p>

 @({
  (defmacro member-eq (x lst)
    `(member ,x ,lst :test 'eq))
 })

 <p>@(see Guard) proof obligations generated by calls of @('member') will
 include those based on its use of @('mbe'), and are supported by the following
 two lemmas.</p>

 @({
  (defthm member-eq-exec-is-member-equal
    (equal (member-eq-exec x l)
           (member-equal x l)))

  (defthm member-eql-exec-is-member-equal
    (equal (member-eql-exec x l)
           (member-equal x l)))
 })

 <p>Finally, the following two events arrange that in certain contexts such as
 @(see theories) (including the use of @(tsee in-theory) in @(see events) and
 @(see hints)), @(tsee member-eq) and @(tsee member) are treated as references
 to @(tsee member-equal).</p>

 @({
  (add-macro-alias member-eq member-equal)
  (add-macro-alias member member-equal)
 })

 <p>Note however that these events do not affect printing of calls during
 proofs: calls of @('member') and @('member-eq') will be macroexpanded away,
 leaving you with calls of @('member-equal') that are displayed in proof
 output.  For a way to change this behavior, see @(tsee add-macro-fn).</p>

 <p>We conclude this topic by exploring the following recommendation made in
 the @(see documentation) for @(see equality-variants).</p>

 <blockquote><p>For efficiency we recommend using the @('-equal') equality
 variant, for example @(tsee member-equal) or @('(')@(tsee member)@(' ... :TEST
 'equal)'), in certain contexts: @(tsee defmacro), @(tsee defpkg), @(tsee
 defconst), and @(tsee value-triple) forms.</p></blockquote>

 <p>ACL2 relies on the underlying Common Lisp for evaluation.  It also
 processes events in the ACL2 logic.  In order to guarantee consistency of its
 logical and Common Lisp evaluations, ACL2 uses a ``safe mode'' to avoid
 ill-guarded calls.  In particular, consider the use of @(tsee mbe) in
 execution of a call of an equality variant of a primitive, @('F'), other than
 its @('F-equal') variant.  The @(tsee mbe) call discussed above requires a
 connection to be established between the @(':logic') and @(':exec') forms.
 For example, if @('F') is called with @(':TEST 'eql') (either explicitly or as
 the default), then ACL2 will call both @('F-eql-exec') and @('F-equal'), and
 check that the two results are equal.</p>

 <p>The following partial log illustrates the point above.  We define a macro
 that calls @(tsee member), and when a call of this macro is expanded during
 processing of a subsequent definition, we see that two membership functions
 are called on the same arguments.</p>

 @({
  ACL2 !>(defmacro mac (lst)
           (list 'quote (and (true-listp lst)
                             (member 'c lst :test 'eq))))

  Summary
  Form:  ( DEFMACRO MAC ...)
  Rules: NIL
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
   MAC
  ACL2 !>(trace$ member-equal member-eq-exec)
   ((MEMBER-EQUAL) (MEMBER-EQ-EXEC))
  ACL2 !>(defun f () (mac (a b c d)))
  1> (ACL2_*1*_ACL2::MEMBER-EQ-EXEC C (A B C D))
    2> (MEMBER-EQ-EXEC C (A B C D))
    <2 (MEMBER-EQ-EXEC (C D))
  <1 (ACL2_*1*_ACL2::MEMBER-EQ-EXEC (C D))
  1> (ACL2_*1*_ACL2::MEMBER-EQUAL C (A B C D))
    2> (MEMBER-EQUAL C (A B C D))
    <2 (MEMBER-EQUAL (C D))
  <1 (ACL2_*1*_ACL2::MEMBER-EQUAL (C D))

  Since F is non-recursive, its admission is trivial.
 })

 <p>If performance is an issue then we can avoid such a problem, for example as
 follows.  In a fresh session, let us define a suitable wrapper for calling
 @(tsee member) with @(':TEST 'eq').  This time, the trace in our partial log
 shows that we have avoided calling two membership functions.</p>

 @({
  ACL2 !>(defun mem-eq (x lst)
           (declare (xargs :guard (if (symbolp x)
                                      (true-listp lst)
                                    (symbol-listp lst))))
           (member x lst :test 'eq))
  [[ ... output omitted here ... ]]
   MEM-EQ
  ACL2 !>(defmacro mac (lst)
           (list 'quote (and (true-listp lst)
                             (mem-eq 'c lst))))

  Summary
  Form:  ( DEFMACRO MAC ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   MAC
  ACL2 !>(trace$ member-equal member-eq-exec mem-eq)
   ((MEMBER-EQUAL)
    (MEMBER-EQ-EXEC)
    (MEM-EQ))
  ACL2 !>(defun f () (mac (a b c d)))
  1> (ACL2_*1*_ACL2::MEM-EQ C (A B C D))
    2> (MEM-EQ C (A B C D))
    <2 (MEM-EQ (C D))
  <1 (ACL2_*1*_ACL2::MEM-EQ (C D))

  Since F is non-recursive, its admission is trivial.
 })")

(defxdoc equivalence
  :parents (rule-classes)
  :short "Mark a relation as an equivalence relation"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 @({
  Example:
  (defthm r-equal-is-an-equivalence ; assumes that r-equal has been defined
    (and (booleanp (r-equal x y))
         (r-equal x x)
         (implies (r-equal x y) (r-equal y x))
         (implies (and (r-equal x y)
                       (r-equal y z))
                  (r-equal x z)))
    :rule-classes :equivalence)
 })

 <p>Also see @(see defequiv).</p>

 @({
  General Form:
  (and (booleanp (equiv x y))
       (equiv x x)
       (implies (equiv x y) (equiv y x))
       (implies (and (equiv x y)
                     (equiv y z))
                (equiv x z)))
 })

 <p>except that the order of the conjuncts and terms and the choice of variable
 symbols is unimportant.  The effect of such a rule is to identify @('equiv')
 as an equivalence relation.  Note that only Boolean 2-place function symbols
 can be treated as equivalence relations.  See @(see congruence) and see @(see
 refinement) for closely related concepts.</p>

 <p>The macro form @('(defequiv equiv)') is an abbreviation for a @(tsee
 defthm) of rule-class @(':equivalence') that establishes that @('equiv') is an
 equivalence relation.  It generates the formula shown above.  See @(see
 defequiv).</p>

 <p>When @('equiv') is marked as an equivalence relation, its reflexivity,
 symmetry, and transitivity are built into the system in a deeper way than via
 @(':')@(tsee rewrite) rules.  More importantly, after @('equiv') has been
 shown to be an equivalence relation, lemmas about @('equiv'), e.g.,</p>

 @({
  (implies hyps (equiv lhs rhs)),
 })

 <p>when stored as @(':')@(tsee rewrite) rules, cause the system to rewrite
 certain occurrences of (instances of) @('lhs') to (instances of) @('rhs').
 Roughly speaking, an occurrence of @('lhs') in the @('kth') argument of some
 @('fn')-expression, @('(fn ... lhs' ...)'), can be rewritten to produce @('(fn
 ...  rhs' ...)'), provided the system ``knows'' that the value of @('fn') is
 unaffected by @('equiv')-substitution in the @('kth') argument.  Such
 knowledge is communicated to the system via ``congruence lemmas.''</p>

 <p>For example, suppose that @('r-equal') is known to be an equivalence
 relation.  The @(':')@(tsee congruence) lemma</p>

 @({
  (implies (r-equal s1 s2)
           (equal (fn s1 n) (fn s2 n)))
 })

 <p>informs the rewriter that, while rewriting the first argument of
 @('fn')-expressions, it is permitted to use @('r-equal') rewrite-rules.  See
 @(see congruence) for details about @(':')@(tsee congruence) lemmas.
 Interestingly, congruence lemmas are automatically created when an equivalence
 relation is stored, saying that either of the equivalence relation's arguments
 may be replaced by an equivalent argument.  That is, if the equivalence
 relation is @('fn'), we store congruence rules that state the following
 fact:</p>

 @({
  (implies (and (fn x1 y1)
                (fn x2 y2))
           (iff (fn x1 x2) (fn y1 y2)))
 })

 <p>Another aspect of equivalence relations is that of ``refinement.''  We say
 @('equiv1') ``refines'' @('equiv2') iff @('(equiv1 x y)') implies @('(equiv2 x
 y)').  @(':')@(tsee refinement) rules permit you to establish such connections
 between your equivalence relations.  The value of refinements is that if the
 system is trying to rewrite something while maintaining @('equiv2') it is
 permitted to use as a @(':')@(tsee rewrite) rule any refinement of
 @('equiv2').  Thus, if @('equiv1') is a refinement of @('equiv2') and there
 are @('equiv1') rewrite-rules available, they can be brought to bear while
 maintaining @('equiv2').  See @(see refinement).</p>

 <p>The system initially has knowledge of two equivalence relations, equality,
 denoted by the symbol @(tsee equal), and propositional equivalence, denoted by
 @(tsee iff).  @(tsee Equal) is known to be a refinement of all equivalence
 relations and to preserve equality across all arguments of all functions.</p>

 <p>Typically there are five steps involved in introducing and using a new
 equivalence relation, equiv.</p>

 <blockquote>

 <p>(1) Define @('equiv'),</p>

 <p>(2) prove the @(':equivalence') lemma about @('equiv'),</p>

 <p>(3) prove the @(':')@(tsee congruence) lemmas that show where @('equiv')
 can be used to maintain known relations,</p>

 <p>(4) prove the @(':')@(tsee refinement) lemmas that relate @('equiv') to
 known relations other than equal, and</p>

 <p>(5) develop the theory of conditional @(':')@(tsee rewrite) rules that
 drive equiv rewriting.</p>

 </blockquote>

 <p>More will be written about this as we develop the techniques.  For now,
 here is an example that shows how to make use of equivalence relations in
 rewriting.</p>

 <p>Among the theorems proved below is</p>

 @({
  (defthm insert-sort-is-id
    (perm (insert-sort x) x))
 })

 <p>Here @('perm') is defined as usual with @('delete') and is proved to be an
 equivalence relation and to be a congruence relation for @(tsee cons) and
 @(tsee member).</p>

 <p>Then we prove the lemma</p>

 @({
  (defthm insert-is-cons
    (perm (insert a x) (cons a x)))
 })

 <p>which you must think of as you would @('(insert a x) = (cons a x)').</p>

 <p>Now prove @('(perm (insert-sort x) x)').  The base case is trivial.  The
 induction step is</p>

 @({
     (consp x)
   & (perm (insert-sort (cdr x)) (cdr x))

  -> (perm (insert-sort x) x).
 })

 <p>Opening @('insert-sort') makes the conclusion be</p>

 @({
     (perm (insert (car x) (insert-sort (cdr x))) x).
 })

 <p>Apply @('insert-is-cons') to get</p>

 @({
  (perm (cons (car x) (insert-sort (cdr x)) x)).
 })

 <p>Note that we have proved that @('perm') is a congruence relation for
 @('cons'). That allows us to apply the induction hypothesis (rewriting
 @('(insert-sort (cdr x))') to @('(cdr x)')), to make the conclusion be</p>

 @({
  (perm (cons (car x) (cdr x)) x).
 })

 <p>But we know that @('(cons (car x) (cdr x))') is @('x'), so we get @('(perm
 x x)') which is trivial, since @('perm') is an equivalence relation.  An
 exercise left to the reader is how this proof will change had we also proved
 that @('perm') is a congruence relation for @('insert').</p>

 <p>Here are the events.</p>

 @({
  (encapsulate (((lt * *) => *))
    (local (defun lt (x y) (declare (ignore x y)) nil))
    (defthm lt-non-symmetric (implies (lt x y) (not (lt y x)))))

  (defun insert (x lst)
    (cond ((atom lst) (list x))
          ((lt x (car lst)) (cons x lst))
          (t (cons (car lst) (insert x (cdr lst))))))

  (defun insert-sort (lst)
    (cond ((atom lst) nil)
          (t (insert (car lst) (insert-sort (cdr lst))))))

  (defun del (x lst)
    (cond ((atom lst) nil)
          ((equal x (car lst)) (cdr lst))
          (t (cons (car lst) (del x (cdr lst))))))

  (defun mem (x lst)
    (cond ((atom lst) nil)
          ((equal x (car lst)) t)
          (t (mem x (cdr lst)))))

  (defun perm (lst1 lst2)
    (cond ((atom lst1) (atom lst2))
          ((mem (car lst1) lst2)
           (perm (cdr lst1) (del (car lst1) lst2)))
          (t nil)))

  (defthm perm-reflexive
    (perm x x))

  (defthm perm-cons
    (implies (mem a x)
             (equal (perm x (cons a y))
                    (perm (del a x) y)))
    :hints ((\"Goal\" :induct (perm x y))))

  (defthm perm-symmetric
    (implies (perm x y) (perm y x)))

  (defthm mem-del
    (implies (mem a (del b x)) (mem a x)))

  (defthm perm-mem
    (implies (and (perm x y)
                  (mem a x))
             (mem a y)))

  (defthm mem-del2
    (implies (and (mem a x)
                  (not (equal a b)))
             (mem a (del b x))))

  (defthm comm-del
    (equal (del a (del b x)) (del b (del a x))))

  (defthm perm-del
    (implies (perm x y)
             (perm (del a x) (del a y))))

  (defthm perm-transitive
    (implies (and (perm x y) (perm y z)) (perm x z)))

  (defequiv perm)

  (in-theory (disable perm
                      perm-reflexive
                      perm-symmetric
                      perm-transitive))

  (defcong perm perm (cons x y) 2)

  (defcong perm iff (mem x y) 2)

  (defthm atom-perm
    (implies (not (consp x)) (perm x nil))
    :rule-classes :forward-chaining
    :hints ((\"Goal\" :in-theory (enable perm))))

  (defthm insert-is-cons
    (perm (insert a x) (cons a x)))

  (defthm insert-sort-is-id
    (perm (insert-sort x) x))

  (defun app (x y) (if (consp x) (cons (car x) (app (cdr x) y)) y))

  (defun rev (x)
    (if (consp x) (app (rev (cdr x)) (list (car x))) nil))

  (defcong perm perm (app x y) 2)

  (defthm app-cons
    (perm (app a (cons b c)) (cons b (app a c))))

  (defthm app-commutes
    (perm (app a b) (app b a)))

  (defcong perm perm (app x y) 1
    :hints ((\"Goal\" :induct (app y x))))

  (defthm rev-is-id (perm (rev x) x))

  (defun == (x y)
    (if (consp x)
        (if (consp y)
            (and (equal (car x) (car y))
                 (== (cdr x) (cdr y)))
            nil)
        (not (consp y))))

  (defthm ==-reflexive (== x x))

  (defthm ==-symmetric (implies (== x y) (== y x)))

  (defequiv ==)

  (in-theory (disable ==-symmetric ==-reflexive))

  (defcong == == (cons x y) 2)

  (defcong == iff (consp x) 1)

  (defcong == == (app x y) 2)

  (defcong == == (app x y) 1)

  (defthm rev-rev (== (rev (rev x)) x))
 })")

(defxdoc equivalent-formulas-different-rewrite-rules
  :parents (introduction-to-the-theorem-prover)
  :short "Logically equivalent formulas can generate radically different rules"
  :long "<p>Consider the rewrite rules that would be generated from the three
 commands below.  In all three cases, the fact being stated relates the
 @('n')th element of the reverse of @('x') to the @('n')th element of @('x').
 In fact, the three formulas are simple rearrangements of each other and are
 all equivalent.  The theorem prover treats all three formulas equivalently
 when proving them.  But the rules generated from them are very different.</p>

 @({
  (defthm nth-rev-1
    (implies (and (natp n)
                  (< n (len x)))
             (equal (nth n (rev x))
                    (nth (- (len x) (+ 1 n)) x))))

  (defthm nth-rev-2
    (implies (and (natp n)
                  (< n (len x)))
             (equal (nth (- (len x) (+ 1 n)) x)
                    (nth n (rev x)))))

  (defthm nth-rev-3
    (implies (and (natp n)
                  (not (equal (nth n (rev x))
                              (nth (- (len x) (+ 1 n)) x))))
             (not (< n (len x)))))
 })

 <p>Here are the three rewrite rules:</p>

 <p><b>nth-rev-1</b>:<br></br>

 Replace instances of @('(NTH n (REV x))')<br></br>

 by @('(NTH (- (LEN x) (+ 1 n)) x)'),<br></br>

 if you can establish that @('n') is a natural number less than the length of
 @('x').</p>

 <p><b>nth-rev-2</b>:<br></br>

 Replace instances of @('(NTH (- (LEN x) (+ 1 n)) x)')<br></br>

 by @('(NTH n (REV x))'),<br></br>

 if you can establish that @('n') is a natural number less than the length of
 @('x').</p>

 <p><b>nth-rev-3</b>:<br></br>

 Replace instances of @('(< n (LEN x))')<br></br>

 by @('NIL')<br></br>

 if you can establish that @('n') is a natural number and that @('(NTH n (REV
 x))') is different from @('(NTH (- (LEN x) (+ 1 n)) x)').</p>

 <p>As the driver of ACL2, you have to decide which rule you want <i>when you
 give the command to prove it</i>.</p>

 <p>If you tell the theorem prover to use both @('nth-rev-1') and
 @('nth-rev-2'), ACL2 will enter an infinite loop when it sees any term
 matching either @('NTH') expression.</p>

 <p>Most users would choose form @('nth-rev-1') of the rule.  It eliminates
 @('rev') from the problem &mdash; at the expense of introducing some
 arithmetic.  But arithmetic is so fundamental it is rarely possible to avoid
 it and it is likely to be in the problem already since you're indexing into
 @('(rev x)').  The @('nth-rev-2') form of the rule is ``bad'' because it
 introduces @('rev') into a problem where it might not have appeared.  The
 @('nth-rev-3') version is ``bad'' because it makes the theorem prover shift
 its attention from a simple arithmetic inequality to a complicated property of
 @('nth') and @('rev'), which might not be in the problem.</p>

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-rewrite-rules-part-1).</p>")

(defxdoc er
  :parents (errors acl2-built-ins)
  :short "Print an error message and ``cause an error''"
  :long "<p>See @(see fmt) for a general discussion of formatted printing in
 ACL2.  All calls of @('er') print formatted strings, just as is done by @(tsee
 fmt).</p>

 @({
  Example Forms:
  (er hard  'top-level \"Illegal inputs, ~x0 and ~x1.\" a b)
  (er hard? 'top-level \"Illegal inputs, ~x0 and ~x1.\" a b)
  (er hard! 'top-level \"Illegal inputs, ~x0 and ~x1.\" a b)
  (er soft  'top-level \"Illegal inputs, ~x0 and ~x1.\" a b)
 })

 <p>The examples above all print an error message to standard output saying
 that @('a') and @('b') are illegal inputs.  However, the first three abort
 evaluation after printing an error message (while logically returning
 @('nil'), though in ordinary evaluation the return value is never seen); while
 the last returns @('(mv t nil state)') after printing an error message.  The
 result in the last case can be interpreted as an ``error'' when programming
 with the ACL2 @(tsee state), something most ACL2 users will probably not want
 to do unless they are building systems of some sort; see @(see
 programming-with-state).  If state is not available in the current context
 then you will probably want to use a call other than the last to cause an
 error; for example, if you are returning two values, you may write @('(mv (er
 hard ...) nil)').</p>

 <p>The difference between the @('hard') and @('hard?') forms is one of guards.
 Use @('hard') if you want the call to generate a (clearly impossible) guard
 proof obligation of (essentially) @('NIL').  But use @('hard?') if you want to
 be able to call this function in guard-verified code, since the call generates
 a (trivially satisfied) guard proof obligation of @('T').</p>

 <p>The difference between the @('hard') and @('hard!') forms is that there are
 situations in which @('(er hard ...)') returns @('nil') rather than causing an
 error, while @('(er hard! ...)') will always cause an error (though such
 errors are sometimes ``caught'', for example during proofs).  You will
 probably be happy using @('hard') rather than considering the use of
 @('hard!'), which is really provided mostly for system implementors; but you
 can try @('hard!') if you are not getting the errors you expect.  There is
 even an additional option, @('hard?!'), which avoids guard proof obligations
 like @('hard?') but ensures errors like @('hard!').</p>

 <p>@('Er') is a macro, and the above examples expand to calls of ACL2
 functions, as shown below.  See @(see illegal), see @(see hard-error), and see
 @(see error1).  The @('hard?')/@('hard?!') forms have guards of (essentially)
 @('NIL') while the @('hard')/@('hard!') forms have guards of (essentially)
 @('T').  @(tsee Error1), on the other hand, is in @(':')@(tsee program)
 mode; for variants of @('(er soft ...)') that generate @(':')@(tsee logic)
 mode code, see @(see er-soft-logic) and @(see er-soft+).</p>

 @({
  General forms:
  (er hard  ctx fmt-string arg1 arg2 ... argk)
    ==> {macroexpands, in essence, to:}
  (ILLEGAL    CTX FMT-STRING
              (LIST (CONS #\\0 ARG1) (CONS #\\1 ARG2) ... (CONS #\\k ARGk)))

  (er hard? ctx fmt-string arg1 arg2 ... argk)
    ==> {macroexpands, in essence, to:}
  (HARD-ERROR CTX FMT-STRING
              (LIST (CONS #\\0 ARG1) (CONS #\\1 ARG2) ... (CONS #\\k ARGk)))

  (er hard! ctx fmt-string arg1 arg2 ... argk)
    ; logically is same as (er hard ...), but always produces an error

  (er soft  ctx fmt-string arg1 arg2 ... argk)
    ==> {macroexpands, in essence, to:}
  (ERROR1     CTX FMT-STRING
              (LIST (CONS #\\0 ARG1) (CONS #\\1 ARG2) ... (CONS #\\k ARGk)))
 })

 <p>See @(see ctx) for the possible forms of the @('ctx') argument.</p>

 <p>Technical note for raw Lisp programmers only: It is possible to cause hard
 errors to signal actual raw Lisp errors.  See @(see hard-error).</p>")

(defxdoc er-progn
  :parents (errors programming-with-state acl2-built-ins)
  :short "Perform a sequence of state-changing ``error triples''"
  :long "@({
  Example:
  (er-progn (check-good-foo-p (f-get-global 'my-foo state) state)
            (value (* (f-get-global 'my-foo state)
                      (f-get-global 'bar state))))
 })

 <p>This sequencing primitive is only useful when programming with @(see
 state), something that very few users will probably want to do.  See @(see
 state).</p>

 <p>@('Er-progn') is used much the way that @(tsee progn) is used in Common
 Lisp, except that it expects each form within it to evaluate to an @(see
 error-triple) of the form @('(mv erp val state)').  The first such form, if
 any, that evaluates to such a triple where @('erp') is not @('nil') yields the
 error triple returned by the @('er-progn').  If there is no such form, then
 the last form returns the value of the @('er-progn') form.</p>

 @({
  General Form:
  (er-progn <expr1> ... <exprk>)
 })

 <p>where each @('<expri>') is an expression that evaluates to an error triple
 (see @(see programming-with-state)).  The above form is essentially equivalent
 to the following (``essentially'' because in fact, care is taken to avoid
 variable capture).</p>

 @({
  (mv-let (erp val state)
          <expr1>
          (cond (erp (mv erp val state))
                (t (mv-let (erp val state)
                           <expr2>
                           (cond (erp (mv erp val state))
                                 (t ...
                                        (mv-let (erp val state)
                                                <expr{k-1}>
                                                (cond (erp (mv erp val state))
                                                      (t <exprk>)))))))))
 })")

(defxdoc error-triple
  :parents (errors programming-with-state)
  :short "A common ACL2 programming idiom"
  :long "<p>When evaluation returns three values, where the first two are
 ordinary (non-@(see stobj)) objects and the third is the ACL2 @(see state),
 the result may be called an ``error triple'' or ``error-triple''.  If an error
 triple is @('(mv erp val state)'), we think of @('erp') as an error flag and
 @('val') as the returned value.  By default, if the result of evaluating a
 top-level form is an error triple @('(mv erp val state)'), then that result is
 not printed if @('erp') is non-@('nil') or if @('val') is the keyword
 @(':INVISIBLE'), and otherwise @('val') is printed with a preceding space.
 For example:</p>

 @({
  ACL2 !>(+ 3 4) ; ordinary value
  7
  ACL2 !>(mv nil (+ 3 4) state) ; error triple, error component of nil
   7
  ACL2 !>(mv t (+ 3 4) state) ; error triple, non-nil error component
  ACL2 !>(mv nil :invisible state) ; special case for :INVISIBLE
  ACL2 !>
 })

 <p>See @(see programming-with-state) for a discussion of error triples and how
 to program with them.  Also see @(see ld-error-triples) and see @(see ld) for
 a discussion of the value @(':COMMAND-CONVENTIONS') for keyword
 @(':LD-POST-EVAL-PRINT').</p>")

(defxdoc error-triples-and-parallelism
  :parents (parallel-programming)
  :short "How to avoid error triples in ACL2(p)"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 <p>ACL2 supports the use of error triples in many features; e.g., @(tsee
 computed-hints).  (For background on error triples, see @(see
 programming-with-state).)  However, ACL2(p) does not support the use of error
 triples in some of these features (e.g., @(tsee computed-hints)) while @(see
 waterfall-parallelism) is enabled.</p>

 <p>You may see an error message like the following when running ACL2(p) with
 @(see waterfall-parallelism) enabled:</p>

 @({
  ACL2 Error in ( THM ...):  Since we are translating a form in ACL2(p)
  intended to be executed with waterfall parallelism enabled, the form
  (MY-STATE-MODIFYING-COMPUTED-HINT ID STATE) was expected to represent
  an ordinary value, not an error triple (mv erp val state), as would
  be acceptable in a serial execution of ACL2.  Therefore, the form returning
  a tuple of the form (* * STATE) is an error.  See :DOC unsupported-
  waterfall-parallelism-features and :DOC error-triples-and-parallelism
  for further explanation.
 })

 <p>In this particular example, the cause of the error was trying to use a
 computed hint that returned state, which is not allowed when executing the
 waterfall in parallel (see @(see unsupported-waterfall-parallelism-features)
 for other related information).</p>

 <p>Often, the only reason users need to return state is so they can perform
 some output during the proof process.  In this case, we suggest using one of
 the state-free output functions, like @(tsee cw) or @(tsee observation-cw).
 If the user is concerned about the interleaving of their output with other
 output, these calls can be surrounded with the macro @(tsee
 with-output-lock).</p>

 <p>Another frequent reason users return state is so they can cause a @('soft')
 error and halt the proof process.  In this case, we suggest instead calling
 @(tsee er) with the @('hard') or @('hard?') severity.  By using these
 mechanisms, the user avoids modifying @(tsee state), a requirement for much of
 the code written in ACL2(p).</p>

 <p>You may encounter other similar error messages when using @(see
 computed-hints), @(see custom-keyword-hints), or @(see override-hints).
 Chances are that you are somehow returning an error triple when an ordinary
 value is needed.  If this turns out not to be the case, please let the ACL2
 implementors know.</p>")

(defxdoc error1
  :parents (errors acl2-built-ins)
  :short "Print an error message and cause a ``soft error''"
  :long "<p>@('(Error1 ctx str alist)') returns @('(mv t nil state)').  An
 error message is first printed using the the ``context'' @('ctx'), as well as
 the string @('str') and alist @('alist') that are of the same kind as expected
 by @(tsee fmt).  See @(see fmt).</p>

 <p>@('Error1') can be interpreted as causing an ``error'' when programming
 with the ACL2 @(tsee state), something most ACL2 users will probably not want
 to do; see @(see ld-error-triples) and see @(see er-progn).  In order to cause
 errors with @(':')@(tsee logic) mode functions, see @(see hard-error) and see
 @(see illegal).  Better yet, see @(see er) for a macro that provides a unified
 way of signaling errors.</p>

 <p>As mentioned above, @('error1') always returns @('(mv t nil state)').  But
 if a call @('(error1 ctx str alist)') is encountered during evaluation, then
 the string @('str') is first printed using the association list @('alist') (as
 in @(tsee fmt)).  Here is a trivial, contrived example.</p>

 @({
  ACL2 !>(error1 'my-context
                 \"Printing 4: ~n0\"
                 (list (cons #\\0 4))
                 state)

  ACL2 Error in MY-CONTEXT:  Printing 4: four

  ACL2 !>
 })")

(defxdoc errors
  :parents (programming)
  :short "Support for causing runtime errors, breaks, assertions, etc.")

(defxdoc escape-to-common-lisp
  :parents (common-lisp)
  :short "Escaping to Common Lisp"
  :long "@({
  Example:
  ACL2 !>:Q
 })

 <p>There is essentially no Common Lisp escape feature in the @(tsee lp) (but
 see @(see set-raw-mode)).  This is part of the price of purity.  To execute a
 form in Common Lisp as opposed to ACL2, exit @(tsee lp) with @(':')@(tsee q),
 submit the desired forms to the Common Lisp read-eval-print loop, and reenter
 ACL2 with @('(lp)').</p>")

(defxdoc evaluation
  :parents (programming)
  :short "Evaluating ACL2 expressions"
  :long "<p>This topic uses examples to expose how ACL2 uses Common Lisp to
 evaluate expressions.  Links are provided to topics that elaborate on
 aspects of evaluation in ACL2.</p>

 <p>At a high level, we can say that ACL2 evaluation takes place using the
 underlying host Common Lisp.  But consider the form @('(car 3)').  In Common
 Lisp this is an error; typically you will be thrown into the Lisp debugger.
 In the ACL2 read-eval-print loop, however, you may see the following.</p>

 @({
 ACL2 !>(car 3)


 ACL2 Error in TOP-LEVEL:  The guard for the function call (CAR X),
 which is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments
 in the call (CAR 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 !>
 })

 <p>The message suggests that the function @('car') has a @(see guard), or
 precondition, that is violated by the proposed argument, @('3').  So clearly
 something more is going on here than just evaluation of the form @('(car 3)')
 in Common Lisp.</p>

 <p>In fact, every ACL2 function symbol is associated with the following two
 Common Lisp definitions, as explained below:</p>

 <ul>

 <li>the ``executable-counterpart'' definition, sometimes called the ``*1*''
 function (pronounced ``star one star''); and</li>

 <li>the ``submitted'' definition (sometimes called the ``raw Lisp''
 function).</li>

 </ul>

 <p>We may also speak of the ``executable-counterpart'' and ``submitted''
 functions, which are the two functions defined by the
 ``executable-counterpart'' and ``submitted'' definitions, respectively.</p>

 <p>Let us explore these two functions in the case of @('car').  When @('(car
 3)') is evaluated in the ACL2 loop, the executable-counterpart of @('car') is
 applied to the argument @('3').  That executable-counterpart (which was
 hand-coded) first checks the guard of @('car'), which fails for @('3'),
 leading to the error displayed above.  If instead the form to be evaluated by
 ACL2 is @('(car '(4 5 6))'), the executable-counterpart of @('car') will first
 check that the guard of @('car') holds for the list argument @('(4 5 6)');
 then seeing that this is the case, it will apply the Common Lisp function
 @('car') &mdash; which we consider to be the ``submitted'' function for
 @('car') &mdash; to that list argument, returning @('4').</p>

 <p>The example above does not really explain why the submitted function is
 called ``submitted'', so let us consider the more common case of a defined
 function, as opposed to a @(see primitive) like @('car').  Suppose we define
 the following functions @('f') and @('g'), each of which has an implicit @(see
 guard) (precondition) of @('t'), i.e., the precondition always holds.</p>

 @({
 (defun f (x)
   (car x))
 (defun g (x)
   (f x))
 })

 <p>ACL2 defines two functions named @('\"F\"'): the executable-counterpart of
 @('f'), sometimes called ``@('*1*f')'', and the submitted function for @('f').
 It also defines two such functions for @('g').  The executable-counterpart is
 generated by ACL2 to include not only code to check guards, but also code to
 invoke the executable-counterparts of its callees.  (Such invocation can be
 avoided by a process known as verifying guards, as we explain further below.)
 We can see what is going on by tracing calls of @('f') (see @(see trace) for
 more about tracing); some analysis follows below this display.</p>

 @({
 ACL2 !>(trace$ f g)
  ((F) (G))
 ACL2 !>(g '(4 5 6))
 1> (ACL2_*1*_ACL2::G (4 5 6))
   2> (ACL2_*1*_ACL2::F (4 5 6))
   <2 (ACL2_*1*_ACL2::F 4)
 <1 (ACL2_*1*_ACL2::G 4)
 4
 ACL2 !>
 })

 <p>It is now perhaps evident why sometimes we call the executable-counterpart
 functions the ``*1* functions'': the executable-counterpart is actually
 defined in a special ``*1*'' package that corresponds to the package of the
 submitted function.  The trace above shows that the executable-counterpart of
 @('g') calls the executable-counterpart of @('f'), rather than calling any
 submitted function.</p>

 <p>Such a trace can show us an error caused by applying @('car') to
 @('3').</p>

 @({
 ACL2 !>(g 3)
 1> (ACL2_*1*_ACL2::G 3)
   2> (ACL2_*1*_ACL2::F 3)


 ACL2 Error in TOP-LEVEL:  The guard for the function call (CAR X),
 which is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments
 in the call (CAR 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 !>
 })

 <p>It is generally more efficient to invoke a submitted functions &mdash;
 which has as its Common Lisp definition exactly the @(tsee defun) form
 submitted to ACL2 &mdash; than it is to invoke an executable-counterpart,
 which is generated by ACL2 to do auxiliary calculations including
 guard-checking.  So we next modify the example above to show that by
 performing a process called ``guard verification'', we can avoid *1* function
 calls, so that submitted functions are invoked instead.  This time we supply
 reasonable guards for @('f') and @('g'), in a fresh ACL2 session.</p>

 @({
 (defun f (x)
   (declare (xargs :guard (or (consp x) (null x))))
   (car x))
 (defun g (x)
   (declare (xargs :guard (consp x)))
   (f x))
 })

 <p>This time, we see that the executable-counterpart of @('g') directly calls
 the submitted function for @('g'), because @('g') was guard-verified when
 @('g') was admitted and the value @(''(4 5 6)') for the formal @('x') of
 @('g') satisfies the guard @('(consp x)') of @('g').</p>

 @({
 ACL2 !>(trace$ f g)
  ((F) (G))
 ACL2 !>(g '(4 5 6))
 1> (ACL2_*1*_ACL2::G (4 5 6))
   2> (G (4 5 6))
     3> (F (4 5 6))
     <3 (F 4)
   <2 (G 4)
 <1 (ACL2_*1*_ACL2::G 4)
 4
 ACL2 !>
 })

 <p>We can also see that because @('3') fails to satisfy the guard of @('g'), a
 guard violation is signaled by the executable-counterpart of @('g'), rather
 than (as before) by the executable-counterpart of @('car').</p>

 @({
 ACL2 !>(g 3)
 1> (ACL2_*1*_ACL2::G 3)


 ACL2 Error in TOP-LEVEL:  The guard for the function call (G X), which
 is (CONSP X), is violated by the arguments in the call (G 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 !>
 })

 <p>See if you can predict the corresponding traces if instead, @('f') has a
 suitable guard and is guard-verified, but @('g') is as in the first
 example (with an implicit guard of @('t'), and not guard-verified):</p>

 @({
 (defun f (x)
   (declare (xargs :guard (or (consp x) (null x))))
   (car x))
 (defun g (x)
   (f x))
 })

 <p>The corresponding trace is as follows; discussion follows.</p>

 @({
 ACL2 !>(g '(4 5 6))
 1> (ACL2_*1*_ACL2::G (4 5 6))
   2> (ACL2_*1*_ACL2::F (4 5 6))
     3> (F (4 5 6))
     <3 (F 4)
   <2 (ACL2_*1*_ACL2::F 4)
 <1 (ACL2_*1*_ACL2::G 4)
 4
 ACL2 !>(g 3)
 1> (ACL2_*1*_ACL2::G 3)
   2> (ACL2_*1*_ACL2::F 3)


 ACL2 Error in TOP-LEVEL:  The guard for the function call (F X), which
 is (OR (CONSP X) (NULL X)), is violated by the arguments in the call
 (F 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 !>
 })

 <p>The traces above show that first, the executable-counterpart of @('g')
 calls the executable-counterpart of @('f').  This is because @('g') is not
 guard-verified, so its executable-counterpart can only invoke other
 executable-counterparts.  However, since @('f') is guard-verified, its
 executable-counterpart invokes its submitted function when the guard is
 satisfied, for example to generate the call @('(F (4 5 6))').  If the guard
 for @('f') fails to hold, however, the executable-counterpart for @('f')
 causes a guard violation error, as shown above for the executable-counterpart
 call @('(ACL2_*1*_ACL2::F 3)').</p>

 <p>See also @(see guard) and its subtopics, especially, @(see
 guards-and-evaluation), for a discussion of guards and their connection to
 evaluation.  Advanced system hackers who want to see the
 executable-counterpart definition for @('f') may invoke @('(trace!
 (oneify-cltl-code :native t))') before defining @('f') in ACL2.</p>")

(defxdoc evaluator-restrictions
  :parents (meta)
  :short "Some restrictions on the use of evaluators in meta-level rules"
  :long "<p>Note: This topic, which explains some subtleties for evaluators,
 can probably be skipped by most readers.</p>

 <p>Rules of class @(':')@(tsee meta) and of class @(':')@(tsee
 clause-processor) are stated using so-called ``evaluator'' functions.  Here we
 explain some restrictions related to evaluators.  Below we refer primarily to
 @(':meta') rules, but the discussion applies equally to @(':clause-processor')
 rules.</p>

 <p>In a nutshell, we require that a rule's evaluator does not support other
 functions in the rule, and we require that the evaluator not be introduced
 under a non-trivial encapsulate.  We also require that no function has an
 attachment (see @(see defattach)) that is both ancestral in the evaluator and
 also ancestral in the meta or clause-processor functions.  We explain these
 restrictions in detail below.</p>

 <p>An argument given elsewhere (see @(see meta), in particular ``Aside for the
 logic-minded'') explains that the correctness argument for applying
 metatheoretic simplifiers requires that one be able to ``grow'' an evaluator
 (see @(see defevaluator)) to handle all functions in the current ACL2 @(see
 world).  Then we may, in essence, functionally instantiate the original
 evaluator to the new (``grown'') evaluator, provided that the new evaluator
 satisfies all of the axioms of the original.  We therefore require that the
 evaluator function does not support the formula of any @(tsee defaxiom) event.
 This notion of ``support'' (sometimes denoted ``is an ancestor of'') is
 defined recursively as follows: a function symbol supports a formula if either
 it occurs in that formula, or else it supports the definition or constraint
 for some function symbol that occurs in that formula.  Moreover, we require
 that neither the evaluator function nor its list version support the
 definition or constraint for any other function symbol occurring in the
 proposed @(':meta') theorem.</p>

 <p>We also require that the evaluator does not support the formula of a
 @(':meta') rule's metafunction (nor, if there is one, hypothesis metafunction)
 or of a @(':clause-processor') rule's clause-processor function.  This
 requirement, along with with the analogous requirement for @(tsee defaxiom)
 @(see events) stated above, are necessary in order to carry out the functional
 instantiation argument alluded to above, as follows (where the reader may find
 it useful to have some familiarity with the paper ``Structured Theory
 Development for a Mechanized Logic'' (Journal of Automated Reasoning 26, no. 2
 (2001), pages 161-203).  By the usual conservativity argument, we know that
 the rule follows logically from the axiomatic events for its supporters.  This
 remains true if we functionally instantiate the evaluator with one
 corresponding to all the functions symbols of the current session, since none
 of the definitions of supporters of defaxioms or metafunctions are hit by that
 functional substitution.</p>

 <p>Notice though that the argument above depends on knowing that the rule is
 not itself an axiom about the evaluator!  Therefore, we also restrict
 evaluators so that they are not defined in the scope of a superior @(tsee
 encapsulate) event with non-empty signature, in order to avoid an even more
 subtle problem.  The aforementioned correctness argument depends on knowing
 that the rule is provable from the axioms on the evaluator and metafunction
 (and hypothesis metafunction, if any).  The additional restriction avoids
 unsoundness!  The following events, if allowed, produce a proof that @('(f
 x)') equals @('t') even though, as shown below, that does not follow logically
 from the axioms introduced.</p>

 @({
  ; Introduce our metafunction.
  (defun my-cancel (term)
    (case-match term
      (('f ('g))
       *t*)
      (& term)))

  ; Introduce our evaluator and prove our meta rule, but in the same
  ; encapsulate!
  (encapsulate
   ((f (x) t))

   (local (defun f (x) (declare (ignore x)) t))

   (defevaluator evl evl-list
     ((f x)))

   (defthm correctness-of-my-cancel
     (equal (evl x a)
            (evl (my-cancel x) a))
     :rule-classes ((:meta :trigger-fns (f)))))

  ; Prove that (f x) = t.
  (encapsulate
   ()

   (local (defstub c () t))

   (local (encapsulate
           ()
           (local (defun g () (c)))
           (local (in-theory (disable g (g))))
           (local (defthm f-g
                    (equal (f (g)) t)
                    :rule-classes nil))
           (defthm f-c
             (equal (f (c)) t)
             :hints ((\"Goal\" :use f-g
                      :in-theory (e/d (g) (correctness-of-my-cancel))))
             :rule-classes nil)))

   (defthm f-t
     (equal (f x) t)
     :hints ((\"Goal\" :by (:functional-instance
                          f-c
                          (c (lambda () x)))))
     :rule-classes nil))
 })

 <p>To see that the term @('(equal (f x) t)') does not follow logically from
 the axiomatic @(see events) above, consider following the above definition of
 @('my-cancel') with the following @(see events) instead.</p>

 @({
  ; (defun my-cancel (term) ...) as before, then:

  (defun f (x)
    (not x))

  (defun g ()
    nil)

  (defevaluator evl evl-list
     ((f x) (g)))
 })

 <p>These events imply the axiomatic events above, because we still have the
 definition of @('my-cancel'), we have a stronger @(tsee defevaluator) event,
 and we can now prove @('correctness-of-my-cancel') exactly as it is stated
 above.  So, the rule @('f-t') is a logical consequence of the chronology of
 the current session.  However, in the current session we can also prove the
 following rule, which contradicts @('f-t').</p>

 @({
  (defthm f-not-t
    (equal (f t) nil)
    :rule-classes nil)
 })

 <p>It follows that the current session logically yields a contradiction!</p>

 <p>Erik Reeber has taken the above example and modified it to prove @('nil')
 in ACL2 Version_3.1, as follows.</p>

 @({
  (in-package \"ACL2\")

  (defun my-cancel (term)
     (case-match term
       (('f ('g))
        *t*)
       (('f2 ('g2))
        *t*)
       (& term)))

  (defun f2 (x)
     (not x))

  (defun g2 ()
     nil)

  (encapsulate
    ((f (x) t))

    (local (defun f (x) (declare (ignore x)) t))

    (defevaluator evl evl-list
      ((f x)
       (f2 x)
       (g2)))

    (defthm correctness-of-my-cancel
      (equal (evl x a)
             (evl (my-cancel x) a))
      :rule-classes ((:meta :trigger-fns (f)))))

  (encapsulate
    ()

    (local (defstub c () t))

    (local (encapsulate
            ()
            (local (defun g () (c)))
            (local (in-theory (disable g (g))))
            (local (defthm f-g
                     (equal (f (g)) t)
                     :rule-classes nil))
            (defthm f-c
              (equal (f (c)) t)
              :hints ((\"Goal\" :use f-g
                       :in-theory (e/d (g) (correctness-of-my-cancel))))
              :rule-classes nil)))

    (defthm f-t
      (equal (f x) t)
      :hints ((\"Goal\" :by (:functional-instance
                           f-c
                           (c (lambda () x)))))
      :rule-classes nil))

  (defun g ()
     nil)

  ; Below is the expansion of the following defevaluator, changed slightly as
  ; indicated by comments.
  ; (defevaluator evl2 evl2-list ((f x) (f2 x) (g) (g2)))

  (ENCAPSULATE
    (((EVL2 * *) => *)
     ((EVL2-LIST * *) => *))
    (SET-INHIBIT-WARNINGS \"theory\")
    (LOCAL (IN-THEORY *DEFEVALUATOR-FORM-BASE-THEORY*))
    (LOCAL
     (MUTUAL-RECURSION (DEFUN EVL2 (X A)
                         (DECLARE (XARGS :VERIFY-GUARDS NIL
                                         :MEASURE (ACL2-COUNT X)
                                         :WELL-FOUNDED-RELATION O<
                                         :MODE :LOGIC))
                         (COND ((SYMBOLP X) (CDR (ASSOC-EQ X A)))
                               ((ATOM X) NIL)
                               ((EQ (CAR X) 'QUOTE) (CAR (CDR X)))
                               ((CONSP (CAR X))
                                (EVL2 (CAR (CDR (CDR (CAR X))))
                                      (PAIRLIS$ (CAR (CDR (CAR X)))
                                                (EVL2-LIST (CDR X) A))))
                               ((EQUAL (CAR X) 'F) ; changed f to f2 just below
                                (F2 (EVL2 (CAR (CDR X)) A)))
                               ((EQUAL (CAR X) 'F2)
                                (F2 (EVL2 (CAR (CDR X)) A)))
                               ((EQUAL (CAR X) 'G) (G))
                               ((EQUAL (CAR X) 'G2) (G2))
                               (T NIL)))
                       (DEFUN EVL2-LIST (X-LST A)
                         (DECLARE (XARGS :MEASURE (ACL2-COUNT X-LST)
                                         :WELL-FOUNDED-RELATION O<))
                         (COND ((ENDP X-LST) NIL)
                               (T (CONS (EVL2 (CAR X-LST) A)
                                        (EVL2-LIST (CDR X-LST) A)))))))

    (DEFTHM EVL2-CONSTRAINT-1
      (IMPLIES (SYMBOLP X)
               (EQUAL (EVL2 X A)
                      (CDR (ASSOC-EQ X A)))))
    (DEFTHM EVL2-CONSTRAINT-2
      (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'QUOTE))
               (EQUAL (EVL2 X A) (CADR X))))
    (DEFTHM EVL2-CONSTRAINT-3
      (IMPLIES (AND (CONSP X) (CONSP (CAR X)))
               (EQUAL (EVL2 X A)
                      (EVL2 (CADDAR X)
                            (PAIRLIS$ (CADAR X)
                                      (EVL2-LIST (CDR X) A))))))
    (DEFTHM EVL2-CONSTRAINT-4
      (IMPLIES (NOT (CONSP X-LST))
               (EQUAL (EVL2-LIST X-LST A) NIL)))
    (DEFTHM EVL2-CONSTRAINT-5
      (IMPLIES (CONSP X-LST)
               (EQUAL (EVL2-LIST X-LST A)
                      (CONS (EVL2 (CAR X-LST) A)
                            (EVL2-LIST (CDR X-LST) A)))))
    (DEFTHM EVL2-CONSTRAINT-6
      (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'F))
               (EQUAL (EVL2 X A) ; changed f to f2 just below
                      (F2 (EVL2 (CADR X) A)))))
    (DEFTHM EVL2-CONSTRAINT-7
      (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'F2))
               (EQUAL (EVL2 X A)
                      (F2 (EVL2 (CADR X) A)))))
    (DEFTHM EVL2-CONSTRAINT-8
      (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'G))
               (EQUAL (EVL2 X A) (G))))
    (DEFTHM EVL2-CONSTRAINT-9
      (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'G2))
               (EQUAL (EVL2 X A) (G2)))))

  (defthm f2-t
     (equal (f2 x) t)
     :hints ((\"Goal\" :by (:functional-instance
                          f-t
                          (f f2)
                          (evl evl2)
                          (evl-list evl2-list)))))

  (defthm bug-implies-nil
     nil
     :hints ((\"Goal\" :use ((:instance f2-t (x t)))))
     :rule-classes nil)
 })

 <p>Finally, we also require that no function has an attachment (see @(see
 defattach)) that is both ancestral in the evaluator and also ancestral in the
 meta or clause-processor functions.  (If you don't use @(tsee defattach) then
 you can ignore this condition.)  Without this restriction, the following
 events prove @('nil').</p>

 @({
  (in-package \"ACL2\")
  (defstub f () t)
  (defevaluator evl evl-list
    ((f)))
  (defun my-meta-fn (x)
    (if (equal x '(f))
        (list 'quote (f))
      x))
  (defthm my-meta-fn-correct
    (equal (evl x a)
           (evl (my-meta-fn x) a))
    :rule-classes ((:meta :trigger-fns (f))))
  (defun constant-nil ()
    (declare (xargs :guard t))
    nil)
  (defattach f constant-nil)
  (defthm f-is-nil
  ; proved using my-meta-fn-correct
    (equal (f) nil)
    :rule-classes nil)
  (defthm contradiction
    nil
    :hints ((\"Goal\" :use ((:functional-instance
                           f-is-nil
                           (f (lambda () t))))))
    :rule-classes nil)
 })

 <p>To see why this restriction is sufficient, see a comment in the ACL2 source
 code entitled ``; Essay on Correctness of Meta Reasoning.''</p>")

(defxdoc evenp
  :parents (numbers acl2-built-ins)
  :short "Test whether an integer is even"
  :long "<p>@('(evenp x)') is true if and only if the integer @('x') is even.
 Actually, in the ACL2 logic @('(evenp x)') is defined to be true when @('x/2')
 is an integer.</p>

 <p>The @(see guard) for @('evenp') requires its argument to be an integer.</p>

 <p>@('Evenp') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def evenp)")

(defxdoc events
  :parents (acl2)
  :short "Functions that extend the logic"
  :long "<p>Any extension of the syntax of ACL2 (i.e., the definition of a new
 constant or macro), the axioms (i.e., the definition of a function), or the
 rule database (i.e., the proof of a theorem), constitutes a logical ``event.''
 Events change the ACL2 logical world (see @(see world)).  Indeed, the only way
 to change the ACL2 @(see world) is via the successful evaluation of an event
 function.  Every time the @(see world) is changed by an event, a landmark is
 left on the @(see world) and it is thus possible to identify the @(see world)
 ``as of'' the evaluation of a given event.  An event may introduce new logical
 names.  Some events introduce no new names (e.g., @(tsee verify-guards)), some
 introduce exactly one (e.g., @(tsee defmacro) and @(tsee defthm)), and some
 may introduce many (e.g., @(tsee encapsulate) ).</p>

 <p>ACL2 typically completes processing of an event by printing a summary.
 Unless proofs are skipped (see @(see ld-skip-proofsp)) or summary output is
 inhibited (see @(see set-inhibit-output-lst)), information about the proof
 attempt (if any) is printed that includes a list of rules used, a summary of
 warnings, and the number of ``prover steps'' (if any; see @(see
 with-prover-step-limit)).  A breakdown of the time used is also printed, which
 by default is runtime (cpu time), but can be changed to realtime (wall clock
 time); see @(see get-internal-time).</p>

 <p>See @(see embedded-event-form) for a discussion of events permitted in
 @(see books).</p>")

(defxdoc evisc-table
  :parents (events)
  :short "Support for abbreviated output"
  :long "<p>The @('evisc-table') is an ACL2 table (see @(see table)) whose
 purpose is to modify the print representations of specified non-@('nil')
 objects.  When a key (some object) is associated with a string value, then
 that string is printed instead of that key (as an abbreviation).  For example,
 the following log shows how to abbreviate the key @('(a b c)') with the token
 @('<my-abc-list>').</p>

 @({
  ACL2 !>(table evisc-table '(a b c) \"<my-abc-list>\")

  Summary
  Form:  ( TABLE EVISC-TABLE ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   EVISC-TABLE
  ACL2 !>'(a b c)
  <my-abc-list>
  ACL2 !>'(4 5 a b c)
  (4 5 . <my-abc-list>)
  ACL2 !>
 })

 <p>Every value in this @(see table) must be either a string or @('nil'), where
 @('nil') eliminates any association of the key with an abbreviation.
 Continuing with the log above:</p>

 @({
  ACL2 !>(table evisc-table '(a b c) nil)

  Summary
  Form:  ( TABLE EVISC-TABLE ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   EVISC-TABLE
  ACL2 !>'(a b c)
  (A B C)
  ACL2 !>'(4 5 a b c)
  (4 5 A B C)
  ACL2 !>
 })

 <p>It can be particularly helpful to use this table to abbreviate a constant
 introduced by @(tsee defconst) by prefixing the constant name with
 @('\"#,\"'), as we now describe.  Consider first the following example.</p>

 @({
  (defconst *abc* '(1 2 3 4 5 6 7 8))
  (table evisc-table *abc*
    (concatenate 'string \"#,\" (symbol-name '*abc*)))
 })

 <p>Then the constant @('*abc*') is printed as follows &mdash; very helpful if
 its associated structure is significantly larger than the 8-element list of
 numbers shown above!</p>

 @({
  ACL2 !>*abc*
  #,*ABC*
  ACL2 !>
 })

 <p>What's more, the ACL2 reader will replace @('#,*C*'), where @('*C*') is
 defined by @(tsee defconst), by its value, regardless of @('evisc-table'); see
 @(see sharp-dot-reader).  Continuing with the example above, we have:</p>

 @({
  ACL2 !>(cdr (quote #,*ABC*))
  (2 3 4 5 6 7 8)
  ACL2 !>
 })

 <p>Of course, more care needs to be taken if packages are involved (see @(see
 defpkg)), as we now illustrate.</p>

 @({
  ACL2 !>(defpkg \"FOO\" nil)

  Summary
  Form:  ( DEFPKG \"FOO\" ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   \"FOO\"
  ACL2 !>(defconst foo::*a* '(1 2 3))

  Summary
  Form:  ( DEFCONST FOO::*A* ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FOO::*A*
  ACL2 !>(table evisc-table foo::*a* \"#,foo::*a*\")

  Summary
  Form:  ( TABLE EVISC-TABLE ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   EVISC-TABLE
  ACL2 !>foo::*a*
  #,foo::*a*
  ACL2 !>'#,foo::*a*
  #,foo::*a*
  ACL2 !>(cdr '#,foo::*a*)
  (2 3)
  ACL2 !>
 })

 <p>We conclude by an example showing some extra care that may be important to
 consider taking.  We start with:</p>

 @({
  (defconst |*BaR*| '(3 4))
 })

 <p>Then the following works just fine; but try it without the extra code for
 the @('may-need-slashes') case and you'll see that the sharp-dot printing is
 missing.  First:</p>

 @({
  (table evisc-table
         |*BaR*|
         (let ((x (symbol-name '|*BaR*|)))
           (if (may-need-slashes x)
               (concatenate 'string \"#.|\" x \"|\")
             (concatenate 'string \"#.\" x))))
 })

 <p>Then:</p>

 @({
  ACL2 !>|*BaR*|
  #,|*BaR*|
  ACL2 !>
 })")

(defxdoc evisc-tuple
  :parents (io)
  :short "Control suppression of details when printing"
  :long "<p>ACL2 output is generally printed in full.  However, ACL2 can be
 directed to abbreviate, or ``eviscerate'', objects before printing them.  To
 ``eviscerate'' an object we replace certain substructures within it by strings
 that are printed in their stead.  Such replacement is made relative to a
 so-called ``evisc-tuple'', which has four components: @('(evisc-tuple
 print-level print-length alist hiding-cars)') is the same as the value of
 @('(list alist print-level print-length hiding-cars)'), and the components are
 used as follows (with priority order as discussed below).  The @('alist')
 component is used to replace any substructure occurring as a key by the
 corresponding string.  The @('print-level') and @('print-length') are
 analogous to Common Lisp variables @('*print-level*') and @('*print-length*'),
 respectively, and cause replacement of substructures deeper than
 @('print-level') by `@('#')' and those longer than @('print-length') by
 `@('...')'.  Finally, any @(tsee consp) @('x') that starts with one of the
 symbols in @('hiding-cars') is printed as @('<hidden>').</p>

 <p>The following example illustrates the use of an evisc-tuple that limits the
 print-level to 3 &mdash; only three descents into list structures are
 permitted before replacing a subexpression by `@('#')' &mdash; and limits the
 print-length to 4 &mdash; only the first four elements of any list structure
 will be printed before replacing its tail by `@('...')'.</p>

 @({
  ACL2 !>(fms \"~x0~%\"
              (list (cons #\\0 '((a b ((c d)) e f g) u v w x y)))
              *standard-co*
              state
              (evisc-tuple 3 4 nil nil))

  ((A B (#) E ...) U V W ...)
  <state>
  ACL2 !>
 })

 <p>Notice that it is impossible to read the printed value back into ACL2,
 since there is no way for the ACL2 reader to interpret `@('#')' or `@('...')'.
 To solve this problem, see @(see set-iprint).</p>

 <p>In the above example we pass an evisc-tuple explicitly to a printing
 function, in this case, @(tsee fms) (see @(see fmt)).  But ACL2 also does its
 own printing, for example during a proof attempt.  There are global
 evisc-tuples that control ACL2's printing; see @(see set-evisc-tuple) and see
 @(see without-evisc).</p>")

(defxdoc eviscerate-hide-terms
  :parents (io)
  :short "To print @('(hide ...)') as @('<hidden>')"
  :long "@({
  Example:
  (assign eviscerate-hide-terms t)
  (assign eviscerate-hide-terms nil)
 })

 <p>@('Eviscerate-hide-terms') is a @(tsee state) global variable whose value
 is either @('t') or @('nil').  The variable affects how terms are displayed by
 default (but not if you have set the term-evisc-tuple to other than its
 default; see @(see set-evisc-tuple)).  If @('t'), terms of the form @('(hide
 ...)')  are printed as @('<hidden>').  Otherwise, they are printed
 normally.</p>")

(defxdoc example-induction-scheme-binary-trees
  :parents (introduction-to-the-theorem-prover)
  :short "Induction on binary trees"
  :long "<p>See @(see logic-knowledge-taken-for-granted-inductive-proof) for an
 explanation of what we mean by the induction <i>suggested</i> by a recursive
 function or a term.</p>

 <p><b>Classical Induction on Binary Trees</b>: To prove @('(p x)'), for all
 @('x'), by classical induction on binary tree structures, prove each of the
 following:</p>

 <code>
 <i>Base Case</i>:
 (implies (atom x) (p x))
 </code>

 <code>
 <i>Induction Step</i>:
 (implies (and (not (atom x))
               (p (car x))
               (p (cdr x)))
          (p x))
 </code>

 <p>An argument analogous to that given in @(see
 example-induction-scheme-on-lists) should convince you that @('(p x)') holds
 for every object.</p>

 <p>A function that suggests this induction is:</p>

 @({
  (defun flatten (x)
    (if (atom x)
        (list x)
        (app (flatten (car x))
             (flatten (cdr x))))).
 })")

(defxdoc example-induction-scheme-down-by-2
  :parents (introduction-to-the-theorem-prover)
  :short "Induction downwards 2 steps at a time"
  :long "<p>See @(see logic-knowledge-taken-for-granted-inductive-proof) for an
 explanation of what we mean by the induction <i>suggested</i> by a recursive
 function or a term.</p>

 <p><b>Classical Induction on Natural Numbers Preserving Parity</b>: Here is
 another way to decompose natural numbers.  To prove @('(p n)'), for all
 @('n'), prove each of the following:</p>

 <code>
 <i>Base Case 1</i>:
 (implies (zp n) (p n))
 </code>

 <code>
 <i>Base Case 2</i>:
 (implies (equal n 1) (p n))
 </code>

 <code>
 <i>Induction Step</i>:
 (implies (and (not (zp n))
               (not (equal n 1))
               (p (- n 2)))
          (p n))
 </code>

 <p>Base Case 1 establishes that @('p') holds for @('0') (and all objects other
 than positive naturals).</p>

 <p>Base Case 2 establishes that @('p') holds for @('1').</p>

 <p>The Induction Step establishes that if @('n') is a natural number greater
 than @('1'), and if @('p') holds for @('n')-2, then @('p') holds for
 @('n').</p>

 <p>Note that we have thus proved that @('(p n)') holds, for all @('n').  For
 example, @('(p -7)'), @('(p 'abc)'), and @('(p 0)') are all established by
 Base Case 1.  @('(p 1)') is established by Base Case 2.  @('(p 2)') is
 established from @('(p 0)') and the Induction Step.  Think about it!  @('(p
 3)') is established form @('(p 1)') and the Induction Step, etc.</p>

 <p>A function that suggests this induction is:</p>

 @({
  (defun parity (n)
    (if (zp n)
        'even
        (if (equal n 1)
            'odd
            (parity (- n 2))))).
 })")

(defxdoc example-induction-scheme-nat-recursion
  :parents (introduction-to-the-theorem-prover)
  :short "Induction on natural numbers"
  :long "<p>See @(see logic-knowledge-taken-for-granted-inductive-proof) for an
 explanation of what we mean by the induction <i>suggested</i> by a recursive
 function or a term.</p>

 <p><b>Classical Induction on Natural Numbers</b>: Induction is familiar in the
 arithmetic setting.  To prove @('(p n)'), for all @('n'), by classical
 induction on the construction of the natural numbers, prove each of the
 following:</p>

 <code>
 <i>Base Case</i>:
 (implies (zp n) (p n))
 </code>

 <code>
 <i>Induction Step</i>:
 (implies (and (not (zp n))
               (p (- n 1)))
          (p n))
 </code>

 <p>The Base Case establishes that @('p') holds for @('0').  In fact, because
 of the definition of @(tsee zp) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>, it
 establishes that @('(p n)') holds when @('n') is @('0') and it holds when
 @('n') is not a natural number.</p>

 <p>The Induction Step establishes that if @('n') is a natural number other
 than @('0'), and if @('p') holds for @('n')-1, then @('p') holds for @('n').
 The hypothesis @('(p (- n 1))') above is called the <i>induction
 hypothesis</i>.</p>

 <p>A function that suggests this induction is</p>

 @({
  (defun nat-recursion (n)
    (if (zp n)
        n
        (nat-recursion (- n 1))))
 })

 <p>Similarly, the term @('(fact n)') suggests this induction if @('fact') is
 defined:</p>

 @({
   (defun fact (k)
    (if (zp k)
        1
        (* k (fact (- k 1))))).
 })

 <p>even though the formal parameter of this definition of @('fact') is @('k'),
 not @('n').</p>")

(defxdoc example-induction-scheme-on-lists
  :parents (introduction-to-the-theorem-prover)
  :short "Induction on lists"
  :long "<p>See @(see logic-knowledge-taken-for-granted-inductive-proof) for an
 explanation of what we mean by the induction <i>suggested</i> by a recursive
 function or a term.</p>

 <p><b>Classical Induction on Lists</b>: To prove @('(p x)'), for all @('x'),
 by classical induction on the linear list structure, prove each of the
 following:</p>

 <code>
 <i>Base Case</i>:
 (implies (endp x) (p x))
 </code>

 <code>
 <i>Induction Step</i>:
 (implies (and (not (endp x))
               (p (cdr x)))
          (p x))
 </code>

 <p>An argument analogous to that given for natural numbers, @(see
 example-induction-scheme-nat-recursion), establishes @('(p x)') for every
 @('x').  For example, @('(p -7)'), @('(p 'abc)'), and @('(p nil)') are all
 established by the Base Case.  @('(p '(Friday))') follows from @('(p nil)'),
 given the Induction Step.  That sentence bears thinking about!  Think about
 it!  Similarly, @('(p '(Yellow))') holds for the same reason.  @('(p
 '(Thursday Friday))') follows from @('(p '(Friday))') and the Induction Step,
 etc.</p>

 <p>A function that suggests this induction is</p>

 @({
  (defun app (x y)
    (if (endp x)
        y
        (cons (car x)
              (app (cdr x) y)))).
 })")

(defxdoc example-induction-scheme-on-several-variables
  :parents (introduction-to-the-theorem-prover)
  :short "Induction on several variables"
  :long "<p>See @(see logic-knowledge-taken-for-granted-inductive-proof) for an
 explanation of what we mean by the induction <i>suggested</i> by a recursive
 function or a term.</p>

 <p><b>Induction on Several Variables</b> To @('(p n x)') for all @('n') and
 all @('x'), prove each of the following:</p>

 <code>
 <i>Base Case 1</i>:
 (implies (endp x)
          (p n x))
 </code>

 <code>
 <i>Base Case 2</i>:
 (implies (and (not (endp x))
               (zp n))
          (p n x))
 </code>

 <code>
 <i>Induction Step</i>:
 (implies (and (not (endp x))
               (not (zp n))
               (p (- n 1) (cdr x)))
          (p n x))
 </code>

 <p>A function that suggests this induction is</p>

 @({
  (defun nth (n x)
    (if (endp x)
        nil
        (if (zp n)
            (car x)
            (nth (- n 1) (cdr x))))).
 })")

(defxdoc example-induction-scheme-upwards
  :parents (introduction-to-the-theorem-prover)
  :short "Induction upwards"
  :long "<p>See @(see logic-knowledge-taken-for-granted-inductive-proof) for an
 explanation of what we mean by the induction <i>suggested</i> by a recursive
 function or a term.</p>

 <p><b>Induction Upwards</b>: To @('(p i max)') for all @('i') and all
 @('max'), prove each of the following:</p>

 <code>
 <i>Base Case</i>:
 (implies (not (and (natp i)
                    (natp max)
                    (&lt; i max)))
          (p i max))
 </code>

 <code>
 <i>Induction Step</i>:
 (implies (and  (natp i)
                (natp max)
                (&lt; i max)
                (p (+ i 1) max))
          (p i max))
 </code>

 <p>Note that the induction hypothesis is about an @('i') that is <i>bigger</i>
 than the @('i') in in the conclusion.  In induction, as in recursion, the
 sense of one thing being ``smaller'' than another is determined by an
 arbitrary measure of all the variables, not the magnitude or extent of some
 particular variable.</p>

 <p>A function that suggests this induction is shown below.  ACL2 has to be
 told the measure, namely the difference between @('max') and @('i') (coerced
 to a natural number to insure that the measure is an ordinal).</p>

 @({
  (defun count-up (i max)
    (declare (xargs :measure (nfix (- max i))))
    (if (and (natp i)
             (natp max)
             (< i max))
        (cons i (count-up (+ 1 i) max))
        nil)).
 })")

(defxdoc example-induction-scheme-with-accumulators
  :parents (introduction-to-the-theorem-prover)
  :short "Induction scheme with accumulators"
  :long "<p>See @(see logic-knowledge-taken-for-granted-inductive-proof) for an
 explanation of what we mean by the induction <i>suggested</i> by a recursive
 function or a term.</p>

 <p>To prove @('(p x a)') for all @('x') and all @('a'), prove each of the
 following:</p>

 <code>
 <i>Base Case</i>:
 (implies (endp x)
          (p x a))
 </code>

 <code>
 <i>Induction Step</i>:
 (implies (and (not (endp x))
               (p (cdr x) (cons (car x) a)))
          (p x a))
 </code>

 <p>Note that in the induction hypothesis we assume @('p') for a smaller @('x')
 but a larger @('a').  In fact, we could include as many induction hypotheses
 as we want and use any terms we want in the @('a') position as long as the
 @('x') position is occupied by a smaller term.</p>

 <p>A function that suggests this particular induction is shown below.</p>

 @({
  (defun rev1 (x a)
    (if (endp x)
        a
        (rev1 (cdr x) (cons (car x) a)))).
 })

 <p>A function that suggests a similar induction in which three induction
 hypotheses are provided, one in which the @('a') position is occupied by
 @('(cons (car x) a)'), another in which the @('a') position is occupied by
 some arbitrary term @('b'), and a third in which the @('a') position is
 occupied by @('a'), is suggested by the term @('(rev1-modified x a b)')
 where</p>

 @({
  (defun rev1-modified (x a b)
    (if (endp x)
        (list x a b)
        (list (rev1-modified (cdr x) (cons (car x) a) b)
              (rev1-modified (cdr x) b b)
              (rev1-modified (cdr x) a b))))
 })

 <p>Remember that the value of this term or function is irrelevant to the
 induction suggested.  Because ACL2's definitional principle insists that all
 the formal parameters play a role in the computation (at least syntactically),
 it is common practice when defining functions for their induction schemes to
 return the @('list') of all the formals (to insure all variables are involved)
 and to combine recursive calls on a given branch with @('list') (to avoid
 introducing additional case analysis as would happen if @('and') or @('or') or
 other propositional functions are used).</p>

 <p>If you tried to prove @('(p x a)') and suggested the induct hint
 @('(rev1-modified x a (fact k))'), as by</p>

 @({
  (thm (p x a)
       :hints ((\"Goal\" :induct (rev1-modified x a (fact k)))))
 })

 <p>the inductive argument would be:</p>

 <code>
 <i>Base Case</i>:
 (implies (endp x)
          (p x a))
 </code>

 <code>
  <i>Inductive Step</i>:
  (implies (and (not (endp x))
                (p (cdr x) (cons (car x) a))
                (p (cdr x) (fact k))
                (p (cdr x) a))
           (p x a))
  </code>")

(defxdoc example-induction-scheme-with-multiple-induction-steps
  :parents (introduction-to-the-theorem-prover)
  :short "Induction scheme with more than one induction step"
  :long "<p>See @(see logic-knowledge-taken-for-granted-inductive-proof) for an
 explanation of what we mean by the induction <i>suggested</i> by a recursive
 function or a term.</p>

 <p><b>Several Induction Steps</b>: To @('(p x i a)') for all @('x'), @('i'),
 and @('a'), prove each of the following:</p>

 <code>
 <i>Base Case 1</i>:
 (implies (zp i)
          (p x i a))
 </code>

 <code>
 <i>Induction Step 1</i>:
 (implies (and (not (zp i))
               (equal (parity i) 'even)
               (p (* x x)
                  (floor i 2)
                  a))
          (p x i a))
 </code>

 <code>
 <i>Induction Step 2</i>:
 (implies (and (not (zp i))
               (not (equal (parity i) 'even))
               (p x
                  (- i 1)
                  (* x a)))
          (p x i a))
 </code>

 <p>A function that suggests this induction is the binary exponentiation
 function for natural numbers.</p>

 @({
  (defun bexpt (x i a)
    (cond ((zp i) a)
          ((equal (parity i) 'even)
           (bexpt (* x x)
                  (floor i 2)
                  a))
          (t (bexpt x
                    (- i 1)
                    (* x a)
                    )))).
 })

 <p>In order to admit this function it is necessary to know that @('(floor i
 2)') is smaller than @('i') in the case above.  This can be proved if the
 community book @('\"arithmetic-5/top\"') has been included from the ACL2
 system directory, i.e.,</p>

 @({
  (include-book \"arithmetic-5/top\" :dir :system)
 })

 <p>should be executed before defining @('bexpt').</p>")

(defxdoc example-inductions
  :parents (introduction-to-the-theorem-prover)
  :short "Some examples of induction schemes in ACL2"
  :long "<p>Here are some pages illustrating various induction schemes
 suggested by recursive functions.</p>

 <p><b>Classical Induction on Natural Numbers</b>: see @(see
 example-induction-scheme-nat-recursion).</p>

 <p><b>Induction Preserving Even/Odd Parity</b> or<br></br>

 <b>Induction Downwards by 2</b> or <br></br>

 <b>Induction with Multiple Base Cases</b>: see @(see
 example-induction-scheme-down-by-2) for an induction in which the induction
 hypothesis decreases the induction variable by an amount other than 1.  This
 illustrates that the induction hypothesis can be about whatever term or terms
 are needed to explain how the formula recurs.  The example also illustrates an
 induction with more than one Base Case.</p>

 <p><b>Classical Induction on Lists</b>: see @(see
 example-induction-scheme-on-lists) for an induction over linear lists, in
 which we inductively assume the conjecture for @('(cdr x)') and prove it for
 @('x').  It doesn't matter whether the list is @('nil')-terminated or not; the
 Base Case addresses all the possibilities.</p>

 <p><b>Classical Induction on Binary (Cons) Trees</b>: see @(see
 example-induction-scheme-binary-trees) for an induction over the simplest form
 of binary tree.  Here the Induction Step provides two hypotheses, one about
 the left subtree and one about the right subtree.</p>

 <p><b>Induction on Several Variables</b>: see @(see
 example-induction-scheme-on-several-variables) for an induction in which
 several variables participate in the case analysis and induction
 hypotheses.</p>

 <p><b>Induction Upwards</b>: see @(see example-induction-scheme-upwards) for
 an induction scheme in which the induction hypothesis is about something
 ``bigger than'' the induction conclusion.  This illustrates that the sense in
 which the hypothesis is about something ``smaller'' than the conclusion is
 determined by a measure of all the variables, not the magnitude or extent of
 some single variable.</p>

 <p><b>Induction with Auxiliary Variables</b> or<br></br>

 <b>Induction with Accumulators</b>: see @(see
 example-induction-scheme-with-accumulators) for an induction scheme in which
 one variable ``gets smaller'' but another is completely arbitrary.  Such
 schemes are common when dealing with tail-recursive functions that accumulate
 partial results in auxiliary variables.  This example also shows how to
 provide several arbitrary terms in a non-inductive variable of a scheme.</p>

 <p><b>Induction with Multiple Induction Steps</b>: see @(see
 example-induction-scheme-with-multiple-induction-steps) for an induction in
 which we make different inductive hypotheses depending on which case we're in.
 This example also illustrates the handling of auxiliary variables or
 accumulators.</p>")

(defxdoc executable-counterpart
  :parents (rule-classes)
  :short "A rule for computing the value of a function"
  :long "<p>This topic is about a type of @(see rune) that controls evaluation
 using the executable-counterpart of a function.  For discussion of
 executable-counterparts of functions, see @(see evaluation).</p>

 @({
  Examples:
  (:executable-counterpart length)
 })

 <p>which may be abbreviated in @(see theories) as</p>

 @({
  (length)
 })

 <p>Every @(tsee defun) introduces at least two rules used by the theorem
 prover.  Suppose @('fn') is the name of a @(tsee defun)'d function.  Then
 @('(:definition fn)') is the rune (see @(see rune)) naming the rule that
 allows the simplifier to replace calls of @('fn') by its instantiated body.
 @('(:executable-counterpart fn)') is the @(see rune) for the rule for how to
 evaluate the function on known constants.</p>

 <p>When typing @(see theories) it is convenient to know that @('(fn)') is a
 runic designator that denotes @('(:executable-counterpart fn)').  See @(see
 theories).</p>

 <p>If @('(:executable-counterpart fn)') is @(see enable)d, then when
 applications of @('fn') to known constants are seen by the simplifier they are
 computed out by executing the Common Lisp code for @('fn') (with the
 appropriate handling of @(see guard)s).  Suppose @('fact') is defined as the
 factorial function.  If the executable-counterpart @(see rune) of @('fact'),
 @('(:executable-counterpart fact)'), is @(see enable)d when the simplifier
 encounters @('(fact 12)'), then that term will be ``immediately'' expanded to
 @('479001600').  Note that even if subroutines of @('fn') have disabled
 executable-counterparts, @('fn') will call their Lisp code nonetheless: once
 an executable-counterpart function is applied, no subsidiary enable checks are
 made.</p>

 <p>Such one-step expansions are sometimes counterproductive because they
 prevent the anticipated application of certain lemmas about the subroutines of
 the expanded function.  Such computed expansions can be prevented by disabling
 the executable-counterpart @(see rune) of the relevant function.  For example,
 if @('(:executable-counterpart fact)') is @(see disable)d, @('(fact 12)') will
 not be expanded by computation.  In this situation, @('(fact 12)') may be
 rewritten to @('(* 12 (fact 11))'), using the rule named @('(:definition
 fact)'), provided the system's heuristics permit the introduction of the term
 @('(fact 11)').  Note that lemmas about multiplication may then be applicable
 (while such lemmas would be inapplicable to @('479001600')).  In many proofs
 it is desirable to @(see disable) the executable-counterpart @(see rune)s of
 certain functions to prevent their expansion by computation.  See @(see
 executable-counterpart-theory).</p>

 <p>Finally: What do we do about functions that are ``constrained'' rather than
 defined, such as the following?  (See @(see encapsulate).)</p>

 @({
  (encapsulate (((foo *) => *))
               (local (defun foo (x) x)))
 })

 <p>Does @('foo') have an executable-counterpart?  Yes: since the vast majority
 of functions have sensible executable-counterparts, it was decided that
 <b>all</b> functions, even such ``constrained'' ones, have
 executable-counterparts.  We essentially ``trap'' when such calls are
 inappropriate.  Thus, consider for example:</p>

 @({
  (defun bar (x)
    (if (rationalp x)
        (+ x 1)
      (foo x)))
 })

 <p>If the term @('(bar '3)') is encountered by the ACL2 rewriter during a
 proof, and if the @(':executable-counterpart') of @('bar') is @(see enable)d,
 then it will be invoked to reduce this term to @(''4').  However, if the term
 @('(bar 'a)') is encountered during a proof, then since @(''a') is not a
 @(tsee rationalp) and since the @(':executable-counterpart') of @('foo') is
 only a ``trap,'' then this call of the @(':executable-counterpart') of
 @('bar') will result in a ``trap.'' In that case, the rewriter will return the
 term @('(hide (bar 'a))') so that it never has to go through this process
 again.  See @(see hide).</p>")

(defxdoc executable-counterpart-theory
  :parents (theories theory-functions)
  :short "@(csee Executable-counterpart) rules as of logical name"
  :long "@({
  Examples:
  (executable-counterpart-theory :here)
  (executable-counterpart-theory 'lemma3)
 })

 <p>See @(see logical-name).</p>

 @({
  General Form:
  (executable-counterpart-theory logical-name)
 })

 <p>Returns the theory containing all the @(':')@(tsee executable-counterpart)
 @(see rune)s, whether @(see enable)d or not, that existed immediately after
 @(tsee logical-name) was introduced.  See the documentation for @(see
 theories), @(see logical-name), @(see executable-counterpart) and @(tsee
 function-theory).</p>

 <p>You may experience a fencepost problem in deciding which logical name to
 use.  @(tsee Deflabel) can always be used to mark unambiguously for future
 reference a particular point in the development of your theory.  The order of
 @(see events) in the vicinity of an @(tsee encapsulate) is confusing.  See
 @(see encapsulate).</p>

 <p>This ``function'' is actually a macro that expands to a term mentioning the
 single free variable @(tsee world).  When theory expressions are evaluated by
 @(tsee in-theory) or the @(':')@(tsee in-theory) hint, @(tsee world) is bound
 to the current ACL2 @(see world).</p>")

(defxdoc exists
  :parents (defun-sk)
  :short "Existential quantifier"
  :long "<p>The symbol @('exists') (in the ACL2 package) represents existential
 quantification in the context of a @(tsee defun-sk) form.  See @(see defun-sk)
 and see @(see forall).</p>

 <p>See @(see quantifiers) for an example illustrating how the use of
 recursion, rather than explicit quantification with @(tsee defun-sk), may be
 preferable.</p>")

(defxdoc exit
  :parents (good-bye)
  :short "Quit entirely out of Lisp"
  :long "<p>Same as @(tsee good-bye).</p>")

(defxdoc exit-boot-strap-mode
  :parents (history)
  :short "The end of pre-history"
  :long "<p>@('Exit-boot-strap-mode') is the last step in creating the ACL2
 @(see world) in which the user lives.  It has @(see command) number @('0').
 @(see Command)s before it are part of the system initialization and extend all
 the way back to @(':')@(tsee min).  @(see Command)s after it are those of the
 user.</p>

 <p>@('Exit-boot-strap-mode') is a Common Lisp function but not an ACL2
 function.  It is called when every @(tsee defconst), @(tsee defun), etc., in
 our source code has been processed under ACL2 and the @(see world) is all but
 complete.  @('exit-boot-strap-mode') has only one job: to signal the
 completion of the boot-strapping.</p>")

(defxdoc explode-atom
  :parents (characters acl2-built-ins)
  :short "Convert any @(see atom) into a @(see character-listp) that contains
 its printed representation, rendering numbers in your choice of print base."

  :long "<p>@(call explode-atom) prints the atom @('x') as a list of
 characters, using some @(see print-base-p) to decide what base to print
 numbers in.</p>

 <p>Examples:</p>

 @({
 (explode-atom 15 10) --> (#\\1 #\\5)              ; 15 in decimal
 (explode-atom 15 16) --> (#\\F)                  ; 15 in hex
 (explode-atom \"foo\" 10) --> (#\\f #\\o #\\o)
 (explode-atom 'acl2::foo 10) --> (#\\F #\\O #\\O)  ; note: no package
 })

 <p>See also @(see explode-nonnegative-integer), @(see str::numbers), and @(see
 printing-to-strings).</p>

 @(def explode-atom)")

(defxdoc explode-nonnegative-integer
  :parents (characters numbers acl2-built-ins)
  :short "The list of @(see characters) in the radix-r form of a number"
  :long "@({
  Examples:
  ACL2 !>(explode-nonnegative-integer 925 10 nil)
  (#9 #2 #5)
  ACL2 !>(explode-nonnegative-integer 325 16 nil)
  (#3 #9 #D)
 })

 <p>For a non-negative integer @('n'), @('(explode-nonnegative-integer n r
 nil)') is the list of @(see characters) in the radix-@('r') (base-@('r'))
 representation of @('n').</p>

 <p>The @(see guard) for @('explode-nonnegative-integer') requires the first
 argument to be a nonnegative integer and second argument to be a valid radix
 for ACL2 (2, 8, 10, or 16).</p>

 <p>See also @(see explode-atom), @(see str::numbers), and @(see
 printing-to-strings).</p>

 @(def explode-nonnegative-integer)")

(defxdoc expt
  :parents (numbers acl2-built-ins)
  :short "Exponential function"
  :long "<p>@('(Expt r i)') is the result of raising the number @('r') to the
 integer power @('i').</p>

 <p>The @(see guard) for @('(expt r i)') is that @('r') is a number and @('i')
 is an integer, and furthermore, if @('r') is @('0') then @('i') is
 nonnegative.  When the type requirements of the @(see guard) aren't met,
 @('(expt r i)') first coerces @('r') to a number and @('i') to an integer.</p>

 <p>@('Expt') is a Common Lisp function.  See any Common Lisp documentation for
 more information.  Note that @('r') can be a complex number; this is
 consistent with Common lisp.</p>

 @(def expt)")

(defxdoc extend-pe-table
  :parents (history)
  :short "Replace @(see events) displayed by @(see history) commands"
  :long "@({
 Example Form:
 (extend-pe-table all-natp (all-p natp))

 General Form:
 (extend-pe-table event-name form)
 })

 <p>where @('event-name') is the name of an existing event and @('form') is to
 be displayed by @(see history) commands in place of the actual event that
 introduced @('event-name').</p>

 <p>We motivate and illustrate this utility with the following example.
 Suppose you develop a macro to define the notion that each element of a list
 satisfies a given predicate, as follows.</p>

 @({
 (defmacro all-p (pred)
   (declare (xargs :guard (symbolp pred)))
   (let ((name (intern$ (concatenate 'string \"ALL-\" (symbol-name pred))
                        (symbol-package-name pred))))
     `(defun ,name (lst)
        (if (atom lst)
            t
          (and (,pred lst)
               (,name (cdr lst)))))))
 })

 <p>So for example, after evaluating @('(all-p natp)'), you see the
 following.</p>

 @({
 ACL2 !>:pe all-natp
  L         2:x(ALL-P NATP)
               \
 >L             (DEFUN ALL-NATP (LST)
                       (IF (ATOM LST)
                           T
                           (AND (NATP LST) (ALL-NATP (CDR LST)))))
 ACL2 !>
 })

 <p>So far so good.  But suppose that instead, you introduce this event within
 a call of @(tsee progn), as follows.</p>

 @({
 (progn (defun f1 (x) x)
        (defun f2 (x) x)
        (all-p natp))
 })

 <p>Then when we ask to see the event introducing @('all-natp'), we will not
 see any use of the macro @('all-p').</p>

 @({
 ACL2 !>:pe all-natp
            2:x(PROGN (DEFUN F1 # ...)
                      (DEFUN F2 # ...)
                      ...)
               \
 >L             (DEFUN ALL-NATP (LST)
                       (IF (ATOM LST)
                           T
                           (AND (NATP LST) (ALL-NATP (CDR LST)))))
 ACL2 !>
 })

 <p>Perhaps we therefore prefer that @(see history) commands display the event
 for @('all-natp') as @('(all-p natp)'), rather than as the generated @(tsee
 defun) event.  Of course, in this simple example that might not be important;
 but it is easy to imagine examples where a small macro invocation generates a
 large, ugly primitive event that is best not viewed by any user!</p>

 <p>A solution is to associate the name @('all-natp') with the form that
 introduced this name, as follows.</p>

 @({
 (extend-pe-table all-natp (all-p natp))
 })

 <p>After evaluating this form, we see the desired call of @('all-natp').  In
 essence, @(':')@(tsee pe) and other @(see history) commands consider the
 defining event for @('all-natp') to be @('(all-p natp)') rather than the
 actual @('defun') form that introduced @('all-natp').</p>

 @({
 ACL2 !>:pe all-natp
            2  (PROGN (DEFUN F1 # ...)
                      (DEFUN F2 # ...)
                      ...)
               \
 >L             (ALL-P NATP)
 ACL2 !>
 })

 <p>As mentioned above, other @(see history) commands are sensitive to the
 result of evaluating a call of @('extend-pe-table').  For example:</p>

 @({
 ACL2 !>:pcb all-natp
            2  (PROGN (DEFUN F1 # ...)
                      (DEFUN F2 # ...)
                      ...)
  L             (DEFUN F1 (X) ...)
  L             (DEFUN F2 (X) ...)
  L             (ALL-P NATP)
 ACL2 !>
 })

 <p>Note that @('extend-pe-table') actually associates the indicated form with
 the most recent event introducing the given event name.  Consider the
 following example (output elided as shown).</p>

 @({
 ACL2 !>(encapsulate
          ()
          (program)
          (all-p alistp))
 [[.. elided ..]]
  T
 ACL2 !>:pe all-alistp
            4:x(ENCAPSULATE NIL ...)
               \
 >P             (DEFUN ALL-ALISTP (LST)
                       (IF (ATOM LST)
                           T
                           (AND (ALISTP LST)
                                (ALL-ALISTP (CDR LST)))))
 ACL2 !>(extend-pe-table all-alistp (all-p alistp))

 Summary
 Form:  ( TABLE PE-TABLE ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  PE-TABLE
 ACL2 !>:pe all-alistp
            4  (ENCAPSULATE NIL ...)
               \
 >P             (ALL-P ALISTP)
 ACL2 !>(verify-termination all-alistp)
 [[.. elided ..]]
  ALL-ALISTP
 ACL2 !>:pe all-alistp
  L         6:x(VERIFY-TERMINATION ALL-ALISTP)
               \
 >L             (DEFUN ALL-ALISTP (LST)
                       (IF (ATOM LST)
                           T
                           (AND (ALISTP LST)
                                (ALL-ALISTP (CDR LST)))))

 Additional events for the logical name ALL-ALISTP:
            4  (ENCAPSULATE NIL ...)
               \
 >PL            (ALL-P ALISTP)
 ACL2 !>(extend-pe-table all-alistp (:termination-verified (all-p alistp)))

 Summary
 Form:  ( TABLE PE-TABLE ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  PE-TABLE
 ACL2 !>:pe all-alistp
  L         6  (VERIFY-TERMINATION ALL-ALISTP)
               \
 >L             (:TERMINATION-VERIFIED (ALL-P ALISTP))

 Additional events for the logical name ALL-ALISTP:
            4  (ENCAPSULATE NIL ...)
               \
 >PL            (ALL-P ALISTP)
 ACL2 !>
 })

 <p>Note that by using @(':')@(tsee pe!), in place of @(':')@(tsee pe), you can
 avoid using the information that was provided by @('extend-pe-table').</p>

 @({
 ACL2 !>:pe! all-alistp
  L         6  (VERIFY-TERMINATION ALL-ALISTP)
               \
 >L             (DEFUN ALL-ALISTP (LST)
                       (IF (ATOM LST)
                           T
                           (AND (ALISTP LST)
                                (ALL-ALISTP (CDR LST)))))

 Additional events for the logical name ALL-ALISTP:
            4  (ENCAPSULATE NIL ...)
               \
 >PL            (DEFUN ALL-ALISTP (LST)
                       (IF (ATOM LST)
                           T
                           (AND (ALISTP LST)
                                (ALL-ALISTP (CDR LST)))))
 ACL2 !>
 })

 <p>In the examples above we invoked @('extend-pe-table') explicitly.  It might
 have been better, however, to ``bake in'' such calls by way of the macro
 itself, as follows.</p>

 @({
 (defmacro all-p (&whole form pred)
   (declare (xargs :guard (symbolp pred)))
   (let ((name (intern$ (concatenate 'string \"ALL-\" (symbol-name pred))
                        (symbol-package-name pred))))
     `(progn (defun ,name (lst)
               (if (atom lst)
                   t
                 (and (,pred lst)
                      (,name (cdr lst)))))
             (extend-pe-table ,name ,form))))
 })

 <p>Then in a fresh session, after defining @('all-p') as shown immediately
 above, we can obtain the following (edited) log.</p>

 @({
 ACL2 !>(all-p natp)
 [[.. elided ..]]
 ACL2 !>:pe all-natp
            2:x(ALL-P NATP)
 ACL2 !>
 })

 <p>We close with two remarks.  First, note that the indicated event must have
 already been defined at the time @('extend-pe-table') is invoked.  Second
 &mdash; in case an advanced user wishes to extend directly the underlying
 table, @('pe-table') &mdash; we mention that this table associates each key,
 an event name, with an association list that maps so-called absolute event
 numbers with events to display.  So for example, we can remove all custom
 printing of events for the name @('all-natp') as follows.</p>

 @({
 (table pe-table 'all-natp nil)
 })

")

(defxdoc extend-world
  :parents (world)
  :short "Install an extension of a given ACL2 @(see world)"
  :long "<p>See @(see world) for relevant background on ACL2 property list
 worlds.  Here we discuss how to install an extension of a user-defined world,
 that is, a world other than the one named @(''current-acl2-world'), which is
 maintained by the ACL2 system.  Also see @(see retract-world) for a similar
 utility that instead installs an initial segment of a named world.</p>

 @({
 General Form:

 (extend-world name wrld)
 })

 <p>where @('name') is a symbol intended to name the given ACL2 property list
 world, @('world').  Consider the following example.</p>

 @({
 ACL2 !>(let* ((wrld0 nil)
               (wrld1 (putprop 'my-sym1 'my-key1 'my-val1-old wrld0))
               (wrld2 (putprop 'my-sym2 'my-key2 'my-val2 wrld1))
               (wrld3 (putprop 'my-sym1 'my-key1 'my-val1 wrld2)))
          (assign my-w (extend-world 'my-world wrld3)))
  ((MY-SYM1 MY-KEY1 . MY-VAL1)
   (MY-SYM2 MY-KEY2 . MY-VAL2)
   (MY-SYM1 MY-KEY1 . MY-VAL1-OLD))
 ACL2 !>(getprop 'my-sym1 'my-key1 nil 'my-world (@ my-w))
 MY-VAL1
 ACL2 !>
 })

 <p>The first top-level form sets the value of @(tsee state) global @('my-w')
 to the world obtained by extending the empty world three times, as shown.  The
 second top-level form returns the most recent @(''my-key1') property of the
 symbol @(''my-sym1').  This second computation is efficient, because
 @('extend-world') has <i>installed</i> the value of @('my-w') as the world
 that is current for the name @(''my-world').  See @(see world).</p>")

(defxdoc extended-metafunctions
  :parents (meta)
  :short "State and context sensitive metafunctions"
  :long "@({
  General Form of an Extended :Meta theorem:
  (implies (and (pseudo-termp x)              ; this hyp is optional
                (alistp a)                    ; this hyp is optional
                (ev (hyp-fn x mfc state) a)   ; this hyp is optional
                ; meta-extract hyps may also be included (see below)
                )
           (equiv (ev x a)
                  (ev (fn x mfc state) a)))
 })

 <p>where the restrictions are as described in the @(see documentation) for
 @(tsee meta) where @('state') is literally the symbol @('STATE'), and @('x'),
 @('a'), @('mfc'), and @('state') are distinct variable symbols.  A @(':meta')
 theorem of the above form installs @('fn') as a metatheoretic simplifier with
 hypothesis function @('hyp-fn'), exactly as for vanilla metafunctions.  The
 only difference is that when the metafunctions are applied, some contextual
 information is passed in via the @('mfc') argument and the ACL2 @(tsee state)
 is made available.</p>

 <p>See @(see meta) for a discussion of vanilla flavored metafunctions.  This
 documentation assumes you are familiar with the simpler situation, in
 particular, how to define a vanilla flavored metafunction, @('fn'), and its
 associated hypothesis metafunction, @('hyp-fn'), and how to state and prove
 metatheorems installing such functions.  Defining extended metafunctions
 requires that you also be familiar with many ACL2 implementation details.
 This documentation is sketchy on these details; see the ACL2 source code or
 email the @(see acl2-help) list if you need more help.</p>

 <p>Additional hypotheses are supported, called ``meta-extract hypotheses'',
 that allow metafunctions to depend on the validity of certain terms extracted
 from the context or the logical @(see world).  These hypotheses provide an
 even more advanced form of metatheorem so we explain them elsewhere; see @(see
 meta-extract).</p>

 <p>The metafunction context, @('mfc'), is a list containing many different
 data structures used by various internal ACL2 functions.  Generally, your
 extended metafunction will take @('mfc') as its second formal and pass it into
 the functions mentioned below.  However, advanced users who want other access
 to @('mfc') may wish to see the documentation for @(see mfc).  The ACL2
 @('state') is well-documented (see @(see state)).  Below we present
 expressions below that can be useful in defining extended metafunctions.  Some
 of these expressions involve keyword arguments, @(':forcep') and @(':ttree'),
 which are optional and in most cases are fine to omit, and which we explain
 after we present the useful expressions.</p>

 <p>@('(mfc-clause mfc)'): returns the current goal, in clausal form.  A clause
 is a list of ACL2 terms, implicitly denoting the disjunction of the listed
 terms.  The clause returned by @('mfc-clause') is the clausal form of the
 translation (see @(see trans)) of the goal or subgoal on which the rewriter is
 working.  When a metafunction calls @('mfc-clause'), the term, @('term-mf'),
 being rewritten by the metafunction has resulted from an attempt to rewrite
 some term, @('term-cl'), in this clause.  These could be the same term, but
 that need not be the case: for example, @('term-mf') could be a term to which
 the rewriter has backchained while trying to rewrite @('term-cl'), or
 @('term-mf') could arise from the right-hand side of a rewrite rule applied to
 @('term-cl').</p>

 <p>@('(mfc-ancestors mfc)'): returns an alist whose keys are the negations of
 the backchaining hypotheses being pursued.  In particular, @('(null
 (mfc-ancestors mfc))') will be true exactly when rewriting is on part of the
 current goal.  Exception: An element of this alist whose key is of the form
 @('(:binding-hyp hyp unify-subst)') indicates that @('hyp') has been
 encountered as a hypothesis of the form @('(equal var term)') or @('(equiv var
 (double-rewrite-term))'), in each case binding variable @('var') to the result
 of rewriting @('term') under @('unify-subst').</p>

 <p>@('(mfc-rdepth mfc)'): returns the remaining stack depth for calls of the
 rewriter (by default, @('*default-rewrite-stack-limit*') at the top level; see
 @(see rewrite-stack-limit)).  When this is 0, no further calls of the rewriter
 can be made without error.</p>

 <p>@('(mfc-type-alist mfc)'): returns the type-alist governing the occurrence
 of the term, @('x'), being rewritten by the metafunction.  A type-alist is an
 association list, each element of which is of the form @('(term ts . ttree)').
 Such an element means that the term @('term') has the @(see type-set) @('ts');
 see @(see type-alist).  The @('ttree') component is probably irrelevant here.
 All the terms in the type-alist are in translated form (see @(see trans)).
 The @('ts') are numbers denoting finite Boolean combinations of ACL2's
 primitive types (see @(see type-set)).  The type-alist includes not only
 information gleaned from the conditions governing the term being rewritten but
 also that gleaned from forward chaining from the (negations of the) other
 literals in the clause returned by @('mfc-clause').</p>

 <p>@('(mfc-unify-subst mfc)'): returns @('nil') except when evaluating a
 @(tsee syntaxp) or @(tsee bind-free) hypothesis, in which case, returns the
 unifying substitution present at the start of that evaluation.</p>

 <p>@('(mfc-world mfc)'): returns the ACL2 logical @(tsee world).</p>

 <p>@('(mfc-ts term mfc state :forcep forcep :ttreep ttreep)'): returns the
 @('type-set') of @('term') in the current context; see @(see type-set).</p>

 <p>@('(mfc-rw term obj equiv-info mfc state)'): returns the result of
 rewriting @('term') in the current context, @('mfc'), with objective @('obj')
 and the equivalence relation described by @('equiv-info').  @('Obj') should be
 @('t'), @('nil'), or @('?'), and describes your objective: try to show that
 @('term') is true, false, or anything.  @('Equiv-info') is either @('nil'),
 @('t'), a function symbol @('fn') naming a known equivalence relation, or a
 list of congruence rules.  @('Nil') means return a term that is @('equal') to
 @('term').  @('T') means return a term that is propositionally equivalent
 (i.e., in the @('iff') sense) to @('term'), while @('fn') means return a term
 @('fn')-equivalent to @('term').  The final case, which is intended only for
 advanced users, allows the specification of generated equivalence relations,
 as supplied to the @('geneqv') argument of @('rewrite').  Generally, if you
 wish to establish that @('term') is true in the current context, use the
 idiom</p>

 @({
  (equal (mfc-rw term t t mfc state) *t*)
 })

 <p>The constant @('*t*') is set to the internal form of the constant term
 @('t'), i.e., @(''t').</p>

 <p>@('(mfc-rw+ term alist obj equiv-info mfc state)'): if @('alist') is
 @('nil') then this is equivalent to @('(mfc-rw term obj equiv-info mfc
 state)').  However, the former takes an argument, @('alist'), that binds
 variables to terms, and returns the result of rewriting @('term') under that
 @('alist'), where this rewriting is as described for @('mfc-rw') above.  The
 function @('mfc-rw+') can be more efficient than @('mfc-rw'), because the
 terms in the binding alist have generally already been rewritten, and it can
 be inefficient to rewrite them again.  For example, consider a rewrite rule of
 the following form.</p>

 @({
  (implies (and ...
                (syntaxp (... (mfc-rw `(bar ,x) ...) ...))
                ...)
           (equal (... x ...) ...))
 })

 <p>Here, @('x') is bound in the conclusion to the result of rewriting some
 term, say, @('tm').  Then the above call of @('mfc-rw') will rewrite @('tm'),
 which is probably unnecessary.  So a preferable form of the rule above may be
 as follows, so that @('tm') is not further rewritten by @('mfc-rw+').</p>

 @({
  (implies (and ...
                (syntaxp (... (mfc-rw+ '(bar v) `((v . ,x)) ...) ...))
                ...)
           (equal (... x ...) ...))
 })

 <p>However, you may find that the additional rewriting done by @('mfc-rw') is
 useful in some cases.</p>

 <p>@('(mfc-ap term mfc state)'): returns @('t') or @('nil') according to
 whether linear arithmetic can determine that @('term') is false.  To the
 cognoscenti: returns the contradiction flag produced by linearizing @('term')
 and adding it to the @('linear-pot-lst').</p>

 <p>@('(mfc-relieve-hyp hyp alist rune target bkptr mfc state)'): returns
 @('t') or @('nil') according to whether the indicated hypothesis term,
 @('hyp'), can be relieved (proved) under the giving variable bindings,
 @('alist').  Note that this function returns @('nil') if @('hyp') has free
 variables (see @(see free-variables)).  Here, @('hyp') is the hypothesis of
 the indicated @(tsee rune) at (one-based) position @('bkptr'), and @('target')
 is an instantiated term to which @('rune') is being applied.  Note that no
 indication is returned for whether any assumptions have been generated by
 @(tsee force) or @(tsee case-split).  (If you need such a feature, feel free
 to request it of the ACL2 implementors.)</p>

 <p>We explain the @(':forcep') and @(':ttreep') keyword arguments provided in
 some expressions, as promised above.  Their defaults are @(':same') and
 @('nil'), respectively.  A value of @(':same') for @(':forcep') means that
 forcing will be allowed if and only if it is allowed in the current rewriting
 environment; see @(see force).  A value of @('t') or @('nil') for @(':forcep')
 overrides this default and allows or disallows forcing, respectively.  By
 default these functions return a single value, @('val'), but if @(':ttreep')
 is @('t') then they return @('(mv val ttree)'), where @('ttree') is the
 tag-tree (see @(see ttree)) returned by the indicated operation, with an input
 tag-tree of @('nil')).</p>

 <p>During the execution of a metafunction by the theorem prover, the
 expressions above compute the results specified.  Typically, you should
 imagine that there are no axioms about the @('mfc-') function symbols: treat
 them as uninterpreted function symbols.  There is an advanced feature,
 meta-extract hypotheses, that can avoid this logical weakness in some cases
 when proving @(':')@(tsee meta) rules; see @(see meta-extract).  But we assume
 for the rest of the present @(see documentation) topic that you do not use
 meta-extract hypotheses.  Thus, in the proof of the correctness of a
 metafunction, no information is available about the results of these
 functions: you should <i>use these functions for heuristic purposes
 only</i>.</p>

 <p>For example, your metafunction may use these functions to decide whether to
 perform a given transformation, but the transformation must be sound
 regardless of the value that your metafunction returns.  We illustrate this
 below.  It is sometimes possible to use the hypothesis metafunction,
 @('hyp-fn'), to generate a sufficient hypothesis to justify the
 transformation.  The generated hypothesis might have already been ``proved''
 internally by your use of @('mfc-ts') or @('mfc-rw'), but the system will have
 to prove it ``officially'' by relieving it.  We illustrate this below
 also.</p>

 <p>We conclude with a script that defines, verifies, and uses several extended
 metafunctions.  This script is based on one provided by Robert Krug, who was
 instrumental in the development of this style of metafunction and whose help
 we gratefully acknowledge.</p>

 @({
  ; Here is an example.  I will define (foo i j) simply to be (+ i j).
  ; But I will keep its definition disabled so the theorem prover
  ; doesn't know that.  Then I will define an extended metafunction
  ; that reduces (foo i (- i)) to 0 provided i has integer type and the
  ; expression (< 10 i) occurs as a hypothesis in the clause.

  ; Note that (foo i (- i)) is 0 in any case.

  (defun foo (i j) (+ i j))

  (defevaluator eva eva-lst ((foo i j)
                             (unary-- i)

  ; I won't need these two cases until the last example below, but I
  ; include them now.

                             (if x y z)
                             (integerp x)))

  (set-state-ok t)

  (defun metafn (x mfc state)
    (cond
     ((and (consp x)
           (equal (car x) 'foo)
           (equal (caddr x) (list 'unary-- (cadr x))))

  ; So x is of the form (foo i (- i)).  Now I want to check some other
  ; conditions.

      (cond ((and (ts-subsetp (mfc-ts (cadr x) mfc state)
                              *ts-integer*)
                  (member-equal `(NOT (< '10 ,(cadr x)))
                                (mfc-clause mfc)))
             (quote (quote 0)))
            (t x)))
     (t x)))

  (defthm metafn-correct
    (equal (eva x a) (eva (metafn x mfc state) a))
    :rule-classes ((:meta :trigger-fns (foo))))

  (in-theory (disable foo))

  ; The following will fail because the metafunction won't fire.
  ; We don't know enough about i.

  (thm (equal (foo i (- i)) 0))

  ; Same here.

  (thm (implies (and (integerp i) (< 0 i)) (equal (foo i (- i)) 0)))

  ; But this will work.

  (thm (implies (and (integerp i) (< 10 i))
                (equal (foo i (- i)) 0)))

  ; This won't, because the metafunction looks for (< 10 i) literally,
  ; not just something that implies it.

  (thm (implies (and (integerp i) (< 11 i))
                (equal (foo i (- i)) 0)))

  ; Now I will undo the defun of metafn and repeat the exercise, but
  ; this time check the weaker condition that (< 10 i) is provable
  ; (by rewriting it) rather than explicitly present.

  (ubt 'metafn)

  (defun metafn (x mfc state)
    (cond
     ((and (consp x)
           (equal (car x) 'foo)
           (equal (caddr x) (list 'unary-- (cadr x))))
      (cond ((and (ts-subsetp (mfc-ts (cadr x) mfc state)
                              *ts-integer*)
                  (equal (mfc-rw `(< '10 ,(cadr x)) t t mfc state)
                         *t*))

  ; The mfc-rw above rewrites (< 10 i) with objective t and iffp t.  The
  ; objective means the theorem prover will try to establish it.  The
  ; iffp means the theorem prover can rewrite maintaining propositional
  ; equivalence instead of strict equality.

             (quote (quote 0)))
            (t x)))
     (t x)))

  (defthm metafn-correct
    (equal (eva x a) (eva (metafn x mfc state) a))
    :rule-classes ((:meta :trigger-fns (foo))))

  (in-theory (disable foo))

  ; Now it will prove both:

  (thm (implies (and (integerp i) (< 10 i))
                (equal (foo i (- i)) 0)))

  (thm (implies (and (integerp i) (< 11 i))
                (equal (foo i (- i)) 0)))

  ; Now I undo the defun of metafn and change the problem entirely.
  ; This time I will rewrite (integerp (foo i j)) to t.  Note that
  ; this is true if i and j are integers.  I can check this
  ; internally, but have to generate a hyp-fn to make it official.

  (ubt 'metafn)

  (defun metafn (x mfc state)
    (cond
     ((and (consp x)
           (equal (car x) 'integerp)
           (consp (cadr x))
           (equal (car (cadr x)) 'foo))

  ; So x is (integerp (foo i j)).  Now check that i and j are
  ; ``probably'' integers.

      (cond ((and (ts-subsetp (mfc-ts (cadr (cadr x)) mfc state)
                              *ts-integer*)
                  (ts-subsetp (mfc-ts (caddr (cadr x)) mfc state)
                              *ts-integer*))
             *t*)
            (t x)))
     (t x)))

  ; To justify this transformation, I generate the appropriate hyps.

  (defun hyp-fn (x mfc state)

    (declare (ignore mfc state))

  ; The hyp-fn is run only if the metafn produces an answer different
  ; from its input.  Thus, we know at execution time that x is of the
  ; form (integerp (foo i j)) and we know that metafn rewrote
  ; (integerp i) and (integerp j) both to t.  So we just produce their
  ; conjunction.  Note that we must produce a translated term; we
  ; cannot use the macro AND and must quote constants!  Sometimes you
  ; must do tests in the hyp-fn to figure out which case the metafn
  ; produced, but not in this example.

             `(if (integerp ,(cadr (cadr x)))
                  (integerp ,(caddr (cadr x)))
                  'nil))

  (defthm metafn-correct
    (implies (eva (hyp-fn x mfc state) a)
             (equal (eva x a) (eva (metafn x mfc state) a)))
    :rule-classes ((:meta :trigger-fns (integerp))))

  (in-theory (disable foo))

  ; This will not be proved.

  (thm (implies (and (rationalp x) (integerp i)) (integerp (foo i j))))

  ; But this will be.

  (thm (implies (and (rationalp x)
                     (integerp i)
                     (integerp j))
                (integerp (foo i j))))
 })")

(defxdoc extra-info
  :parents (guard)
  :short "Sources of measure or guard proof obligations"
  :long "<p>@('(Extra-info x y)') always returns @('t') by definition.  See
 @(see guard-debug) and see @(see measure-debug) for a discussion of this
 function, which is useful for debugging failures from attempts to prove
 measure conjectures or to verify @(see guard)s.</p>")

(defxdoc |Evaluating App on Sample Input|
  :parents (|Pages Written Especially for the Tours|)
  :short "Evaluating App on Sample Input"
  :long "<p><see topic='@(url |The Associativity of App|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p><img src='res/tours/green-line.gif'></img></p>

 <code>
 ACL2 !&gt;<b>(app nil '(x y z))</b>
 (X Y Z)

 ACL2 !&gt;<b>(app '(1 2 3) '(4 5 6 7))</b>
 (1 2 3 4 5 6 7)

 ACL2 !&gt;<b>(app '(a b c d e f g) '(x y z))</b>   ; click <see topic='@(url |Conversion|)'>here</see> for an explanation
 (A B C D E F G X Y Z)

 ACL2 !&gt;<b>(app (app '(1 2) '(3 4)) '(5 6))</b>
 (1 2 3 4 5 6)

 ACL2 !&gt;<b>(app '(1 2) (app '(3 4) '(5 6)))</b>
 (1 2 3 4 5 6)

 ACL2!&gt;<b>(let ((a '(1 2))</b>
             <b>(b '(3 4))</b>
             <b>(c '(5 6)))</b>
         <b>(equal (app (app a b) c)</b>
                <b>(app a (app b c))))</b>
 T
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>As we can see from these examples, ACL2 functions can be executed more or
 less as Common Lisp.</p>

 <p>The last three examples suggest an interesting property of @('app').</p>

 <p><see topic='@(url |The Associativity of App|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc f-get-global
  :parents (programming-with-state acl2-built-ins)
  :short "Get the value of a global variable in @(tsee state)"
  :long "@({
  Examples:
  (+ (f-get-global 'y state) 1)
  (f-put-global 'a
                (aset1 'ascii-map-array
                       (f-get-global 'a state)
                       66
                       'Upper-case-B)
                state)

  General Form:
  (f-get-global 'symbol state)
 })

 <p>where @('symbol') is any symbol to which you have @(tsee assign)ed a global
 value.</p>

 <p>The macro @(tsee @) is closely related to @('f-get-global'): @('(@ var)')
 macroexpands to @('(f-get-global 'var state)').</p>

 <p>The macro @(tsee f-put-global) makes it convenient to set the value of a
 symbol.  The @(':')@(tsee ubt) operation has no effect on the
 @('global-table') of @(tsee state).  Thus, you may use these globals to hang
 onto useful data structures even though you may undo back past where you
 computed and saved them.</p>")

(defxdoc f-put-global
  :parents (programming-with-state acl2-built-ins)
  :short "Assign to a global variable in @(tsee state)"
  :long "@({
  Examples:
  (f-put-global 'x (expt 2 10) state)
  (f-put-global 'a (aset1 'ascii-map-array (@ a) 66 'Upper-case-B) state)

  General Form:
  (f-put-global (quote symbol) term state)
 })

 <p>where @('symbol') is any symbol (with certain enforced exclusions to avoid
 overwriting ACL2 system ``globals'') and @('term') is any ACL2 term that could
 be evaluated at the top-level.  @('F-put-global') evaluates the term, stores
 the result as the value of the given symbol in the @('global-table') of @(tsee
 state), and returns the new @('state').  (Note: the actual implementation of
 the storage of this value is much more efficient than this discussion of the
 logic might suggest.)</p>

 <p>The macro @(tsee assign) is closely related to @('f-put-global'):
 @('(assign var val)') macroexpands to @('(f-put-global 'var val state)').</p>

 <p>The macros @(tsee @) and @(tsee f-get-global) give convenient access to the
 value of such globals.  The @(':')@(tsee ubt) operation has no effect on the
 @('global-table') of @(tsee state).  Thus, you may use these globals to hang
 onto useful data structures even though you may undo back past where you
 computed and saved them.</p>")

(defxdoc failed-forcing
  :parents (force debugging)
  :short "How to deal with a proof @(see failure) in a forcing round"
  :long "<p>See @(see forcing-round) for a background discussion of the notion
 of forcing rounds.  When a proof fails during a forcing round it means that
 the ``gist'' of the proof succeeded but some ``technical detail'' failed.  The
 first question you must ask yourself is whether the @(see force)d goals are
 indeed theorems.  We discuss the possibilities below.</p>

 <p>If you believe the @(see force)d goals are theorems, you should follow the
 usual methodology for ``fixing'' failed ACL2 proofs, e.g., the identification
 of key lemmas and their timely and proper use as rules.  See @(see failure),
 see @(see gag-mode), and see @(see proof-tree).</p>

 <p>The rules designed for the goals of forcing rounds are often just what is
 needed to prove the @(see force)d hypothesis at the time it is @(see force)d.
 Thus, you may find that when the system has been ``taught'' how to prove the
 goals of the forcing round no forcing round is needed.  This is intended as a
 feature to help structure the discovery of the necessary rules.</p>

 <p>If a hint must be provided to prove a goal in a forcing round, the
 appropriate ``goal specifier'' (the string used to identify the goal to which
 the hint is to be applied) is just the text printed on the line above the
 formula, e.g., @('\"[1]Subgoal *1/3''\"').  See @(see goal-spec).</p>

 <p>If you solve a forcing problem by giving explicit @(see hints) for the
 goals of forcing rounds, you might consider whether you could avoid forcing
 the assumption in the first place by giving those @(see hints) in the
 appropriate places of the main proof.  This is one reason that we print out
 the origins of each @(see force)d assumption.  An argument against this style,
 however, is that an assumption might be @(see force)d in hundreds of places in
 the main goal and proved only once in the forcing round, so that by delaying
 the proof you actually save time.</p>

 <p>We now turn to the possibility that some goal in the forcing round is not a
 theorem.</p>

 <p>There are two possibilities to consider.  The first is that the original
 theorem has insufficient hypotheses to ensure that all the @(see force)d
 hypotheses are in fact always true.  The ``fix'' in this case is to amend the
 original conjecture so that it has adequate hypotheses.</p>

 <p>A more difficult situation can arise and that is when the conjecture has
 sufficient hypotheses but they are not present in the forcing round goal.
 This can be caused by what we call ``premature'' forcing.</p>

 <p>Because ACL2 rewrites from the inside out, it is possible that it will
 @(see force) hypotheses while the context is insufficient to establish them.
 Consider trying to prove @('(p x (foo x))').  We first rewrite the formula in
 an empty context, i.e., assuming nothing.  Thus, we rewrite @('(foo x)') in an
 empty context.  If rewriting @('(foo x)') @(see force)s anything, that @(see
 force)d assumption will have to be proved in an empty context.  This will
 likely be impossible.</p>

 <p>On the other hand, suppose we did not attack @('(foo x)') until after we
 had expanded @('p').  We might find that the value of its second argument,
 @('(foo x)'), is relevant only in some cases and in those cases we might be
 able to establish the hypotheses @(see force)d by @('(foo x)').  Our premature
 forcing is thus seen to be a consequence of our ``over eager'' rewriting.</p>

 <p>Here, just for concreteness, is an example you can try.  In this example,
 @('(foo x)') rewrites to @('x') but has a @(see force)d hypothesis of
 @('(rationalp x)').  @('P') does a case split on that very hypothesis and uses
 its second argument only when @('x') is known to be rational.  Thus, the
 hypothesis for the @('(foo x)') rewrite is satisfied.  On the false branch of
 its case split, @('p') simplifies to @('(p1 x)') which can be proved under the
 assumption that @('x') is not rational.</p>

 @({
  (defun p1 (x) (not (rationalp x)))
  (defun p (x y)(if (rationalp x) (equal x y) (p1 x)))
  (defun foo (x) x)
  (defthm foo-rewrite (implies (force (rationalp x)) (equal (foo x) x)))
  (in-theory (disable foo))
 })

 <p>The attempt then to do @('(thm (p x (foo x)))') @(see force)s the
 unprovable goal @('(rationalp x)').</p>

 <p>Since all ``formulas'' are presented to the theorem prover as single terms
 with no hypotheses (e.g., since @(tsee implies) is a function), this problem
 would occur routinely were it not for the fact that the theorem prover expands
 certain ``simple'' definitions immediately without doing anything that can
 cause a hypothesis to be @(see force)d.  See @(see simple).  This does not
 solve the problem, since it is possible to hide the propositional structure
 arbitrarily deeply.  For example, one could define @('p'), above, recursively
 so that the test that @('x') is rational and the subsequent first ``real'' use
 of @('y') occurred arbitrarily deeply.</p>

 <p>Therefore, the problem remains: what do you do if an impossible goal is
 @(see force)d and yet you know that the original conjecture was adequately
 protected by hypotheses?</p>

 <p>One alternative is to disable forcing entirely.  See @(see
 disable-forcing).  Another is to @(see disable) the rule that caused the @(see
 force).</p>

 <p>A third alternative is to prove that the negation of the main goal implies
 the @(see force)d hypothesis.  For example,</p>

 @({
  (defthm not-p-implies-rationalp
    (implies (not (p x (foo x))) (rationalp x))
    :rule-classes nil)
 })

 <p>Observe that we make no rules from this formula.  Instead, we merely
 @(':use') it in the subgoal where we must establish @('(rationalp x)').</p>

 @({
  (thm (p x (foo x))
       :hints ((\"Goal\" :use not-p-implies-rationalp)))
 })

 <p>When we said, above, that @('(p x (foo x))') is first rewritten in an empty
 context we were misrepresenting the situation slightly.  When we rewrite a
 literal we know what literal we are rewriting and we implicitly assume it
 false.  This assumption is ``dangerous'' in that it can lead us to simplify
 our goal to @('nil') and give up &mdash; we have even seen people make the
 mistake of assuming the negation of what they wished to prove and then via a
 very complicated series of transformations convince themselves that the
 formula is false.  Because of this ``tail biting'' we make very weak use of
 the negation of our goal.  But the use we make of it is sufficient to
 establish the @(see force)d hypothesis above.</p>

 <p>A fourth alternative is to weaken your desired theorem so as to make
 explicit the required hypotheses, e.g., to prove</p>

 @({
  (defthm rationalp-implies-main
    (implies (rationalp x) (p x (foo x)))
    :rule-classes nil)
 })

 <p>This of course is unsatisfying because it is not what you originally
 intended.  But all is not lost.  You can now prove your main theorem from this
 one, letting the @(tsee implies) here provide the necessary case split.</p>

 @({
  (thm (p x (foo x))
       :hints ((\"Goal\" :use rationalp-implies-main)))
 })")

(defxdoc failure
  :parents (debugging)
  :short "How to deal with a proof failure"
  :long "<p>When ACL2 gives up it does not mean that the submitted conjecture
 is invalid, even if the last formula ACL2 printed in its proof attempt is
 manifestly false.  Since ACL2 sometimes @(see generalize)s the goal being
 proved, it is possible it adopted an invalid subgoal as a legitimate (but
 doomed) strategy for proving a valid goal.  Nevertheless, conjectures
 submitted to ACL2 are often invalid and the proof attempt often leads the
 careful reader to the realization that a hypothesis has been omitted or that
 some special case has been forgotten.  It is good practice to ask yourself,
 when you see a proof attempt fail, whether the conjecture submitted is
 actually a theorem.</p>

 <p>If you think the conjecture is a theorem, then you must figure out from
 ACL2's output what you know that ACL2 doesn't about the functions in the
 conjecture and how to impart that knowledge to ACL2 in the form of rules.  The
 ``key checkpoint'' information printed at the end of the summary provides a
 fine place to start.  See @(see the-method) for a general discussion of how to
 prove theorems with ACL2, and see @(see introduction-to-the-theorem-prover)
 for a more detailed tutorial.  Also see @(see set-gag-mode) for discussion of
 key checkpoints and an abbreviated output mode that focuses attention on them.
 You may find it most useful to start by focusing on key checkpoints that are
 not under a proof by induction, if any, both because these are more likely to
 suggest useful lemmas and because they are more likely to be theorems; for
 example, generalization may have occurred before a proof by induction has
 begun.  If you need more information than is provided by the key checkpoints
 &mdash; although this should rarely be necessary &mdash; then you can look at
 the full proof, perhaps with the aid of certain utilities: see @(see
 proof-tree), see @(see set-gag-mode), and see @(see set-saved-output).</p>

 <p>For information on a tool to help debug failures of @(tsee encapsulate) and
 @(tsee progn) events, as well as @(tsee certify-book) failures, see @(see
 redo-flat).</p>

 <p>Again, see @(see the-method) for a general discussion of how to prove
 theorems with ACL2, and see @(see introduction-to-the-theorem-prover) for a
 more detailed tutorial.  See also the book ``Computer-Aided Reasoning: An
 Approach'' (Kaufmann, Manolios, Moore), as well as the discussion of how to
 read Nqthm proofs and how to use Nqthm rules in ``A Computational Logic
 Handbook'' by Boyer and Moore (Academic Press, 1988).</p>

 <p>If the failure occurred during a forcing round, see @(see
 failed-forcing).</p>")

(defxdoc fancy-string-reader
  :parents (reader)
  :short "A friendly syntax for strings literals that have backslashes and
quotes."

  :long "<p>Examples:</p>
@({
     ACL2 !> #{\"\"\"Hello, World!\"\"\"}
     \"Hello, World!\"

     ACL2 !> #{\"\"\"<img src=\"hello.png\"/>\"\"\"}
     \"<img src=\\\"hello.png\\\"/>\"

     ACL2 !> #{\"\"\"C:\\ACL2\\axioms.lisp\"\"\"}
     \"C:\\\\ACL2\\\\axioms.lisp\"
})

<p>String literals in ACL2 and Common Lisp source code files are usually
written as text strings within quote marks.  For instance, the 5-character
string whose contents are @('Hello') is normally written as @('\"Hello\"').</p>

<p>Usually this syntax is fine, but things can get tricky when you want to
write a string whose contents include @('\"') marks.  For example, if you
wanted to write down a string whose contents were:</p>

@({
     <img src=\"hello.png\"/>
})

<p>then you would need to escape the quote marks within it using backslash
characters, e.g., as follows:</p>

@({
     \"<img src=\\\"hello.png\\\"/>\"
})

<p>But using @('\\') as a special character means we also need a special way to
write backslashes.  For instance, if we want to write a string literal whose
contents are:</p>

@({
      C:\\ACL2\\axioms.lisp
})

<p>Then we would need to write something a string literal such as:</p>

@({
      \"C:\\\\ACL2\\\\axioms.lisp\"
})

<p>In certain cases, such as when writing long @(see documentation) strings,
the extra escaping can be tedious and error-prone.</p>

<p>To simplify this, ACL2 provides an alternate @('#{\"\"\"...\"\"\"}') syntax
for string literals.  This syntax has no special characters, so nothing needs
to be escaped.  The end of the string is recognized by the unusual character
sequence @('\"\"\"}').</p>

<p>Of course, a string that needs to contain the sequence @('\"\"\"}') cannot
be represented using this fancy string literal syntax, but in practice that's
rarely ever a problem.</p>")

(defxdoc fast-alist-clean
  :parents (fast-alists acl2-built-ins)
  :short "@('(fast-alist-clean alist)') can be used to eliminate
 \"shadowed pairs\" from a fast alist."
  :long "<p>This @(see documentation) topic assumes familiarity with fast
 alists; see @(see fast-alists).  See @(tsee fast-alist-clean!), @(tsee
 fast-alist-fork), and @(tsee fast-alist-fork!) for related utilities.</p>

 <p>Logically, @('(fast-alist-clean alist)') is defined as follows:</p>

 @(def fast-alist-clean)

 <p>The result is thus a corresponding fast alist, with the order reversed and
 with atoms and shadowed pairs removed, as per the definition above; see @(see
 fast-alist-fork) for details.  Moreover, if @('alist') is not a fast alist,
 then @('(fast-alist-clean alist)') is executed in raw Lisp by calling
 @('fast-alist-fork') as indicated above.</p>

 <p>However, if @('alist') is a fast alist, then a special definition under the
 hood provides a different handling of associated hash tables.  After running
 @('(fast-alist-clean alist)') to obtain a result, @('cleaned-alist'), the hash
 table that had been associated with @('alist') will now be associated with
 @('cleaned-alist') instead.  This saves the expense of creating a new hash
 table, but there is still the expense of copying the alist, as for @(tsee
 fast-alist-fork).  However, unlike @('fast-alist-fork'), there is no need to
 free the input alist.</p>

 <p>Note that the final @('cdr') is preserved, so that the name is preserved
 for use by @(tsee fast-alist-summary) (also see @(see hons-acons)).</p>")

(defxdoc fast-alist-clean!
  :parents (fast-alists acl2-built-ins)
  :short "@('(fast-alist-clean! alist)') is an alternative to @(tsee
fast-alist-clean) that produces a @(see normed) result."
  :long "<p>Logically this function is just @('fast-alist-clean'); we leave it
 enabled and would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, this is the same as @('fast-alist-clean') except that it
 uses something like @(tsee hons-acons!) instead of @(tsee hons-acons).  You
 generally <b>should not use</b> this function unless you really know what
 you're doing and understand the drawbacks discussed in @(tsee
 hons-acons!).</p>")

(defxdoc fast-alist-fork
  :parents (fast-alists acl2-built-ins)
  :short "@('(fast-alist-fork alist ans)') can be used to eliminate
\"shadowed pairs\" from an alist or to copy @(see fast-alists)."
  :long "<p>This @(see documentation) topic assumes familiarity with fast
 alists; see @(see fast-alists).  See @(tsee fast-alist-fork!), @(tsee
 fast-alist-clean), and @(tsee fast-alist-clean!) for related utilities.</p>

 <p>Logically, @('(fast-alist-fork alist ans)') is defined as follows:</p>

 @(def fast-alist-fork)

 <p>The alist argument need not be a fast alist.</p>

 <p>Typically ans is set to nil or some other atom.  In this case, shrinking
 produces a new, fast alist which is like alist except that (1) any
 \"malformed,\" atomic entries have been removed, (2) all \"shadowed pairs\"
 have been removed, and (3) incidentally, the surviving elements have been
 reversed.  This can be useful as a way to clean up any unnecessary bindings in
 alist, or as a way to obtain a \"deep copy\" of a fast alist that can extended
 independently from the original while maintaining discipline.</p>

 <p>Note that fast-alist-fork is potentially expensive, for the following two
 reasons.</p>

 <ul>

 <li>The alist is copied, dropping any shadowed pairs.  This process will
 require a hash table lookup for each entry in the alist; and it will require
 creating a new alist, which uses additional memory.</li>

 <li>Unless ans is a fast alist that is stolen (see below), a new hash table
 is created, which uses additional memory.  This hash table is populated in
 time that is linear in the number of unique keys in the
 alist.</li>

 </ul>

 <p>When ans is not an atom, good discipline requires that it is a fast alist.
 In this case, @('fast-alist-fork') steals the hash table for ans and extends
 it with all of the bindings in alist that are not in ans.  From the
 perspective of @(tsee hons-assoc-equal), you can think of the resulting alist
 as being basically similar to @('(append ans alist)'), but in a different
 order.</p>

 <p>Note that when ans is not a fast alist (e.g., ans is an atom) then such
 stealing does not take place.</p>

 <p>A common idiom is to replace an alist by the result of shrinking it, in
 which case it is best to free the input alist, for example as follows.</p>

 @({
    (let ((alist (fast-alist-free-on-exit alist
                                          (fast-alist-fork alist nil))))
      ...)
 })

 <p>See @(see fast-alist-free-on-exit) and see @(see fast-alist-free).</p>

 ")

(defxdoc fast-alist-fork!
  :parents (fast-alists acl2-built-ins)
  :short "@('(fast-alist-fork! alist ans)') is an alternative to @(tsee
fast-alist-fork) that produces a @(see normed) result."
  :long "<p>Logically this function is just @('fast-alist-fork'); we leave it
 enabled and would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, this is the same as @('fast-alist-fork') except that it
 uses something like @(tsee hons-acons!) instead of @(tsee hons-acons).  You
 generally <b>should not use</b> this function unless you really know what
 you're doing and understand the drawbacks discussed in @(tsee
 hons-acons!).</p>")

(defxdoc fast-alist-free
  :parents (fast-alists acl2-built-ins)
  :short "@('(fast-alist-free alist)') throws away the hash table associated
with a fast alist."
  :long "<p>Logically, this function is the identity; we leave it enabled and
 would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, @('fast-alist-free') removes the hash table associated with
 this alist, if one exists.  This effectively converts the alist into an
 ordinary alist.</p>

 <p>Also see @(see fast-alist-free-on-exit).</p>

 <p>Because there is no automatic mechanism for freeing the hash tables used in
 fast alists, to avoid memory leaks you should manually free any alists that
 will no longer be used.  You may find @(tsee fast-alist-summary) useful in
 tracking down alists that were not properly freed.</p>

 <p>It is safe to call @('fast-alist-free') on any argument, including fast
 alists that have already been freed and objects which are not alists at
 all.</p>

 @(def fast-alist-free)")

(defxdoc fast-alist-free-on-exit
  :parents (fast-alists acl2-built-ins)
  :short "Free a fast alist after the completion of some form."
  :long "<p>Logically, @('(fast-alist-free-on-exit alist form)') is the
 identity and returns @('form').  Also see @(see fast-alist-free).</p>

 <p>Under the hood, this essentially expands to:</p>

 @({
   (prog1 form
          (fast-alist-free alist))
 })

 <p>In other words, @('alist') is not freed immediately, but instead remains a
 fast alist until the form completes.  This may be useful when you are writing
 code that uses a fast alist but has many return points.</p>

 <p>See also the macro @('fast-alists-free-on-exit') defined in the community
 book @('\"books/centaur/misc/hons-extra.lisp\"'), which can be used to free
 several alists.</p>

 <p>The community book @('\"books/centaur/misc/hons-extra.lisp\"') extends the
 @(see b*) macro with the @('free-on-exit') pattern binder.  That is, after
 executing @('(include-book \"centaur/misc/hons-extra.lisp\" :dir :system)'),
 the form</p>

 @({
   (b* (...
        ((free-on-exit a b c))
        ...)
     ...)
 })

 <p>causes @('a'), @('b'), and @('c') to be freed when the @('b*') completes,
 but they remain fast alists until then.</p>")

(defxdoc fast-alist-len
  :parents (fast-alists acl2-built-ins)
  :short "@('(fast-alist-len alist)') counts the number of unique keys in a
  fast alist."
  :long "<p>Logically this function counts how many elements would remain in
 the alist were we to shrink it with @(tsee fast-alist-fork).</p>

 <p>Good discipline requires that the alist is a fast alist.  Under the hood,
 when the alist is a fast alist we can simply call the underlying Common Lisp
 function @('hash-table-count') on the associated hash table, which is very
 fast and doesn't require us to actually shrink the alist.</p>

 @(def fast-alist-len)")

(defxdoc fast-alist-summary
  :parents (fast-alists acl2-built-ins)
  :short "@('(fast-alist-summary)') prints some basic statistics about any
current fast alists."
  :long "<p>Logically, @('fast-alist-summary') just returns nil; we leave it
 enabled and would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, this function gathers and prints some basic statistics
 about the current fast alists.  It may be useful for identifying fast alists
 that should have been freed with @(tsee fast-alist-free).</p>

 @(def fast-alist-summary)")

(defxdoc fast-alists
  :parents (alists programming hons-and-memoization)
  :short "Alists with hidden hash tables for faster execution"
  :long "<p>The implementation of fast alists is, in many ways, similar to that
 of ACL2 arrays.  Logically, @(tsee hons-acons) is just like @('acons'), and
 @(tsee hons-get) is similar to @(tsee assoc-equal).  But under the hood, hash
 tables are associated with these alists, and, when a certain <b>discipline</b>
 is followed, these functions execute with hash table speeds.</p>

 <p>What is this discipline?  Each @('hons-acons') operation \"steals\" the
 hash table associated with the alist that is being extended.  Because of this,
 one must be very conscious of which object is the most recent extension of an
 alist and use that extension exclusively.</p>

 <p>The only penalty for a failure to keep track of the most recent extension
 is a loss of execution speed, not of correctness, and perhaps the annoyance of
 some @(tsee slow-alist-warning)s.</p>

 <p>Maintaining discipline may require careful passing of a fast alist up and
 down through function calls, as with any single threaded object in an
 applicative setting, but there is <b>no syntactic enforcement</b> that insists
 you only use the most recent extension of an alist as there is for single
 threaded objects (@(tsee stobj)s).  Also, even with perfectly proper code,
 discipline can sometimes be lost due to user interrupts and aborts.</p>

 <p>Performance Notes</p>

 <p>See @(see hons-acons) for how the final @(tsee cdr) of a fast alist can be
 used as a size hint or as a name for reports printed by calling @(tsee
 fast-alist-summary).</p>

 <p>The keys of fast alists are always @(see normed).  Why?  In Common Lisp,
 equal-based hashing is relatively slow, so to allow the use of eql-based hash
 tables, @(tsee hons-acons) and @(tsee hons-get) always @(tsee hons-copy) the
 keys involved.</p>

 <p>Since alist keys are frequently atoms, this norming activity may often be
 so fast that you do not need to think about it.  But if you are going to use
 large structures as the keys for your fast alist, this overhead can be
 significant, and you may want to ensure that your keys are normed ahead of
 time.</p>

 <p>There is <b>no automatic mechanism</b> for reclaiming the hash tables that
 are associated with alists.  Because of this, to avoid memory leaks, you
 should call @(tsee fast-alist-free) to remove the hash table associated with
 alists that will no longer be used.</p>")

(defxdoc fc-report
  :parents (forward-chaining-reports)
  :short "To report on the forward chaining activity in the most recent proof"
  :long "@({
  Example: (fc-report 15)

  General Form: (fc-report k)
 })

 <p>where @('k') is the number of some forward chaining report printed in the
 most recent event.</p>

 <p>See @(see forward-chaining-reports) for details.</p>")

(defxdoc fifth
  :parents (nth acl2-built-ins)
  :short "Fifth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc file-length$
  :parents (io)
  :short "The size of a file in bytes"
  :long "<p>This analogue of the Common Lisp function, @('file-length'), uses
 that function under the hood to compute efficiently the number of bytes @('B')
 in the specified file if that number can be determined, returning @('(mv B
 state)'); otherwise it returns @('(mv nil state)').  The @(tsee guard) of
 @('file-length$') requires that the first argument is a string; the second
 argument is the ACL2 @(tsee state).  The logical definition does not actually
 look at the file and hence is not useful for reasoning about the number of
 bytes in the file.</p>

 @(def file-length$)")

(defxdoc file-reading-example
  :parents (tutorial5-miscellaneous-examples)
  :short "Example of reading files in ACL2"
  :long "<p>This example illustrates the use of ACL2's @(see IO) primitives to
 read the forms in a file.  See @(see io).</p>

 <p>This example provides a solution to the following problem.  Let's say that
 you have a file that contains s-expressions.  Suppose that you want to build a
 list by starting with @('nil'), and updating it ``appropriately'' upon
 encountering each successive s-expression in the file.  That is, suppose that
 you have written a function @('update-list') such that @('(update-list obj
 current-list)') returns the list obtained by ``updating'' @('current-list')
 with the next object, @('obj'), encountered in the file.  The top-level
 function for processing such a file, returning the final list, could be
 defined as follows.  Notice that because it opens a channel to the given file,
 this function modifies @(see state) and hence must return @(see state).  Thus
 it actually returns two values: the final list and the new @(see state).</p>

 @({
    (defun process-file (filename state)
      (mv-let
       (channel state)
       (open-input-channel filename :object state)
       (mv-let (result state)
               (process-file1 nil channel state) ;see below
               (let ((state (close-input-channel channel state)))
                 (mv result state)))))
 })

 <p>The function @('process-file1') referred to above takes the currently
 constructed list (initially, @('nil')), together with a channel to the file
 being read and the @(see state), and returns the final updated list.  Notice
 that this function is tail recursive.  This is important because many Lisp
 compilers will remove tail recursion, thus avoiding the potential for stack
 overflows when the file contains a large number of forms.</p>

 @({
    (defun process-file1 (current-list channel state)
      (mv-let (eofp obj state)
              (read-object channel state)
              (cond
               (eofp (mv current-list state))
               (t (process-file1 (update-list obj current-list)
                                 channel state)))))
 })

 <p>As an exercise, you might want to add @(see guard)s to the functions above
 and verify the guards (see @(see verify-guards)).  See @(see args) or make a
 call of the form @('(guard 'your-function nil (w state))') to see the guard of
 an existing function.</p>")

(defxdoc file-write-date$
  :parents (io)
  :short "The write-date of a file as a natural number"
  :long "<p>This analogue of the Common Lisp function, @('file-write-date'),
 uses that function under the hood to compute the write date @('D') as a
 natural number if the write date can be determined, returning @('(mv D
 state)'); otherwise it returns @('(mv nil state)').  That number is, quoting
 the Common Lisp HyperSpec, the number of seconds ``measured as an offset from
 the beginning of the year 1900 (ignoring leap seconds)''.  The @(tsee guard)
 of @('file-write-date$') requires that the first argument is a string; the
 second argument is the ACL2 @(tsee state).  The logical definition does not
 actually look at the file and hence is not useful for reasoning about the
 write date.</p>

 @(def file-write-date$)")

(defxdoc finalize-event-user
  :parents (prover-output)
  :short "User-supplied code to complete @(see events), e.g., with extra summary output"
  :long "<p>This utility is intended for system hackers, not standard ACL2
 users.</p>

 <p>ACL2 prints summaries at the conclusions of processing @(see events)
 (unless summaries are inhibited; see @(see set-inhibit-output-lst) and also
 see @(see set-inhibited-summary-types)).  You may arrange for processing to
 take place just after the summary, by defining a function with argument list
 @('(ctx body state)') that returns one value, namely @('state').  We describe
 @('ctx') and @('body') at the end below, but you may simply prefer to ignore
 these arguments.)  Your function should normally be a @(see guard)-verified
 @(':')@(tsee logic) mode function with no guard other than that provided by
 the input requirement on @(tsee state), that is, @('(state-p state)'); but
 later below we discuss how to avoid this requirement.  You then attach (see
 @(see defattach)) your function to the function @('finalize-event-user').  The
 following example illustrates how this all works.</p>

 @({
  (defun finalize-event-user-test (ctx body state)
    (declare (xargs :stobjs state)
             (ignore ctx body))
    (cond ((and (boundp-global 'abbrev-evisc-tuple state)
                (open-output-channel-p *standard-co*
                                       :character
                                       state))
           (pprogn
            (if (eq (f-get-global 'abbrev-evisc-tuple state) :DEFAULT)
                (princ$ \"Abbrev-evisc-tuple has its default value.~%\"
                        *standard-co*
                        state)
              (princ$ \"Abbrev-evisc-tuple has been modified.~%\"
                      *standard-co*
                      state))))
          (t state)))

  (defattach finalize-event-user finalize-event-user-test)
 })

 <p>After admission of the two events above, an event summary will conclude
 with extra printout, for example:</p>

 @({
  Note: Abbrev-evisc-tuple has its default value.
 })

 <p>If the attachment function (above, @('finalize-event-user-test')) does not
 meet all the requirements stated above, then you can use the @(':skip-checks')
 argument of @(tsee defattach) to get around the requirement, as illustrated by
 the following example.</p>

 @({
  (defun finalize-event-user-test2 (state)
    (declare (xargs :stobjs state
                    :mode :program)
             (ignore ctx body))
    (observation
     'my-test
     \"~|Value of term-evisc-tuple: ~x0~|\"
     (f-get-global 'term-evisc-tuple state)))

  (defttag t) ; needed for :skip-checks t

  (defattach (finalize-event-user finalize-event-user-test2)
             :skip-checks t)
 })

 <p>So for example:</p>

 @({
  ACL2 !>(set-term-evisc-tuple (evisc-tuple 2 7 nil nil) state)
   (:TERM)
  ACL2 !>(defconst *foo6* '(a b c))

  Summary
  Form:  ( DEFCONST *FOO6* ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

  ACL2 Observation in MY-TEST:
  Value of term-evisc-tuple: (NIL 2 7 NIL)
   *FOO6*
  ACL2 !>
 })

 <p>Note that (as of this writing) the macro @(tsee observation) expands to a
 call of a @(':')@(tsee program)-mode function.  Thus, the trick shown above
 involving @(':skip-checks') allows the use of @(':program')-mode functions;
 for example, you can print with @(tsee fmt).</p>

 <p>See community book @('books/misc/defattach-bang.lisp') for a variant of
 @(tsee defattach) that uses @(tsee ec-call) to avoid issues of @(see guard)
 verification.</p>

 <p>Also see @(see initialize-event-user), which discusses the handling of
 @(see state) globals by that utility as well as by
 @('finalize-event-user').</p>

 <p>Finally, as promised above, we briefly describe the arguments @('ctx') and
 @('body').  These are the arguments passed to the call of macro
 @('with-ctx-summarized') under which @('finalize-event-user') (or
 @('initialize-event-user')) was called.  Thus, they are unevaluated
 expressions.  For example, system function @('defthm-fn1') has a body of the
 following form.</p>

 @({
  (with-ctx-summarized
   (cons 'defthm name)
   (let ((wrld (w state))
         (ens (ens state))
         .....
 })

 <p>Thus, when @('initialize-event-user') and @('finalize-event-user') are
 called on behalf of @(tsee defthm), @('ctx') is the s-expression</p>

 @({
  (cons 'defthm name)
 })

 <p>while @('body') is the following s-expression (with most code elided).</p>

 @({
   (let ((wrld (w state))
         (ens (ens state))
         .....
 })

 <p>You might find it helpful to use @(tsee trace$) to get a sense of @('ctx')
 and @('body'), for example, @('(trace$ finalize-event-user)').</p>")

(defxdoc find-rules-of-rune
  :parents (rune)
  :short "Find the rules named rune"
  :long "@({
  General Form:
  (find-rules-of-rune rune wrld)
 })

 <p>This function finds all the rules in @('wrld') with @(':')@(tsee rune)
 rune.  It returns a list of rules in their internal form (generally as
 described by the corresponding @('defrec')).  Deciphering these rules is
 difficult since one cannot always look at a rule object and decide what kind
 of record it is without exploiting many system invariants (e.g., that
 @(':')@(tsee rewrite) runes only name rewrite-rules).</p>

 <p>At the moment this function returns @('nil') if the rune in question is a
 @(':')@(tsee refinement) rune, because there is no object representing
 @(':')@(tsee refinement) rules.  (@(':')@(tsee refinement) rules cause changes
 in the @(''coarsenings') properties.)  In addition, if the rune is an
 @(':')@(tsee equivalence) rune, then congruence rules with that rune will be
 returned &mdash; because @(':')@(tsee equivalence) lemmas generate some
 congruence rules &mdash; but the fact that a certain function is now known to
 be an equivalence relation is not represented by any rule object and so no
 such rule is returned.  (The fact that the function is an equivalence relation
 is encoded entirely in its presence as a @(''coarsening') of @(tsee
 equal).)</p>")

(defxdoc finding-documentation
  :parents (documentation)
  :short "Searching the documentation"
  :long "<p>The @(':')@(tsee doc) command will display, at the terminal, @(see
 documentation) topics defined in ACL2 or in @(see books) that have already
 been included.  But how can you find documentation for books that are not
 included in the current ACL2 session?</p>

 <p>The @(see xdoc) @(`(:raw (combined-manual-ref))`) includes documentation
 for both the ACL2 system and the @(see community-books).  For more information
 on this manual and how to view it, see @(see documentation).</p>")

(defxdoc first
  :parents (nth acl2-built-ins)
  :short "First member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc fix
  :parents (numbers acl2-built-ins)
  :short "Coerce to a number"
  :long "<p>@('Fix') simply returns any numeric argument unchanged, returning
 @('0') on a non-numeric argument.  Also see @(see nfix), see @(see ifix), and
 see @(see rfix) for analogous functions that coerce to a natural number, an
 integer, and a rational number, respectively.</p>

 <p>@('Fix') has a @(see guard) of @('t').</p>

 @(def fix)")

(defxdoc fix-true-list
  :parents (lists acl2-built-ins)
  :short "Coerce to a true list"
  :long "<p>@('Fix-true-list') is the identity function on @(tsee true-listp)
 objects.  It converts every list to a true list by dropping the final @(tsee
 cdr), and it converts every @(see atom) to @('nil').</p>

 @(def fix-true-list)")

(defxdoc flet

; Not mentioned here is the fact that ACL2 source function oneify-flet-bindings
; drops type declarations in the *1* functions.  That point is so low-level
; that explaining it in the :doc topic is likely to do more harm than good.

; Regarding "Every variable occurring in the body of a @('defi') must be a formal
; parameter of that @('defi')": the following example shows that if we were to
; remove that restriction, we would need to be very careful about the use of
; special variables as formal or let-bound variables, as illustrated below.

;   ? [RAW LISP] (let ((x 3))
;                  (flet ((f (y) (+ x y)))
;                    (let ((x 4))
;                      (f 7))))
;   ;Compiler warnings :
;   ;   In an anonymous lambda form: Unused lexical variable X
;   10
;   ? [RAW LISP] (defvar x)
;   X
;   ? [RAW LISP] (let ((x 3))
;                  (flet ((f (y) (+ x y)))
;                    (let ((x 4))
;                      (f 7))))
;   11
;   ? [RAW LISP]

  :parents (basics acl2-built-ins)
  :short "Local binding of function symbols"
  :long "@({
  Example Form:
  ; The following evaluates to (mv 7 10):
  (flet ((f (x)
            (+ x 3))
         (g (x)
            (declare (type integer x))
            (* x 2)))
    (mv (f 4) (g 5)))

  General Forms:
  (flet (def1 ... defk) body)
  (flet (def1 ... defk) declare-form1 .. declare-formk body)
 })

 <p>where @('body') is a term, and each @('defi') is a definition as in @(tsee
 defun) but with the leading @('defun') symbol omitted.  See @(see defun).  If
 any @('declare-formi') are supplied, then each must be of the form @('(declare
 decl1 ... decln)'), where each @('decli') is of the form @('(inline g1
 ... gm)') or @('(notinline g1 ... gm)'), and each @('gi') is defined by some
 @('defi').</p>

 <p>The only effect of the declarations is to provide advice to the host Lisp
 compiler.  The declarations are otherwise ignored by ACL2, so we mainly ignore
 them in the discussion below.</p>

 <p>The innermost @('flet')-binding of a function symbol, @('f'), above a call
 of @('f'), is the one that provides the definition of @('f') for that call.
 Note that @('flet') does not provide recursion.  Consider the following
 example.</p>

 @({
  ; Give a global definition of f:
  (defun f (x) (+ x 3))
  ; Evaluate an expression using a local binding of f:
  (flet ((f (x) (cons x (f (1+ x)))))
    (f 4))
 })

 <p>In the above term @('(cons x (f (1+ x)))'), @('f') refers to the global
 definition of @('f') above the @('flet') expression.  However, @('(f 4)')
 refers to the @('flet')-binding of @('f'), @('(f (x) (cons x (f x)))').  The
 result of the @('flet') expression is thus obtained by evaluating @('(f 4)')
 where @('(f 4)') is @('(cons 4 (f (1+ 4)))'), where the latter call of @('f')
 refers to the global definition; thus we have @('(cons 4 (f 5))'), which
 evaluates to @('(4 . 8)').</p>

 <p>Although @('flet') behaves in ACL2 essentially as it does in Common Lisp,
 ACL2 imposes the following restrictions and qualifications.</p>

 <ul>

 <li>Every @(tsee declare) form for a local definition (@('def1')
 through @('defk'), above) must be an @('ignore'), @('ignorable'), or @('type')
 expression.</li>

 <li>Each @('defi') must bind a different function symbol.</li>

 <li>Each @('defi') must bind a symbol that is a legal name for an ACL2
 function symbol.  In particular, the symbol may not be in the keyword package
 or the main Lisp package.  Moreover, the symbol may not be a built-in ACL2
 function or macro.</li>

 <li>Every variable occurring in the body of a @('defi') must be a formal
 parameter of that @('defi').  (This restriction is not enforced in Common
 Lisp.)</li>

 <li>If the @('flet')-binding @('defi') is in the body of a function @('f'),
 then the @(see stobj) inputs for @('defi') are implicitly those of its inputs
 that are declared @(see stobj) inputs of @('f').</li>

 </ul>

 <p>@('Flet') bindings are evaluated in parallel.  Consider the following
 example.</p>

 @({
  (defun f (x) x)
  (flet ((f (x) (cons x x))
         (g (x) (f x)))
    (g 3))
 })

 <p>The binding of @('g') refers to the global value of @('f'), not the
 @('flet')-binding of @('f').  Thus, the @('flet') expression evaluates to 3.
 Compare the @('flet') expression above to the following one, which instead
 evaluates to @('(3 . 3)').</p>

 @({
  (defun f (x) x)
  (flet ((f (x) (cons x x)))
    (flet ((g (x) (f x)))
      (g 3)))
 })

 <p>Under the hood, ACL2 translates @('flet') bindings to @(tsee lambda)
 expressions (see @(see term)), throwing away the @('inline') and
 @('notinline') declarations (if any).  The following example illustrates this
 point.</p>

 @({
  ACL2 !>:trans (flet ((f (x) (cons x x))
                       (g (x y) (+ x y)))
                  (declare (inline f))
                  (f (g 3 4)))

  ((LAMBDA (X) (CONS X X))
   ((LAMBDA (X Y) (BINARY-+ X Y)) '3 '4))

  => *

  ACL2 !>
 })

 <p>@('Flet') is part of Common Lisp.  See any Common Lisp documentation for
 more information.  We conclude by pointing out an important aspect of
 @('flet') shared by ACL2 and Common Lisp: The binding is lexical, not dynamic.
 That is, the @('flet') binding of a function symbol only applies to calls of
 that function symbol in the body of the @('flet'), not other calls made in the
 course of evaluation.  Consider the following example.  Suppose we define:</p>

 @({
  (defun f (x) x)
  (defun g (x) (f x))
  (defun h (x)
    (flet ((f (x) (cons x x)))
      (g x)))
 })

 <p>Then evaluation of @('(h 3)') results in @('3'), not in the @('cons') pair
 @('(3 . 3)'), because the @('flet') binding of @('f') only applies to calls of
 @('f') that appear in the body of that @('flet').  In this case, only @('g')
 is called in the body of that @('flet').</p>")

(defxdoc floor
  :parents (numbers acl2-built-ins)
  :short "Division returning an integer by truncating toward negative infinity"
  :long "@({
  Example Forms:
  ACL2 !>(floor 14 3)
  4
  ACL2 !>(floor -14 3)
  -5
  ACL2 !>(floor 14 -3)
  -5
  ACL2 !>(floor -14 -3)
  4
  ACL2 !>(floor -15 -3)
  5
 })

 <p>@('(Floor i j)') returns the result of taking the quotient of @('i') and
 @('j') and returning the greatest integer not exceeding that quotient.  For
 example, the quotient of @('-14') by @('3') is @('-4 2/3'), and the largest
 integer not exceeding that rational number is @('-5').</p>

 <p>The @(see guard) for @('(floor i j)') requires that @('i') and @('j') are
 rational (@(see real), in ACL2(r)) numbers and @('j') is non-zero.</p>

 <p>@('Floor') is a Common Lisp function.  See any Common Lisp documentation
 for more information.  However, note that unlike Common Lisp, the ACL2
 @('floor') function returns only a single value,</p>

 @(def floor)")

(defxdoc flush-compress
  :parents (arrays acl2-built-ins)
  :short "Flush the under-the-hood array for the given name"
  :long "@({
  Example Form:
  (flush-compress 'my-array)

  General Form:
  (flush-compress name)
 })

 <p>where @('name') is a symbol.</p>

 <p>Recall that @('(compress1 nm alist)') associates an under-the-hood raw Lisp
 one-dimensional array of name @('nm') with the given association list,
 @('alist'), while @('(compress2 nm alist)') is the analogous function for
 two-dimensional arrays; see @(see compress1) and see @(see compress2).  The
 only purpose of @('flush-compress'), which always returns @('nil'), is to
 remove the association of any under-the-hood array with the given name, thus
 eliminating slow array accesses (see @(see slow-array-warning)).  It is not
 necessary if the return values of @(tsee compress1) and @(tsee compress2) are
 always used as the ``current'' copy of the named array, and thus
 @('flush-compress') should rarely, if ever, be needed in user
 applications.</p>

 <p>Nevertheless, we provide the following contrived example to show how
 @('flush-compress') can be used to good effect.  Comments have been added to
 this log to provide explanation.</p>

 @({
  ACL2 !>(assign a (compress1 'demo
                              '((:header :dimensions (5)
                                         :maximum-length 15
                                         :default uninitialized
                                         :name demo)
                                (0 . zero)
                                (1 . one))))
   ((:HEADER :DIMENSIONS (5)
             :MAXIMUM-LENGTH
             15 :DEFAULT UNINITIALIZED :NAME DEMO)
    (0 . ZERO)
    (1 . ONE))
  ACL2 !>(aref1 'demo (@ a) 0)
  ZERO
  ; As expected, the above evaluation did not cause a slow array warning.  Now
  ; we associate a different under-the-hood array with the name 'demo.
  ACL2 !>(compress1 'demo
                    '((:header :dimensions (5)
                               :maximum-length 15
                               :default uninitialized
                               :name demo)
                      (0 . zero)))
  ((:HEADER :DIMENSIONS (5)
            :MAXIMUM-LENGTH
            15 :DEFAULT UNINITIALIZED :NAME DEMO)
   (0 . ZERO))
  ; The following array access produces a slow array warning because (@ a) is
  ; no longer associated under-the-hood with the array name 'demo.
  ACL2 !>(aref1 'demo (@ a) 0)

  **********************************************************
  Slow Array Access!  A call of AREF1 on an array named
  DEMO is being executed slowly.  See :DOC slow-array-warning
  **********************************************************

  ZERO
  ; Now we associate under-the-hood, with array name 'demo, an alist equal to
  ; (@ a).
  ACL2 !>(compress1 'demo
                    '((:header :dimensions (5)
                               :maximum-length 15
                               :default uninitialized
                               :name demo)
                      (0 . zero)
                      (1 . one)))
  ((:HEADER :DIMENSIONS (5)
            :MAXIMUM-LENGTH
            15 :DEFAULT UNINITIALIZED :NAME DEMO)
   (0 . ZERO)
   (1 . ONE))
  ; The following array access is still slow, because the under-the-hood array
  ; is merely associated with a copy of (@ a), not with the actual object
  ; (@ a).
  ACL2 !>(aref1 'demo (@ a) 0)

  **********************************************************
  Slow Array Access!  A call of AREF1 on an array named
  DEMO is being executed slowly.  See :DOC slow-array-warning
  **********************************************************

  ZERO
  ; So we might try to fix the problem by recompressing. But this doesn't
  ; work.  It would work, by the way, if we re-assign a:
  ; (assign a (compress1 'demo (@ a))).  That is why we usually will not need
  ; flush-compress.
  ACL2 !>(compress1 'demo (@ a))
  ((:HEADER :DIMENSIONS (5)
            :MAXIMUM-LENGTH
            15 :DEFAULT UNINITIALIZED :NAME DEMO)
   (0 . ZERO)
   (1 . ONE))
  ACL2 !>(aref1 'demo (@ a) 0)

  **********************************************************
  Slow Array Access!  A call of AREF1 on an array named
  DEMO is being executed slowly.  See :DOC slow-array-warning
  **********************************************************

  ZERO
  ; Finally, we eliminate the warning by calling flush-compress before we call
  ; compress1.  The call of flush-compress removes any under-the-hood
  ; association of an array with the name 'demo.  Then the subsequent call of
  ; compress1 associates the object (@ a) with that name.  (Technical point:
  ; compress1 always associates the indicated name with the value that it
  ; returns.  in this case, what compress1 returns is (@ a), because (@ a) is
  ; already, logically speaking, a compressed array1p (starts with a :header
  ; and the natural number keys are ordered).
  ACL2 !>(flush-compress 'demo)
  NIL
  ACL2 !>(compress1 'demo (@ a))
  ((:HEADER :DIMENSIONS (5)
            :MAXIMUM-LENGTH
            15 :DEFAULT UNINITIALIZED :NAME DEMO)
   (0 . ZERO)
   (1 . ONE))
  ACL2 !>(aref1 'demo (@ a) 0)
  ZERO
  ACL2 !>
 })

 @(def flush-compress)")

(defxdoc flush-hons-get-hash-table-link
  :parents (fast-alist-free acl2-built-ins)
  :short "Deprecated feature"
  :long "<p>Deprecated.  Alias for @(tsee fast-alist-free).</p>")

(defxdoc fms
  :parents (io acl2-built-ins)
  :short "@('(fms str alist co-channel state evisc) => state')"
  :long "<p>See @(see fmt) for further explanation, including documentation of
 the tilde-directives.</p>")

(defxdoc fms!
  :parents (io acl2-built-ins)
  :short "@('(fms! str alist co-channel state evisc) => state')"
  :long "<p>This function is nearly identical to @('fms'); see @(see fms).  The
 only difference is that @('fms') may insert backslash (\\) characters when
 forced to print past the right margin in order to make the output a bit
 clearer in that case.  Use @('fms!') instead if you want to be able to read
 the forms back in.</p>")

(defxdoc fmt
  :parents (io acl2-built-ins)
  :short "Formatted printing"
  :long "<p>ACL2 provides the functions @('fmt'), @(tsee fmt1), and @(tsee fms)
 as substitutes for Common Lisp's @('format') function.  Also see @(see fmt!),
 see @(see fmt1!), and see @(see fms!) for versions of these functions that
 write forms to files in a manner that allows them to be read, by avoiding
 using backslash (@('\\')) to break long lines.  There are also analogues of
 these functions that return a string without taking @(tsee state) as an
 argument; see @(see printing-to-strings).</p>

 <p>All three print a given string under an alist pairing character objects
 with values, interpreting certain ``tilde-directives'' in the string.
 @('Channel') must be a character output channel (e.g., @(tsee
 *standard-co*)).</p>

 @({
  General Forms:                                            result
  (fms string alist channel state evisc-tuple)         ; state
  (fmt string alist channel state evisc-tuple)         ; (mv col state)
  (fmt1 string alist column channel state evisc-tuple) ; (mv col state)
 })

 <p>@(tsee Fms) and @('fmt') print an initial newline to put @('channel') in
 column @('0'); @(tsee Fmt1) requires the current column as input.  Columns are
 numbered from @('0').  The current column is the column into which the next
 character will be printed.  (Thus, the current column number is also the
 number of @(see characters) printed since the last newline.)  The @('col')
 returned by @('fmt') and @(tsee fmt1) is the current column at the conclusion
 of the formatting.  @('Evisc-tuple') must be either @('nil') (meaning no
 abbreviations are used when objects are printed) or an ``evisceration tuple'';
 see @(see evisc-tuple).</p>

 <p>We list the tilde-directives below.  The notation is explained after the
 chart.</p>

 @({
  ~xx  pretty print vx (maybe after printing a newline)
  ~yx  pretty print vx starting in current column; end with newline
  ~Xxy like ~xx but use vy as the evisceration tuple
  ~Yxy like ~yx but use vy as the evisceration tuple
  ~@x  if vx is a string, \"str\",  recursively format \"str\"
       if vx is (\"str\" . a), recursively format \"str\" under a+
  ~#x~[...~/...~/ ... ~/...~] cases on vx
       ^    ^     ...   ^  if 0<=vx<=k, choose vxth alternative
       0    1     ...   k  if vx is a list of length 1, case 0; else 1
  ~*x  iterator: vx must be of the form
       (\"str0\" \"str1\" \"str2\" \"str3\" lst . a);
       if lst is initially empty, format \"str0\" under a+; otherwise,
       bind #\\* successively to the elements of lst and then
       recursively format \"stri\" under a+, where i=1 if there is one
       element left to process, i=2 if there are two left, and i=3
       otherwise.
  ~&x  print elements of vx with ~x, separated by commas and a
       final ``and''
  ~vx  print elements of vx with ~x, separated by commas and a
       final ``or''
  ~nx  if vx is a small positive integer, print it as a word, e.g.,
       seven;
       if vx is a singleton containing a small positive integer, print
         the corresponding ordinal as a word, e.g., seventh
  ~Nx  like ~nx but the word is capitalized, e.g., Seven or Seventh
  ~tx  tab out to column vx; newline first if at or past column vx
  ~cx  vx is (n . w), print integer n right justified in field of
       width w
  ~fx  print object vx flat over as many lines as necessary
  ~Fx  same as ~f, except that subsequent lines are indented to
       start one character to the right of the first character printed
  ~sx  if vx is a symbol, print vx, breaking on hyphens (unless the
       symbol would normally be printed with surrounding vertical bar
       characters (|), in which case print as with ~fx); if vx is a
       string, print the characters in it, breaking on hyphens; else
       vx is a number, to be printed using the current print-base and
       print-radix
  ~Sx  same as ~s, except that margins are ignored (hence no breaking on
       hyphens and no breaking when the column exceeds the value of
       the hard right-margin)
  ~    tilde space: print a space
  ~_x  print vx spaces
  ~
       tilde newline: skip following whitespace
  ~%   output a newline
  ~|   output a newline unless already on left margin
  ~~   print a tilde
  ~-   if close to right margin, output a hyphen and newline; else
       skip this char
 })

 <p>If @('x') is a character, then @('vx') is the value of @('#\\x') under the
 current alist.  Consider for example the discussion above for @('~y'),
 ``@('~yx pretty print vx')'', applied to the following expression: @('(fmt
 \"HELLO ~y7\" (list (cons #\\7 'world)) *standard-co* state nil)').  Then in
 this example: @('#\\x') is 7; and @('vx') is the value of character @('#\\7')
 under the given alist, which is the symbol, @('WORLD').  Thus, ACL2 will print
 @('HELLO WORLD').  When we say ``format @('str') under @('a+')'' we mean:
 process the given string under an alist obtained by appending @('a') to the
 current alist.  The following example illustrates how this works.</p>

 @({
  ACL2 !>(fms \"~@0\"
              (list (cons #\\0 (cons \"~x0 ~@1\" (list (cons #\\0  'abc))))
                    (cons #\\1 \"-- and now: ~x0 again~%\"))
              *standard-co* state nil)

  ABC -- and now: ABC again
  <state>
  ACL2 !>
 })

 <p>Note: @('~p'), @('~q'), @('~P'), and @('~Q') are also currently supported,
 but are deprecated.  These are respectively the same as @('~x'), @('~y'),
 @('~X'), and @('~Y'), except that their arguments are expected to be terms,
 preferably untranslated (user-level) terms, that could be printed using infix
 notation in certain environments.  Infix printing is not currently supported
 but may be if there is sufficient need for it.</p>

 <p>ACL2's formatting functions print to the indicated channel, keeping track
 of which column they are in.  @(tsee Fmt1) can be used if the caller knows
 which column the channel is in (i.e., how many @(see characters) have been
 printed since the last newline).  Otherwise, @('fmt') or @(tsee fms) must be
 used, both of which output a newline so as to establish the column position at
 @('0').  Unlike Common Lisp's @('format') routine, @('fmt') and its relatives
 break the output into lines so that, by default, an attempt is made to avoid
 printing past column @('77') (the value of constant
 @('*fmt-hard-right-margin-default*')), except when using @('~S').  See @(see
 set-fmt-hard-right-margin) for a discussion of how linebreaks are inserted and
 how to change the relevant default settings.</p>

 <p>The formatting functions scan the string from left to right, printing each
 successive character unless it is a tilde @('(~)').  Upon encountering tildes
 the formatters take action determined by the character or @(see characters)
 immediately following the tilde.  The typical tilde-directive is a group of
 three successive @(see characters) from the string being printed.  For
 example, @('~x0') is a 3 character @('tilde-directive').  The first character
 in a tilde-directive is always the tilde character itself.  The next character
 is called the ``command'' character.  The character after that is usually
 taken as the name of a ``format variable'' that is bound in the alist under
 which the string is being printed.  Format variables are, by necessity, @(see
 characters).  The objects actually printed by a tilde-directive are the
 objects obtained by looking up the command's format variables in the alist.
 Typical format variable names are @('0'), @('1'), @('2'), ..., @('9'), @('a'),
 @('b'), @('c'), etc., and if a tilde-directive uses the format variable
 @('0'), as in @('~x0'), then the character @('#\\0') must be bound in the
 alist.  Some tilde commands take no arguments and others take more than one,
 so some directives are of length two and others are longer.</p>

 <p>It should be noted that this use of @(see characters) in the string to
 denote arguments is another break from Common Lisp's @('format') routine.  In
 Common Lisp, the directives refer implicitly to the ``next item to be
 printed.''  But in ACL2 the directives name each item explicitly with our
 format variables.</p>

 <p>The following text contains examples that can be evaluated.  To make this
 process easier, we use a macro which is defined as part of ACL2 just for this
 @(see documentation).  The macro is named @('fmx') and it takes up to eleven
 arguments, the first of which is a format string, @('str'), and the others of
 which are taken as the values of format variables.  The variables used are
 @('#\\0') through @('#\\9').  The macro constructs an appropriate alist,
 @('a'), and then evaluates @('(fmt str a *standard-co* state nil)').</p>

 <p>Thus,</p>

 @({
  (fmx \"Here is v0, ~x0, and here is v1, ~x1.\"
       (cons 'value 0)
       (cons 'value 1))
 })

 <p>is just an abbreviation for</p>

 @({
  (fmt \"Here is v0, ~x0, and here is v1, ~x1.\"
       (list (cons #\\0 (cons 'value 0))
             (cons #\\1 (cons 'value 1)))
       *standard-co*
       state
       nil)
 })

 <p>which returns @('(mv 53 state)') after printing the line</p>

 @({
     Here is v0, (VALUE . 0), and here is v1, (VALUE . 1).
 })

 <p>We now devote special attention to three of the tilde-directives whose use
 is non-obvious.</p>

 <p><i>The Case Statement</i></p>

 <p>@('~#x') is essentially a ``case statement'' in the language of @('fmt').
 The proper form of the statement is</p>

 @({
  ~#x~[case-0~/case-1~/ ... ~/case-k~],
 })

 <p>where each of the @('case-i') is a format string.  In the most common use,
 the variable @('x') has an integer value, @('vx'), between @('0') and @('k'),
 inclusive.  The effect of formatting the directive is to format
 @('case-vx').</p>

 <p>For example</p>

 @({
  (fmx \"Go ~#0~[North~/East~/South~/West~].~%\" 1)
 })

 <p>will print ``Go East.'' followed by a newline and will return</p>

 <p>@('(mv 0 state)'), while if you change the @('1') above to @('3') (the
 maximum legal value), it will print ``Go West.''</p>

 <p>In order to make it easier to print such phrases as ``there are seven
 cases'' requiring agreement between subject and verb based on the number of
 elements of a list, the case statement allows its variable to take a list as
 its value and selects @('case-0') if the list has length @('1') and
 @('case-1') otherwise.</p>

 @({
  (let ((cases '(a b c)))
    (fmx \"There ~#0~[is ~n1 case~/are ~n1 cases~].\"
         cases
         (length cases)))
 })

 <p>will print ``There are three cases.'' but if you change the</p>

 <p>@(''(a b c)') above simply to @(''(a)') it will print ``There is one
 case.'' and if you change it to @('nil') it will print ``There are zero
 cases.''</p>

 <p><i>Indirection</i></p>

 <p>Roughly speaking, @('~@') will act as though the value of its argument is a
 format string and splice it into the current string at the current position.
 It is often used when the phrase to be printed must be computed.  For
 example,</p>

 @({
  (let ((ev 'DEFUN))
   (fmx \"~x0 is an event~@1.\"
        'foo
        (if (member-eq ev '(defun defstub encapsulate))
            \" that may introduce a function symbol\"
            \"\")))
 })

 <p>will print ``@('foo') is an event that may introduce a function symbol,''
 but if the value of @('ev') is changed from @(''')@(tsee defun) to
 @(''')@(tsee defthm), it prints ``@('foo') is an event.''  The @('~@')
 directive ``splices'' in the computed phrase (which might be empty).  Of
 course, this particular example could be done with the case statement</p>

 @({
  ~#1~[~/ that may introduce a function symbol~]
 })

 <p>where the value of @('#\\1') is appropriately computed to be @('0') or
 @('1').</p>

 <p>If the argument to @('~@') is a pair, it is taken to be a format string
 @(tsee cons)ed onto an alist, i.e., @('(\"str\" . a)'), and the alist, @('a'),
 is used to extend the current one before @('\"str\"') is recursively
 processed.  This feature of @('fmt') can be used to pass around ``phrases''
 that contain computed contextual information in @('a').  The most typical use
 is as ``error messages.''  For example, suppose you are writing a function
 which does not have access to @(tsee state) and so cannot print an error
 message.  It may nevertheless be necessary for it to signal an error to its
 caller, say by returning two results, the first of which is interpreted as an
 error message if non-@('nil').  Our convention is to use a @('~@') pair to
 represent such messages.  For example, the error value might be produced by
 the code:</p>

 @({
  (cons
    \"Error:  The instruction ~x0 is illegal when the stack is ~x1.~%\"
    (list (cons #\\0 (current-instruction st))
          (cons #\\1 (i-stack st))))
 })

 <p>If the @('current-instruction') and @('i-stack') (whatever they are) are
 @(''(popi 3)') and @(''(a b)') when the @(tsee cons) above is evaluated, then
 it produces</p>

 @({
  '(\"Error:  The instruction ~x0 is illegal when the stack is ~x1.~%\"
    (#\\0 POPI 3)
    (#\\1 A B))
 })

 <p>and if this pair is made the value of the @('fmt') variable @('0'), then
 @('~@0') will print</p>

 @({
     Error:  The instruction (POPI 3) is illegal when the stack is (A B).
 })

 <p>For example, evaluate</p>

 @({
  (let
   ((pair
    '(\"Error:  The instruction ~x0 is illegal when the stack is ~x1.~%\"
      (#\\0 POPI 3)
      (#\\1 A B))))
   (fmx \"~@0\" pair)).
 })

 <p>Thus, even though the function that produced the ``error'' could not print
 it, it could specify exactly what error message and data are to be
 printed.</p>

 <p>This example raises another issue.  Sometimes it is desirable to break
 lines in your format strings so as to make your source code more attractive.
 That is the purpose of the @('tilde-newline') directive.  The following code
 produces exactly the same output as described above.</p>

 @({
  (let ((pair '(\"Error:  The instruction ~x0 ~
                is illegal when the stack is ~
                ~x1.~%\"
                (#\\0 POPI 3)
                (#\\1 A B))))
   (fmx \"~@0\" pair)).
 })

 <p>Finally, observe that when @('~@0') extends the current alist, @('alist'),
 with the one, @('a'), in its argument, the bindings from @('a') are added to
 the front of @('alist'), overriding the current values of any shared
 variables.  This ensures that the variable values seen by the recursively
 processed string, @('\"str\"'), are those from @('a'), but if @('\"str\"')
 uses variables not bound in @('a'), their values are as specified in the
 original alist.  Intuitively, variables bound in @('a') are local to the
 processing of @('(\"str\" . a)') but @('\"str\"') may use ``global
 variables.''  The example above illustrates this because when the @('~@0') is
 processed, @('#\\0') is bound to the error message pair.  But when the
 @('~x0') in the error string is processed, @('#\\0') is bound to the illegal
 instruction.</p>

 <p><i>Iteration</i></p>

 <p>The @('~*') directive is used to process each element of a list.  For
 example,</p>

 @({
  (let ((lst '(a b c d e f g h))) ; a true-list whose elements we exhibit
   (fmx \"~*0\"
        `(\"Whoa!\"          ; what to print if there's nothing to print
          \"~x*!\"           ; how to print the last element
          \"~x* and \"       ; how to print the 2nd to last element
          \"~x*, \"          ; how to print all other elements
          ,lst)))          ; the list of elements to print
 })

 <p>will print ``@('A, B, C, D, E, F, G and H!')''.  Try this example with
 other true list values of @('lst'), such as @(''(a b)'), @(''(a)'), and
 @('nil').  The tilde-directives @('~&0') and @('~v0'), which take a true list
 argument and display its elements separated by commas and a final ``and'' or
 ``or,'' are implemented in terms of the more general @('~*').</p>

 <p>The @('~*') directive allows the 5-tuple to specify in its final @(tsee
 cdr) an alist with which to extend the current one before processing the
 individual elements.</p>

 <p>We often use @('~*') to print a series of phrases, separated by suitable
 punctuation, whitespace and noise words.  In such use, the @('~*') handles the
 separation of the phrases and each phrase is generally printed by @('~@').</p>

 <p>Here is a complex example.  In the @(tsee let*), below, we bind phrases to
 a list of @('~@') pairs and then we create a @('~*') 5-tuple to print out the
 conjunction of the phrases with a parenthetical ``finally!'' if the series is
 longer than 3.</p>

 @({
  (let* ((phrases
          (list (list \"simplifying with the replacement rules ~&0\"
                      (cons #\\0 '(rewrite-rule1
                                  rewrite-rule2
                                  rewrite-rule3)))
                (list \"destructor elimination using ~x0\"
                      (cons #\\0 'elim-rule))
                (list \"generalizing the terms ~&0\"
                      (cons #\\0 '((rev x) (app u v))))
                (list \"inducting on ~x0\"
                      (cons #\\0 'I))))
         (5-tuple
          (list
           \"magic\"                            ; no phrases
           \"~@*\"                              ; last phrase
           \"~@*, and~#f~[~/ (finally!)~] \"    ; second to last phrase
           \"~@*, \"                            ; other phrases
           phrases                            ; the phrases themselves
           (cons #\\f
                 (if (>(length phrases) 3) 1 0))))) ;print ``finally''?
    (fmx \"We did it by ~*0.\" 5-tuple))
 })

 <p>This @(tsee let*) prints</p>

 @({
     We did it by simplifying with the replacement rules REWRITE-RULE1,
     REWRITE-RULE2 and REWRITE-RULE3, destructor elimination using ELIM-
     RULE, generalizing the terms (REV X) and (APP U V), and (finally!)
     inducting on I.
 })

 <p>You might wish to try evaluating the @(tsee let*) after removing elements
 of phrases.</p>

 <p>Most of the output produced by ACL2 is produced via @('fmt') statements.
 Thus, inspection of the source code will yield many examples.  A complicated
 example is the code that explains the simplifier's work.  See @(':')@(tsee pc)
 @('simplify-clause-msg1').  An ad hoc example is provided by the function
 @('fmt-doc-example'), which takes two arguments: an arbitrary true list and
 @(tsee state).  To see how @('fmt-doc-example') works, @(':')@(tsee pe)
 @('fmt-doc-example').</p>

 @({
  (fmt-doc-example '(a b c d e f g h i j k l m n o p) state)
 })

 <p>will produce the output</p>

 @({
     Here is a true list:  (A B C D E F G H I J K L M N O P).  It has 16
     elements, the third of which is C.

     We could print each element in square brackets:
     ([A], [B], [C], [D], [E], [F], [G], [H], [I], [J], [K], [L], [M], [N],
     [almost there: O], [the end: P]).  And if we wished to itemize them
     into column 15 we could do it like this
     0123456789012345
         0 (zeroth) A
         1 (first)  B
         2 (second) C
         3 (third)  D
         4 (fourth) E
         5 (fifth)  F
         6 (sixth)  G
         7 (seventh)
                    H
         8 (eighth) I
         9 (ninth)  J
        10 (tenth)  K
        11 (eleventh)
                    L
        12 (twelfth)
                    M
        13 (thirteenth)
                    N
        14 (14th)   O
        15 (15th)   P
     End of example.
 })

 <p>and return @('(mv 15 state)').</p>

 <p>Finally, we should remind the reader that @('fmt') and its subfunctions,
 most importantly @('fmt0'), are written entirely in ACL2.  We make this
 comment for two reasons.  First, it illustrates the fact that quite low level
 code can be efficiently written in the language.  Second, it means that as a
 last resort for documentation purposes you can read the source code without
 changing languages.</p>")

(defxdoc fmt!
  :parents (io acl2-built-ins)
  :short "@('(fmt! str alist co-channel state evisc) => state')"
  :long "<p>This function is nearly identical to @('fmt'); see @(see fmt).  The
 only difference is that @('fmt') may insert backslash (\\) characters when
 forced to print past the right margin in order to make the output a bit
 clearer in that case.  Use @('fmt!') instead if you want to be able to read
 the forms back in.</p>")

(defxdoc fmt-to-comment-window
  :parents (io acl2-built-ins)
  :short "Print to the comment window"
  :long "<p>See @(see cw) for an introduction to the comment window and the
 usual way to print it.</p>

 <p>Function @('fmt-to-comment-window') is identical to @('fmt1') (see @(see
 fmt)), except that the channel is @(tsee *standard-co*) and the ACL2 @(tsee
 state) is neither an input nor an output.  An analogous function,
 @('fmt-to-comment-window!'), prints with @(tsee fmt!) instead of @(tsee fmt),
 in order to avoid insertion of backslash (\\) characters for margins; also see
 @(see cw!).  Note that even if you change the value of @(tsee ld) special
 @('standard-co') (see @(see standard-co)), @('fmt-to-comment-window') will
 print to @(tsee *standard-co*), which is the original value of @(tsee
 standard-co).</p>

 @({
  General Form:
  (fmt-to-comment-window fmt-string alist col evisc-tuple)
 })

 <p>where these arguments are as described for @(tsee fmt1); see @(see
 fmt).</p>")

(defxdoc fmt1
  :parents (io acl2-built-ins)
  :short "@('(fmt1 str alist col co-channel state evisc) => (mv col state)')"
  :long "<p>See @(see fmt) for further explanation, including documentation of
 the tilde-directives.</p>")

(defxdoc fmt1!
  :parents (io acl2-built-ins)
  :short "@('(fmt1! str alist col channel state evisc) => (mv col state)')"
  :long "<p>This function is nearly identical to @('fmt1'); see @(see fmt1).
 The only difference is that @('fmt1') may insert backslash (\\) characters
 when forced to print past the right margin in order to make the output a bit
 clearer in that case.  Use @('fmt1!') instead if you want to be able to read
 the forms back in.</p>")

(defxdoc forall
  :parents (defun-sk)
  :short "Universal quantifier"
  :long "<p>The symbol @('forall') (in the ACL2 package) represents universal
 quantification in the context of a @(tsee defun-sk) form.  See @(see defun-sk)
 and see @(see exists).</p>

 <p>See @(see quantifiers) for an example illustrating how the use of
 recursion, rather than explicit quantification with @(tsee defun-sk), may be
 preferable.</p>")

(defxdoc force
  :parents (rewrite linear type-prescription definition meta)
  :short "Identity function used to force a hypothesis"
  :long "<p>@('Force') is the identity function: @('(force x)') is equal to
 @('x').  However, for rules of many classes (see @(see rule-classes)), a
 hypothesis of the form @('(force term)') is given special treatment, as
 described below.  This treatment takes place for rule classes @(':')@(tsee
 rewrite), @(':')@(tsee linear), @(':')@(tsee type-prescription), @(':')@(tsee
 definition), @(':')@(tsee meta) (actually in that case, the result of
 evaluating the hypothesis metafunction call), and @(':')@(tsee
 forward-chaining).</p>

 <p>When a hypothesis of a conditional rule (of one of the classes listed
 above) has the form @('(force hyp)'), it is logically equivalent to @('hyp')
 but has a pragmatic effect.  In particular, when the rule is considered, the
 needed instance of the hypothesis, @('hyp''), may be assumed if the usual
 process fails to prove it or its negation.  In that situation, if the rule is
 eventually applied, then a special case is generated, requiring the system to
 prove that @('hyp'') is true in the current context.  The proofs of all such
 ``forced assumptions'' are, by default, delayed until the successful
 completion of the main goal.  See @(see forcing-round) and see @(see
 immediate-force-modep).</p>

 <p>Note that the only time that ACL2 gives special treatment to calls of
 @('force') is when it is considering the hypotheses of a conditional rule, as
 discussed above.  In particular, when the rewriter encounters a subterm of the
 goal currently being simplified, a call of @('force') is not treated
 specially.  For example, if you provide a @(':use') hint (see @(see hints))
 that replaces a goal @('G') by the goal</p>

 @({
 (implies (implies (and ... (force HYP) ...)
                   concl)
          G)
 })

 <p>then the rewriter will not give any special treatment to <tt>(force
 HYP)</tt>.  Instead, it will first rewrite @('HYP') to, say, @('HYP''); and
 then, using the fact that @('force') is the identity function, the rewriter
 will return @('HYP'') as the rewritten value for <tt>(force HYP)</tt>.</p>

 <p>Forcing is generally used on hypotheses that are always expected to be
 true, as is commonly the case for @(see guard)s of functions.  All the power
 of the theorem prover is brought to bear on a forced hypothesis and no
 backtracking is possible.  Forced goals can be attacked immediately (see @(see
 immediate-force-modep)) or in a subsequent forcing round (see @(see
 forcing-round)).  Also see @(see case-split) for a related utility.  If the
 @(':')@(tsee executable-counterpart) of the function @('force') is @(see
 disable)d, then no hypothesis is forced.  For more on enabling and disabling
 forcing, see @(see enable-forcing) and see @(see disable-forcing).</p>

 <p>It sometimes happens that a conditional rule is not applied because some
 hypothesis, @('hyp'), could not be relieved, even though the required instance
 of @('hyp'), @('hyp''), can be shown true in the context.  This happens when
 insufficient resources are brought to bear on @('hyp'') at the time we try to
 relieve it.  A sometimes desirable alternative behavior is for the system to
 assume @('hyp''), apply the rule, and to generate explicitly a special case to
 show that @('hyp'') is true in the context.  This is called ``forcing''
 @('hyp').  It can be arranged by restating the rule so that the offending
 hypothesis, @('hyp'), is embedded in a call of @('force'), as in @('(force
 hyp)').  By using the @(':')@(tsee corollary) field of the @(tsee
 rule-classes) entry, a hypothesis can be forced without changing the statement
 of the theorem from which the rule is derived.</p>

 <p>Technically, @('force') is just a function of one argument that returns
 that argument.  It is generally @(see enable)d and hence evaporates during
 simplification.  But its presence among the hypotheses of a conditional rule
 causes case splitting to occur if the hypothesis cannot be conventionally
 relieved.</p>

 <p>Since a forced hypothesis must be provable whenever the rule is otherwise
 applicable, forcing should be used only on hypotheses that are expected always
 to be true.</p>

 <p>A particularly common situation in which some hypotheses should be forced
 is in ``most general'' @(see type-prescription) lemmas.  If a single lemma
 describes the ``expected'' type of a function, for all ``expected'' arguments,
 then it is probably a good idea to force the hypotheses of the lemma.  Thus,
 every time a term involving the function arises, the term will be given the
 expected type and its arguments will be required to be of the expected type.
 In applying this advice it might be wise to avoid forcing those hypotheses
 that are in fact just type predicates on the arguments, since the routine that
 applies @(see type-prescription) lemmas has fairly thorough knowledge of the
 types of all terms.</p>

 <p>@('Force') can have the additional benefit of causing the ACL2 typing
 mechanism to interact with the ACL2 rewriter to establish the hypotheses of
 @(see type-prescription) rules.  To understand this remark, think of the ACL2
 type reasoning system as a rather primitive rule-based theorem prover for
 questions about Common Lisp types, e.g., ``does this expression produce a
 @(tsee consp)?''  ``does this expression produce some kind of ACL2 number,
 e.g., an @(tsee integerp), a @(tsee rationalp), or a @(tsee
 complex-rationalp)?'' etc.  It is driven by @(see type-prescription) rules.
 To relieve the hypotheses of such rules, the type system recursively invokes
 itself.  This can be done for any hypothesis, whether it is ``type-like'' or
 not, since any proposition, @('p'), can be phrased as the type-like question
 ``does @('p') produce an object of type @('nil')?''  However, as you might
 expect, the type system is not very good at establishing hypotheses that are
 not type-like, unless they happen to be assumed explicitly in the context in
 which the question is posed, e.g., ``If @('p') produces a @(tsee consp) then
 does @('p') produce @('nil')?''  If type reasoning alone is insufficient to
 prove some instance of a hypothesis, then the instance will not be proved by
 the type system and a @(see type-prescription) rule with that hypothesis will
 be inapplicable in that case.  But by embedding such hypotheses in @('force')
 expressions you can effectively cause the type system to ``punt'' them to the
 rest of the theorem prover.  Of course, as already noted, this should only be
 done on hypotheses that are ``always true.''  In particular, if rewriting is
 required to establish some hypothesis of a @(see type-prescription) rule, then
 the rule will be found inapplicable because the hypothesis will not be
 established by type reasoning alone.</p>

 <p>The ACL2 rewriter uses the type reasoning system as a subsystem.  It is
 therefore possible that the type system will force a hypothesis that the
 rewriter could establish.  Before a forced hypothesis is reported out of the
 rewriter, we try to establish it by rewriting.</p>

 <p>This makes the following surprising behavior possible: A @(see
 type-prescription) rule fails to apply because some true hypothesis is not
 being relieved.  The user changes the rule so as to <b>force</b> the
 hypothesis.  The system then applies the rule but reports no forcing.  How can
 this happen?  The type system ``punted'' the forced hypothesis to the
 rewriter, which established it.</p>

 <p>Finally, we should mention that the rewriter is never willing to force when
 there is an @(tsee if) term present in the goal being simplified.  Since
 @(tsee and) terms and @(tsee or) terms are merely abbreviations for @(tsee if)
 terms, they also prevent forcing.  Note that @(tsee if) terms are ultimately
 eliminated using the ordinary flow of the proof (but see @(see
 set-case-split-limitations)), allowing @('force') ultimately to function as
 intended.  Moreover, forcing can be disabled, as described above; also see
 @(see disable-forcing).</p>

 @(def force)")

(defxdoc forcing-round
  :parents (force)
  :short "A section of a proof dealing with @(see force)d assumptions"
  :long "<p>If ACL2 ``@(see force)s'' some hypothesis of some rule to be true,
 it is obliged later to prove the hypothesis.  See @(see force).  ACL2 delays
 the consideration of @(see force)d hypotheses until the main goal has been
 proved.  It then undertakes a new round of proofs in which the main goal is
 essentially the conjunction of all hypotheses @(see force)d in the preceding
 proof.  Call this round of proofs the ``Forcing Round.''  Additional
 hypotheses may be @(see force)d by the proofs in the Forcing Round.  The
 attempt to prove these hypotheses is delayed until the Forcing Round has been
 successfully completed.  Then a new Forcing Round is undertaken to prove the
 recently @(see force)d hypotheses and this continues until no hypotheses are
 @(see force)d.  Thus, there is a succession of Forcing Rounds.</p>

 <p>The Forcing Rounds are enumerated starting from 1.  The Goals and Subgoals
 of a Forcing Round are printed with the round's number displayed in square
 brackets.  Thus, @('\"[1]Subgoal 1.3\"') means that the goal in question is
 Subgoal 1.3 of the 1st forcing round.  To supply a hint for use in the proof
 of that subgoal, you should use the goal specifier @('\"[1]Subgoal 1.3\"').
 See @(see goal-spec).</p>

 <p>When a round is successfully completed &mdash; and for these purposes you
 may think of the proof of the main goal as being the 0th forcing round &mdash;
 the system collects all of the assumptions @(see force)d by the just-completed
 round.  Here, an assumption should be thought of as an implication,
 @('(implies context hyp)'), where context describes the context in which hyp
 was assumed true.  Before undertaking the proofs of these assumptions, we try
 to ``clean them up'' in an effort to reduce the amount of work required.  This
 is often possible because the @(see force)d assumptions are generated by the
 same rule being applied repeatedly in a given context.</p>

 <p>By delaying and collecting the @('forced') assumptions until the completion
 of the ``main goal'' we gain two advantages.  First, the user gets
 confirmation that the ``gist'' of the proof is complete and that all that
 remains are ``technical details.''  Second, by delaying the proofs of the
 @(see force)d assumptions ACL2 can undertake the proof of each assumption only
 once, no matter how many times it was @(see force)d in the main goal.</p>

 <p>In order to indicate which proof steps of the previous round were
 responsible for which @(see force)d assumptions, we print a sentence
 explaining the origins of each newly @(see force)d goal.  For example,</p>

 @({
  [1]Subgoal 1, below, will focus on
  (GOOD-INPUTP (XTRANS I)),
  which was forced in
   Subgoal 14, above,
    by applying (:REWRITE PRED-CRUNCHER) to
    (PRED (XTRANS I) I),
   and
   Subgoal 28, above,
    by applying (:REWRITE PRED-CRUNCHER) to
    (PRED (XTRANS I) I).
 })

 <p>In this entry, ``[1]Subgoal 1'' is the name of a goal which will be proved
 in the next forcing round.  On the next line we display the @(see force)d
 hypothesis, call it @('x'), which is @('(good-inputp (xtrans i))') in this
 example.  This term will be the conclusion of the new subgoal.  Since the new
 subgoal will be printed in its entirety when its proof is undertaken, we do
 not here exhibit the context in which @('x') was @(see force)d.  The sentence
 then lists (possibly a succession of) a goal name from the just-completed
 round and some step in the proof of that goal that @(see force)d @('x').  In
 the example above we see that Subgoals 14 and 28 of the just-completed proof
 @(see force)d @('(good-inputp (xtrans i))') by applying @('(:rewrite
 pred-cruncher)') to the term @('(pred (xtrans i) i)').</p>

 <p>If one were to inspect the theorem prover's description of the proof steps
 applied to Subgoals 14 and 28 one would find the word ``@(see force)d'' (or
 sometimes ``forcibly'') occurring in the commentary.  Whenever you see that
 word in the output, you know you will get a subsequent forcing round to deal
 with the hypotheses @(see force)d.  Similarly, if at the beginning of a
 forcing round a @(see rune) is blamed for causing a @(see force) in some
 subgoal, inspection of the commentary for that subgoal will reveal the word
 ``@(see force)d'' after the rule name blamed.</p>

 <p>Most @(see force)d hypotheses come from within the prover's simplifier.
 When the simplifier encounters a hypothesis of the form @('(force hyp)') it
 first attempts to establish it by rewriting @('hyp') to, say, @('hyp'').  If
 the truth or falsity of @('hyp'') is known, forcing is not required.
 Otherwise, the simplifier actually @(see force)s @('hyp'').  That is, the
 @('x') mentioned above is @('hyp''), not @('hyp'), when the @(see force)d
 subgoal was generated by the simplifier.</p>

 <p>Once the system has printed out the origins of the newly @(see force)d
 goals, it proceeds to the next forcing round, where those goals are
 individually displayed and attacked.</p>

 <p>At the beginning of a forcing round, the @(see enable)d structure defaults
 to the global @(see enable)d structure.  For example, suppose some @(see
 rune), @('rune'), is globally @(see enable)d.  Suppose in some event you @(see
 disable) the @(see rune) at @('\"Goal\"') and successfully prove the goal but
 @(see force) @('\"[1]Goal\"').  Then during the proof of @('\"[1]Goal\"'),
 @(see rune) is @(see enable)d ``again.''  The right way to think about this is
 that the @(see rune) is ``still'' @(see enable)d.  That is, it is @(see
 enable)d globally and each forcing round resumes with the global @(see
 enable)d structure.</p>")

(defxdoc formula
  :parents (history world acl2-built-ins)
  :short "The formula of a name or @(see rune)"
  :long "<p>The ACL2 system function, @('formula'), returns the @(see term)
 associated with a given @(see rune) or symbolic name, returning @('nil') if
 there is no such term.  Note that a non-@('nil') result will be an ACL2
 ``translated'' term (see @(see term)).  Most ACL2 users probably will have no
 reason to know about this function.  But here we document this function for
 those who write system-level tools, since they might find this interface to
 the ACL2 logical @(see world) to be useful.</p>

 <p>When ACL2 is given a @(':use') or @(':by') hint, it looks for the @(see
 term) stored in the ACL2 logical @(see world) that is associated with the name
 given in the hint, which is a symbol or a @(see rune).  (See (@see
 lemma-instance).)  The utility used to find that term is @('formula'), which
 ACL2 invokes as follows.</p>

 @({
 (formula x t wrld)   ; for :use hints
 (formula x nil wrld) ; for :by hints
 })

 <p>The second argument can affect whether or not to use a normalized version
 of the term (in particular, a definition body) associated with @('x'); see
 @(see normalize).  The value is @('t') for @(':use') @(see hints) because
 normalizing a term simplifies it, which is often desirable.  But for a
 @(':by') hint, the non-normalized version of the term is used in order to
 increase the chance that the necessary subsumption test will succeed.  Even if
 the second argument is @('t'), normalization might not take place.  In the
 unlikely case that you need to know more precisely the effect of supplying
 @('t'), see the source code for @('formula').</p>

 <p>Here are some examples.  Note that @('(w state)') returns the current ACL2
 logical @(see world).  First let us submit a few @(see events).</p>

 @({
 (defun f1 (x) (cons 3 x))
 (defun f2 (x y) (implies x y))
 (defthm one-rule
   (and (equal (* 2 y) (+ y y))
        (equal (* 3 y) (+ y y y))))
 (defthm two-rules
   t
   :rule-classes ((:rewrite :corollary (equal (* 2 y) (+ y y)))
                  (:rewrite :corollary (equal (* 3 y) (+ y y y)))))
 })

 <p>Then:</p>

 @({
 ACL2 !>(formula 'f1 nil (w state))
 (EQUAL (F1 X) (CONS '3 X))
 ACL2 !>(formula 'f1 t (w state))
 (EQUAL (F1 X) (CONS '3 X))
 ACL2 !>(formula 'f2 nil (w state))
 (EQUAL (F2 X Y) (IMPLIES X Y))
 ACL2 !>(formula 'f2 t (w state))
 (EQUAL (F2 X Y)
        (IF X (IF Y 'T 'NIL) 'T))
 ACL2 !>(formula 'one-rule nil (w state))
 (IF (EQUAL (BINARY-* '2 Y) (BINARY-+ Y Y))
     (EQUAL (BINARY-* '3 Y)
            (BINARY-+ Y (BINARY-+ Y Y)))
     'NIL)
 ACL2 !>(equal (formula 'one-rule nil (w state)) (formula 'one-rule t (w state)))
 T
 ACL2 !>(formula 'two-rules nil (w state))
 'T
 ACL2 !>(formula 'two-rules t (w state))
 'T
 ACL2 !>(formula '(:rewrite two-rules . 1) nil (w state))
 (EQUAL (BINARY-* '2 Y) (BINARY-+ Y Y))
 ACL2 !>(formula '(:rewrite two-rules . 2) nil (w state))
 (EQUAL (BINARY-* '3 Y)
        (BINARY-+ Y (BINARY-+ Y Y)))
 ACL2 !>(formula 'no-such-rule nil (w state))
 NIL
 ACL2 !>
 })")

(defxdoc forward-chaining
  :parents (rule-classes)
  :short "Make a rule to forward chain when a certain trigger arises"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 @({
  Examples:

  (defthm p-and-r-forward           ; When (p a) appears in a formula to be
   (implies (and (p x) (r x))       ; simplified, try to establish (p a) and
            (q (f x)))              ; (r a) and, if successful, add (q (f a))
   :rule-classes :forward-chaining) ; to the known assumptions.

  (defthm p-and-r-forward           ; as above with most defaults filled in
    (implies (and (p x) (r x))
             (q (f x)))
    :rule-classes ((:forward-chaining :trigger-terms ((p x))
                                      :corollary (implies (and (p x) (r x))
                                                          (q (f x)))
                                      :match-free :all)))
 })

 <p>To specify the triggering terms provide a non-empty list of terms as the
 value of the @(':trigger-terms') field of the rule class object.</p>

 @({
  General Form:
  Any theorem, provided an acceptable triggering term exists.
 })

 <p>The structure of this documentation is as follows.  First we give a brief
 overview of forward chaining and contrast it to backchaining (rewriting).
 Then we lay out the syntactic restrictions on @(':forward-chaining') rules.
 Then we give more details about the process and point to a tool to assist you
 in debugging your @(':forward-chaining') rules.</p>

 <p><i>Overview and When to Use Forward Chaining</i></p>

 <p>Forward chaining is performed as part of the simplification process: before
 the goal is rewritten a <i>context</i> is established.  The context tells the
 theorem prover what may be assumed during rewriting, in particular, to
 establish hypotheses of rewrite rules.  Forward chaining is used to extend the
 context before rewriting begins.  For example, the @(':forward-chaining') rule
 @('(implies (p x) (p1 x))') would add @('(p1 A)') to the context, where @('A')
 is some term, if @('(p A)') is already in the context.</p>

 <p>Forward chaining and backchaining are duals.  If a rewrite rule requires
 that @('(p1 A)') be established and @('(p A)') is known, it could be done
 either by making @('(implies (p x) (p1 x))') a @(':forward-chaining') rule or
 a @(':rewrite') rule.  Which should you choose?</p>

 <p>As a rule of thumb, if a conclusion like @('(p1 A)') is expected to be
 widely needed, it is better to derive it via forward chaining because then it
 is available ``for free'' during the rewriting after paying the one-time cost
 of forward chaining.  Alternatively, if @('(p1 A)') is a rather special
 hypothesis of key importance to only a few rewrite rules, it is best to derive
 it only when needed.  Thus forward chaining is pro-active and backward
 chaining (rewriting) is reactive.</p>

 <p><i>Syntactic Restrictions</i></p>

 <p>Forward chaining rules are generated from the corollary term (see @(see
 rule-classes)) as follows.  First, every @(tsee let) expression is expanded
 away (hence, so is every @(tsee let*) and @(tsee lambda) expression), and
 trivial ``guard holders'' are removed; see @(see guard-holders).  If the
 resulting term has the form @('(implies hyp concl)'), then @('concl') is
 treated as a conjunction, with one forward chaining rule with hypothesis
 @('hyp') created for each conjunct.  In the other case, where the corollary
 term is not an @(tsee implies), we process it as we process the conclusion in
 the first case.</p>

 <p>Note that unlike rewrite rules, a nested implication is not folded into a
 single implication.  Consider for example the following term.</p>

 @({
  (implies (p1 x)
           (implies (p2 x)
                    (p3 x)))
 })

 <p>Although this term is parsed for a rewrite rule as @('(implies (and (p1 x)
 (p2 x)) (p3 x))'), that is not the case when this term is parsed for a
 forward-chaining rule, in which case @('(p1 x)') is treated as the hypothesis
 and @('(implies (p2 x) (p3 x))') is treated as the conclusion.</p>

 <p>The @(':trigger-terms') field of a @(':forward-chaining') rule class object
 should be a non-empty list of terms, if provided, and should have certain
 properties described below.  If the @(':trigger-terms') field is not provided,
 it defaults to the singleton list containing the ``atom'' of the first
 hypothesis of the formula.  (The atom of @('(not x)') is @('x'); the atom of
 any other term is the term itself.)  If there are no hypotheses and no
 @(':trigger-terms') were provided, an error is caused.</p>

 <p>A triggering term is acceptable if it is not a variable, a quoted constant,
 a lambda application, a @(tsee let)- (or @(tsee let*)-) expression, or a
 @(tsee not)-expression, and every variable symbol in the conclusion of the
 theorem either occurs in the hypotheses or occurs in the trigger.</p>

 <p><i>More Details about Forward Chaining</i></p>

 <p>@(':Forward-chaining') rules are used by the simplifier <i>before</i> it
 begins to rewrite the literals of the goal.  (Forward chaining is thus carried
 out from scratch for each goal.)  If any term in the goal is an instance of a
 trigger of some forward chaining rule, we try to establish the hypotheses of
 that forward chaining theorem (from the negation of the goal).  To relieve a
 hypothesis we only use type reasoning, evaluation of ground terms, and
 presence among our known assumptions.  We do not use rewriting.  So-called
 free variables in hypotheses are treated specially; see @(see free-variables).
 If all hypotheses are relieved, and certain heuristics approve of the newly
 derived conclusion, we add the instantiated conclusion to our known
 assumptions.  Since this might introduce new terms into the assumptions,
 forward chaining is repeated.  Heuristic approval of each new addition is
 necessary to avoid infinite looping as would happen with the rule @('(implies
 (p x) (p (f x)))'), which might otherwise forward chain from @('(p A)') to
 @('(p (f A))') to @('(p (f (f A)))'), etc.</p>

 <p><i>Caution</i>.  Forward chaining does not actually add terms to the goals
 displayed during proof attempts.  Instead, it extends an associated
 <i>context</i>, called ``assumptions'' in the preceding paragraph, that ACL2
 builds from the goal currently being proved.  (For insiders: forward chaining
 extends the @(tsee type-alist).)  The context starts out with ``obvious''
 consequences of the negation of the goal.  For example, if the goal is</p>

 @({
  (implies (and (p A) (q (f A)))
           (c A))
 })

 <p>then the context notes that @('(p A)') and @('(q (f A))') are non-@('nil')
 and @('(c A)') is @('nil').  Forward chaining is then used to expand the
 context.  For example, if a forward chaining rule has @('(f x)') as a trigger
 term and has body @('(implies (p x) (r (f x)))'), then the context is extended
 by binding @('(r (f A))') to non-@('nil'), provided the heuristics approve of
 this extension.  Note however that since @('(r (f A))') is put into the
 context, not the goal, you will not see it in the goal formula.  Furthermore,
 the assumption added to the context is just the instantiation of the
 conclusion of the rule, with no simplification or rewriting applied.  Thus,
 for example, if it contains an enabled non-recursive function symbol it is
 unlikely ever to match a (rewritten) term arising during subsequent
 simplification of the goal.</p>

 <p>However, forward-chaining does support the linear arithmetic reasoning
 package.  For example, suppose that forward-chaining puts @('(< (f x) (g x))')
 into the context.  Then this inequality also goes into the linear arithmetic
 database, together with suitable instances of linear lemmas whose trigger term
 is a call of @('g').  See @(see linear).</p>

 <p>Debugging @(':forward-chaining') rules can be difficult since their effects
 are not directly visible on the goal being simplified.  Tools are available to
 help you discover what forward chaining has occurred see @(see
 forward-chaining-reports).</p>")

(defxdoc forward-chaining-reports
  :parents (forward-chaining debugging)
  :short "To see reports about the forward chaining process"
  :long "<p>Debugging forward-chaining rules can be hard because their effects
 are not directly visible on the goal.  In this documentation we tell you how
 to get reports on the forward chaining activity occurring in your proof
 attempts.  This documentation is written in several parts.  The first part is
 an introduction for the first-time user of forward chaining reports.  The next
 two parts describe how to read reports.  The last part describes how to
 monitor forward chaining activity only for selected runes, etc.  We recommend
 the new user of these reports read everything!</p>

 <p><i>A Quick Introduction to Forward Chaining Reports</i></p>

 <p>Caution: The reporting mechanism maintains some state, and if you have
 already used forward chaining reporting in a session, the directions below may
 not work as advertised!  To return to the default forward chaining reporting
 state, execute this form at the top level:</p>

 @({
  (reset-fc-reporting)
 })

 <p>You can get a report about all forward chaining activity in subsequent
 proofs by doing:</p>

 @({
  (set-fc-criteria t)
 })

 <p>Options will be discussed later that allow you to monitor the activity
 caused by particular @(':forward-chaining') rules or terms.</p>

 <p>Then do a proof that is expected to cause some forward chaining.  In the
 proof output you will see lines like this:</p>

 @({
  (Forward Chaining on behalf of PREPROCESS-CLAUSE:  (FC-Report 1))
 })

 <p>This is the only difference you should see in the proof output.</p>

 <p>After the proof attempt has terminated, you can execute:</p>

 @({
  (fc-report k)
 })

 <p>for any @('k') printed during the immediately preceding proof attempt.
 That will print a much longer report describing the activity that occurred
 during the @('k')th use of forward chaining in that proof attempt.</p>

 <p>If you want to see these reports in real time (embedded in the proof
 output), do this before invoking the prover:</p>

 @({
  (set-fc-report-on-the-fly t)
 })

 <p>Collecting the data used to generate these reports slows down the prover.
 If you no longer wish to see such reports, do</p>

 @({
  (set-fc-criteria nil)
 })

 <p><i>How To Read FC Reports</i></p>

 <p>The report printed by @('(fc-report k)') is of the form:</p>

 <code>
  Forward Chaining Report <i>k</i>:
  Caller: <i>token</i>
  Clause: (<i>lit1</i> <i>lit2</i> ... <i>litn</i>)
  Number of Rounds: <i>m</i>
  Contradictionp: <i>bool</i>
  Activations: (<i>act1</i> <i>act2</i> ...)
  </code>

 <p>This report means that the <i>k</i>th use of forward chaining in the most
 recent proof attempt was done on behalf of <i>token</i> (see below).  The
 initial context (set of assumptions) consisted of the negations of the
 literals listed in the clause shown and the initial candidate trigger terms
 are all those appearing in that clause.  This invocation of forward chaining
 proceeded to do <i>m</i> rounds of successive extensions of the initial
 context and ultimately either reached a contradiction (<i>bool</i> = @('T'))
 or returned an extended context (<i>bool</i> = @('NIL')).  Note that reaching
 a contradiction from the negations of all the literals in a clause is ``good''
 because it means the clause is true.  The report concludes with the final
 status of all the forward chaining rules fired during the process.  We explain
 how to read one of these activation reports in the next section.</p>

 <p>Forward chaining is done on behalf of many proof techniques in the system.
 Each is associated with a <i>token</i>.  The main proof technique that uses
 forward chaining is @('SIMPLIFY-CLAUSE').  This is the call of forward
 chaining that sets up the context used by the rewriter to relieve hypotheses
 during backchaining.  Another common caller of forward chaining is
 @('PREPROCESS-CLAUSE'), the first process in the ACL2 waterfall (see @(see
 hints-and-the-waterfall)).  Forward chaining often proves ``near
 propositional'' goals (those depending just on boolean implications between
 basic predicates).  Other tokens you may see include @('INDUCT'), which uses
 forward chaining to set up a context for applying @(':')@(tsee induction)
 rules, and the definitional principle (and related utilities such as @(tsee
 verify-termination) and @(tsee verify-guards)) which uses forward chaining
 during the construction of both measure conjectures and guard conjectures.
 When used this way, the <i>token</i> is @('defun-or-guard-verification').</p>

 <p><i>How to Read Activation Reports</i></p>

 <p>The forward chaining report concludes with a list of activation
 reports.</p>

 <code>
 Activations: (<i>act1</i> <i>act2</i> ...)
 </code>

 <p>Each <i>acti</i> is of the form:</p>

 <code>
 (<i>rune</i>
  (:TRIGGER <i>inst-trig</i>)
  ((:UNIFY-SUBST <i>subst</i>)
   (:DISPOSITION <i>outcome-part1</i> <i>outcome-part2</i> <i>inst-term</i>))
  ...)
 </code>

 <p>where the @('...') indicates that the rest of the report consists of more
 of those tuples listing a @(':UNIFY-SUBST') and @(':DISPOSITION').  We call
 each tuple a <i>disposition</i> of the activation and each disposition
 describes a substitution <i>subst</i> identifying the final instantiation of
 the rule and how the activation fared.  Suppose there are <i>n</i>
 dispositions.  (If the rule in question contains no free variables, <i>n</i>
 will be 1.)</p>

 <p>This activation report means that during the forward chaining process in
 question, the @(':')@(tsee forward-chaining) @(see rune) <i>rune</i> was fired
 due to the presence in the evolving context of the trigger term
 <i>inst-trig</i>.  (Note that <i>inst-trig</i> is an instantiation of the
 trigger term of the named rule.  That is, the variable symbols you see in
 <i>inst-trig</i> are those of the clause printed in the forward chaining
 report.)  The activation of <i>rune</i> by <i>inst-trig</i> proceeded to split
 <i>n</i> ways as different choices were made for the @(see free-variables)
 occurring among the hypotheses.  Each of those <i>n</i> choices gave rise to a
 different substitution <i>subst</i>, and each succeeded or failed as described
 by the corresponding @(':DISPOSITION').</p>

 <p>The @(':DISPOSITION') of an activation is described in three parts,
 <i>outcome-part1</i>, <i>outcome-part2</i>, and <i>inst-term</i>.
 <i>Outcome-part1</i> is either @('SUCCESS') or @('BLOCKED'), meaning that the
 instance given by <i>subst</i> either succeeded in the sense that all of its
 instantiated hypotheses were found in the context, or failed because some
 instantiated hypothesis was not found.</p>

 <p>If @('outcome-part1') is @('SUCCESS') then <i>inst-term</i> is the
 instantiated conclusion produced by the rule.  <i>Outcome-part2</i> is
 @('APPROVED') if the instantiated conclusion was acceptable to our heuristics
 designed to prevent looping and not already known in the evolving context.
 <i>Outcome-part2</i> is @('REJECTED') if the instantiated conclusion was not
 approved by our heuristics.  <i>Outcome-part2</i> is @('REDUNDANT') if the
 instantiated conclusion was approved by the heuristics but already known true
 in the current evolving context.  If @('APPROVED'), the truth of the
 instantiated conclusion is added to the evolving context.  Otherwise, it is
 not.</p>

 <p>If @('outcome-part1') is @('BLOCKED') then @('outcome-part2') is one of
 three possible things: @('FALSE'), in which case <i>inst-term</i> is an
 instantiated hypothesis of the rule that is assumed false in the current
 context, @('UNRELIEVED-HYP'), in which case <i>inst-term</i> is an
 instantiated hypothesis whose truth value is not determined by the context, or
 @('UNRELIEVED-HYP-FREE'), in which case <i>inst-term</i> is an oddly
 instantiated hypothesis whose truth value is not determined by the context and
 which also contains free variables.  In the last case, the ``odd''
 instantiation was by the substitution <i>subst</i> but extended so that free
 variables in the hypothesis are renamed to start with the prefix
 @('UNBOUND-FREE-') to draw your attention to them.</p>

 <p>Note: All of the terms printed in the report are instantiated with the
 relevant unifying substitution (possibly extended to bind free variables).</p>

 <p><i>Specifying the Tracking Criteria</i></p>

 <p>During a proof attempt, the forward chaining module stores information
 about the activations satisfying certain criteria.  The <i>criteria</i> is a
 list of triples.  Each triple consists of a forward chaining rune, an
 instantiated trigger term, and an instantiated conclusion to watch for.
 However, any or all of the components of such a triple may be @('t') and that
 is given special significance.</p>

 <p>An activation @('satisfies') a criteria if it satisfies at least one of the
 triples.  An activation satisfies a triple if it satisfies all three of the
 components.  Every activation satisfies the component @('t').  An activation
 satisfies a rune if the activation describes a firing of the named rule.  An
 activation satisfies an instantiated trigger term if the activation was
 created by that trigger being present in the context.  An activation satisfies
 an instantiated conclusion if the activation <i>could</i> produce the
 instantiated conclusion (with the right choice of any free variables).</p>

 <p>Thus, the criteria is interpreted as a disjunction of conjunctions, making
 it possible to track a specific set of runes, triggers, and conclusions.</p>

 <p>For example, here is a triple that might appear in the criteria:</p>

 @({
  ((:FORWARD-CHAINING ALISTP-FORWARD-TO-TRUE-LISTP)
   t
   t).
 })

 <p>This triple would cause every activation of the given rule to be tracked.
 However, the triple</p>

 @({
  ((:FORWARD-CHAINING ALISTP-FORWARD-TO-TRUE-LISTP)
   (ALISTP (MAKE-BINDINGS VARS (TOP-N (OP1 INST) (STACK S))))
   t)
 })

 <p>would only track activations of that rule fired by the specific term shown
 as the second element of the triple.  Furthermore</p>

 @({
  (t
   (ALISTP (MAKE-BINDINGS VARS (TOP-N (OP1 INST) (STACK S))))
   t)
 })

 <p>would track any forward chaining rule triggered by that term, and</p>

 @({
  (t
   t
   (TRUE-LISTP (MAKE-BINDINGS VARS (TOP-N (OP1 INST) (STACK S)))))
 })

 <p>would track any rule fired by any trigger that might lead to the specific
 term given as the third component above.</p>

 <p>Note: The condition on how an activation satisfies an instantiated
 conclusion is a little subtle.  Consider the activation of the forward
 chaining rule</p>

 @({
  (implies (and (symbol-listp x)
                (equal (len x) (len y)))
           (true-listp (make-bindings x y)))
 })

 <p>triggered by @('(SYMBOL-LISTP VARS)') arising in the current context.  This
 activation <i>could</i> produce the specific conclusion shown in the last
 triple above, if it just happened that @('(TOP-N (OP1 INST) (STACK S))') were
 chosen as the binding of the free variable @('y').  Thus, the activation of
 this rule triggered by @('(SYMBOL-LISTP VARS)') satisfies the last triple
 above.</p>

 <p>Observe that the triple</p>

 @({
  (t t t)
 })

 <p>is satisfied by every activation of any rule by any trigger term producing
 any conclusion.</p>

 <p>The function @('set-fc-criteria') sets the criteria describing which
 activations are to be tracked.  For example, if you execute:</p>

 @({
  (set-fc-criteria ((:FORWARD-CHAINING LEMMA1)
                    t t)
                   ((:FORWARD-CHAINING LEMMA2)
                    (ALISTP (BASIC-MAPPER A B))
                    t)
                   (t t (TRUE-LISTP (DLT D)))),
 })

 <p>the system would track all activations of the forward-chaining rule
 @('LEMMA1'), plus those activations of forward-chaining rule @('LEMMA2')
 triggered by the term given in the second triple, plus any activation of any
 rule that might derive @('(TRUE-LISTP (DLT D))').</p>

 <p>Because criteria generally mention variable symbols used in a specific
 conjecture, it is probably best to reconsider your criteria every time you
 want to track forward chaining.</p>

 <p>If the criteria is @('nil'), then nothing is tracked.  Setting the criteria
 to @('nil') is the way you turn off tracking and reporting of forward chaining
 activity.  You may do this either by @('(set-fc-criteria)') or by
 @('(set-fc-criteria nil)').  (Technically the second form is an odd use of
 @('set-fc-criteria'), which expects any supplied arguments to be triples; if
 the ``triple'' @('nil') is the only one supplied, we take it to mean that the
 entire criteria should be @('nil').)</p>

 <p>To track every forward chaining activation you may set the criteria with
 either @('(set-fc-criteria (t t t))') or use the abbreviation
 @('(set-fc-criteria t)').</p>

 <p>If, when you read a forward chaining report, you see no mention of an
 activation you have in mind, e.g., of a certain rune or deriving a certain
 conclusion, and you have set the criteria correctly, then the activation never
 happened.  (This is akin to using @(':')@(tsee brr) and @(':')@(tsee monitor)
 to monitor the application of a rewrite rule and then seeing no interactive
 break.)</p>

 <p>For some relevant functions to help you manage criteria and when the full
 reports are printed see @(tsee fc-report), @(tsee show-fc-criteria), @(tsee
 set-fc-criteria), @(tsee reset-fc-reporting), and @(tsee
 set-fc-report-on-the-fly).</p>")

(defxdoc fourth
  :parents (nth acl2-built-ins)
  :short "Fourth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc free-variables
  :parents (rule-classes rewrite)
  :short "Free variables in rules"
  :long "<p>As described elsewhere (see @(see rule-classes)), ACL2 rules are
 treated as implications for which there are zero or more hypotheses @('hj') to
 prove.  In particular, rules of class @(':')@(tsee rewrite) may look like
 this:</p>

 @({
  (implies (and h1 ... hn)
           (fn lhs rhs))
 })

 <p>Variables of @('hi') are said to occur <i>free</i> in the above
 @(':rewrite') rule if they do not occur in @('lhs') or in any @('hj') with
 @('j<i').  (To be precise, here we are only discussing those variables that
 are not in the scope of a @(tsee let)/@(tsee let*)/@('lambda') that binds
 them.)  We also refer to these as the <i>free variables</i> of the rule.  ACL2
 may issue a warning or error when there are free variables in a rule, as
 described below.  (Variables of @('rhs') may be considered free if they do not
 occur in @('lhs') or in any @('hj').  But we do not consider those in this
 discussion.)</p>

 <p>In general, the <i>free variables</i> of rules are those variables
 occurring in their hypotheses (not @(tsee let)/@(tsee let*)/@('lambda')-bound)
 that are not bound when the rule is applied.  For rules of class @(':')@(tsee
 linear) and @(':')@(tsee forward-chaining), variables are bound by a trigger
 term.  (See @(see rule-classes) for a discussion of the @(':trigger-terms')
 field).  For rules of class @(':')@(tsee type-prescription), variables are
 bound by the @(':typed-term') field.</p>

 <p>See @(see free-variables-examples) for more examples of how this all works,
 including illustration of how the user can exercise some control over it.  In
 particular, see @(see free-variables-examples-rewrite) for an explanation of
 output from the @(see break-rewrite) facility in the presence of rewriting
 failures involving free variables, as well as an example exploring ``binding
 hypotheses'' as described below.</p>

 <p>Let us discuss the method for relieving hypotheses of @(see rewrite) rules
 with free variables.  Similar considerations apply to @(see linear) and @(see
 forward-chaining) rules, and @(see type-prescription) rules.  Note that the
 @(':match-free') mechanism discussed below does not apply to @(see
 type-prescription) rules.  See @(see free-variables-type-prescription) for a
 discussion of how to control free-variable matching for @(see
 type-prescription) rules.</p>

 <p>We begin with an example.  Does the proof of the @(tsee thm) below
 succeed?</p>

 @({
  (defstub p2 (x y) t)

  (defaxiom p2-trans
    (implies (and (p2 x y)
                  (p2 y z))
             (equal (p2 x z) t))
    :rule-classes ((:rewrite :match-free :all)))

  (thm (implies (and (p2 a c)
                     (p2 a b)
                     (p2 c d))
                (p2 a d)))
 })

 <p>Consider what happens when the proof of the @('thm') is attempted.  The
 ACL2 rewriter attempts to apply rule @('p2-trans') to the conclusion, @('(p2 a
 d)').  So, it binds variables @('x') and @('z') from the left-hand side of the
 conclusion of @('p2-trans') to terms @('a') and @('d'), respectively, and then
 attempts to relieve the hypotheses of @('p2-trans').  The first hypothesis of
 @('p2-trans'), @('(p2 x y)'), is considered first.  Variable @('y') is free in
 that hypothesis, i.e., it has not yet been bound.  Since @('x') is bound to
 @('a'), the rewriter looks through the context for a binding of @('y') such
 that @('(p2 a y)') is true, and it so happens that it first finds the term
 @('(p2 a b)'), thus binding @('y') to @('b').  Now it goes on to the next
 hypothesis, @('(p2 y z)').  At this point @('y') and @('z') have already been
 bound to @('b') and @('d'); but @('(p2 b d)') cannot be proved.</p>

 <p>So, in order for the proof of the @(tsee thm) to succeed, the rewriter
 needs to backtrack and look for another way to instantiate the first
 hypothesis of @('p2-trans').  Because @(':match-free :all') has been
 specified, backtracking does take place.  This time @('y') is bound to @('c'),
 and the subsequent instantiated hypothesis becomes @('(p2 c d)'), which is
 true.  The application of rule @('(p2-trans)') succeeds and the theorem is
 proved.</p>

 <p>If instead @(':match-free :all') had been replaced by @(':match-free
 :once') in rule @('p2-trans'), then backtracking would not occur, and the
 proof of the @(tsee thm) would fail.</p>

 <p>Next we describe in detail the steps used by the rewriter in dealing with
 free variables.</p>

 <p>The ACL2 rewriter uses the following sequence of steps to relieve a
 hypothesis with free variables, except that steps (1) and (3) are skipped for
 @(':forward-chaining') rules and step (3) is skipped for
 @(':type-prescription') rules.  First, if the hypothesis is of the form
 @('(force hyp0)') or @('(case-split hyp0)'), then replace it with
 @('hyp0').</p>

 <blockquote><p>(1) Suppose the hypothesis has the form @('(equiv var term)')
 where @('var') is free and no variable of @('term') is free, and either
 @('equiv') is @(tsee equal) or else @('equiv') is a known @(see equivalence)
 relation and @('term') is a call of @(tsee double-rewrite).  We call this a
 ``binding hypothesis.''  Then bind @('var') to the result of rewriting
 @('term') in the current context.</p>

 <p>(2) Look for a binding of the free variables of the hypothesis so that the
 corresponding instance of the hypothesis is known to be true in the current
 context.</p>

 <p>(3) Search all @(tsee enable)d, hypothesis-free rewrite rules of the form
 @('(equiv lhs rhs)'), where @('lhs') has no variables (other than those bound
 by @(tsee let), @(tsee let*), or @('lambda')), @('rhs') is known to be true in
 the current context, and @('equiv') is typically @('equal') but can be any
 equivalence relation appropriate for the current context (see @(see
 congruence)); then attempt to bind the free variables so that the instantiated
 hypothesis is @('lhs').</p></blockquote>

 <p>For cases (2) and (3), the first instance found may ultimately fail because
 the remaining hypotheses are not all relieved under the extended bindings.  In
 that case, should the attempt to relieve hypotheses fail, or should the search
 continue to find other instances for (2) or (3)?  The answer depends on which
 of two options is in force for the so-called ``match-free'' of the rule.
 Below we discuss how to specify these two options as ``@(':once')'' or
 ``@(':all')'' (the default), respectively.</p>

 <p>Suppose that the original hypothesis is a call of @(tsee force) or @(tsee
 case-split), where forcing is enabled (see @(see enable-forcing)) .  Also
 suppose that one of the following two cases applies: no instances are found for
 (2) and also none for (3), or else the ``match-free'' option for the rule is
 @(':all') (as discussed below) and all attempts ultimately fail for (2)
 and (3) (because the remaining hypotheses are not all relieved).  Then the
 current hypothesis is relieved but in the resulting split-off goals, all free
 variables are bound to unusual names that call attention to this odd
 situation.</p>

 <p>Is it better to specify @(':once') or @(':all')?  We believe that @(':all')
 is generally the better choice because of its greater power, provided the user
 does not introduce a large number of rules with free variables, which has been
 known to slow down the prover due to combinatorial explosion in the search
 (Steps (2) and (3) above).</p>

 <p>Either way, it is good practice to put the ``more substantial'' hypotheses
 first, so that the most likely bindings of free variables will be found first
 (in the case of @(':all')) or found at all (in the case of @(':once')).  For
 example, a rewrite rule like</p>

 @({
  (implies (and (p1 x y)
                (p2 x y))
           (equal (bar x) (bar-prime x)))
 })

 <p>may never succeed if @('p1') is nonrecursive and enabled, since we may well
 not find calls of @('p1') in the current context.  If however @('p2') is
 disabled or recursive, then the above rule may apply if the two hypotheses are
 switched.  For in that case, we can hope for a match of @('(p2 x y)') in the
 current context that therefore binds @('x') and @('y'); then the rewriter's
 full power may be brought to bear to prove @('(p1 x y)') for that @('x') and
 @('y').</p>

 <p>Moreover, the ordering of hypotheses can affect the efficiency of the
 rewriter.  For example, the rule</p>

 @({
  (implies (and (rationalp y)
                (foo x y))
           (equal (bar x) (bar-prime x)))
 })

 <p>may well be sub-optimal.  Presumably the intention is to rewrite @('(bar
 x)') to @('(bar-prime x)') in a context where @('(foo x y)') is explicitly
 known to be true for some rational number @('y').  But @('y') will be bound
 first to the first term found in the current context that is known to
 represent a rational number.  If the 100th such @('y') that is found is the
 first one for which @('(foo x y)') is known to be true, then wasted work will
 have been done on behalf of the first 99 such terms @('y') &mdash; unless
 @(':once') has been specified, in which case the rule will simply fail after
 the first binding of @('y') for which @('(rationalp y)') is known to be true.
 Thus, a better form of the above rule is almost certainly the following.</p>

 @({
  (implies (and (foo x y)
                (rationalp y))
           (equal (bar x) (bar-prime x)))
 })

 <p><i>Specifying `once' or `all'.</i></p>

 <p>As noted above, the following discussion applies only to @(see rewrite),
 @(see linear), and @(see forward-chaining) rules.  See @(see
 free-variables-type-prescription) for a discussion of analogous considerations
 for @(see type-prescription) rules.</p>

 <p>One method for specifying @(':once') or @(':all') for free-variable
 matching is to provide the @(':match-free') field of the @(':rule-classes') of
 the rule, for example, @('(:rewrite :match-free :all)').  See @(see
 rule-classes).  However, there are global events that can be used to specify
 @(':once') or @(':all'); see @(see set-match-free-default) and see @(see
 add-match-free-override).  Here are some examples.</p>

 @({
  (set-match-free-default :once)    ; future rules without a :match-free field
                                    ; are stored as :match-free :once (but this
                                    ; behavior is local to a book)
  (add-match-free-override :once t) ; existing rules are treated as
                                    ; :match-free :once regardless of their
                                    ; original :match-free fields
  (add-match-free-override :once (:rewrite foo) (:rewrite bar . 2))
                                    ; the two indicated rules are treated as
                                    ; :match-free :once regardless of their
                                    ; original :match-free fields
 })

 <p><i>Some history.</i> Before Version 2.7 the ACL2 rewriter performed Step
 (2) above first.  More significantly, it always acted as though @(':once') had
 been specified.  That is, if Step (2) did not apply, then the rewriter took
 the first binding it found using either Steps (1) or (3), in that order, and
 proceeded to relieve the remaining hypotheses without trying any other
 bindings of the free variables of that hypothesis.</p>")

(defxdoc free-variables-examples
  :parents (free-variables)
  :short "Examples pertaining to free variables in rules"
  :long "<p>The examples in the two sub-topics of this topic illustrate the
 handling of free variables in rules of class @(':')@(tsee rewrite)
 (see @(see free-variables-examples-rewrite)) and of class @(':')@(tsee
 forward-chaining) (see @(see free-variables-examples-forward-chaining)),
 respectively.  These implicitly illustrate @(see free-variables) handling in
 rules of class @(':')@(tsee linear) as well.  Also see @(see free-variables)
 and see @(see rule-classes).</p>")

(defxdoc free-variables-examples-forward-chaining

; Below is a useful comment contributed by Erik Reeber, who also wrote the
; first version of this documentation topic.

;   I've heard that the worst cases of forward-chaining blow up occur when one
;   forward-chaining rule is feeding another one.  These got worse when
;   :match-free :all showed up.  Previously, such situations were kept in check
;   by putting restrictions on the number of times a forward chaining rule
;   could use a term that was generated by another forward-chaining rule.  This
;   worked pretty well since no forward-chaining rule could generate more than
;   one new term.  However, the match-free :all code allows forward-chaining
;   rules to produce lots of terms.  Thus, such we can generate a lot more
;   rules now.

;   I should probably create such a case since it's a more realistic situation
;   for slowdown.  I can also imagine some ways to be more restrictive about
;   such cases.  Perhaps, we should consider the number of siblings of a term
;   as well as the number of ancestors it has before we allow new terms to be
;   generated from it.  Or perhaps only the first round should allow match-free
;   :all.

;   The problem with any such solution is that it would make our
;   forward-chaining even harder to explain to new users.

  :parents (free-variables-examples)
  :short "Examples pertaining to free variables in @(see forward-chaining) rules"
  :long "<p>The following examples illustrate ACL2's handling of free variables
 in @(see forward-chaining) rules, as well as user control over how such free
 variables are handled.  See @(see free-variables) for a background
 discussion.</p>

 @({
  ; First let us introduce a transitive operation, op, and prove a
  ; forward-chaining rule stating the transitivity of op.

  (encapsulate
   (((op * *) => *))
   (local (defun op (x y) (< x y)))
   (defthm transitivity-of-op
     (implies (and (op x y) (op y z)) (op x z))
     :rule-classes :forward-chaining))

  ; The following theorem is proved by forward chaining, using the above rule.

  (thm
   (implies (and (op u v) (op v w) (op v a))
            (op u w)))

  ; The proof of the theorem just above succeeds because the term (op u v)
  ; triggers the application of forward-chaining rule transitivity-of-op,
  ; binding x to u and y to v.  Free variable z of that rule is bound to both w
  ; and to a, resulting in the addition of both (op u w) and (op u a) to the
  ; context.  However, (op v a) happens to be at the front of the context, so
  ; if only one free-variable binding had been allowed, then z would have only
  ; been bound to a, not to w, as we now illustrate.

  (add-match-free-override :once (:forward-chaining transitivity-of-op))

  (thm ; FAILS!
   (implies (and (op u v) (op v w) (op v a))
            (op u w)))

  :ubt! 1

  ; Starting over, this time we prove transitivity-of-op as a :match-free :once
  ; forward-chaining rule.  Note that the presence of :match-free eliminates
  ; the free-variables warning that we got the first time.

  (encapsulate
   (((op * *) => *))
   (local (defun op (x y) (< x y)))
   (defthm transitivity-of-op
     (implies (and (op x y) (op y z)) (op x z))
     :rule-classes ((:forward-chaining :match-free :once))))

  (thm ; FAILS!
   (implies (and (op u v) (op v w) (op v a))
            (op u w)))

  ; Notice that if we swap the order of the last two hypotheses the theorem
  ; goes through, because this time (op v w) is first in the context.

  (thm ; SUCCEEDS!
   (implies (and (op u v) (op v a) (op v w))
            (op u w)))

  :u

  ; Now let's try setting the default to :once.

  (set-match-free-default :once)

  ; We still get a free-variables warning when we admit this forward-chaining rule.

  (encapsulate
   (((op * *) => *))
   (local (defun op (x y) (< x y)))
   (defthm transitivity-of-op
     (implies (and (op x y) (op y z)) (op x z))
     :rule-classes ((:forward-chaining))))

  ; This theorem fails -- as it should.

  (thm ; FAILS!
   (implies (and (op u v) (op v w) (op v a))
            (op u w)))

  ; But if we convert this rule (or here, all possible rules) to :all rules,
  ; then the proof succeeds.

  (add-match-free-override :all t)

  (thm ; SUCCEEDS!
   (implies (and (op u v) (op v w) (op v a))
            (op u w)))

  ; Now let's test a relatively slow :all case (the next thm below).

  :ubt! 1

  (encapsulate
   (((op1 *) => *)
    ((op3 * * *) => *))
   (local (defun op1 (x) (declare (ignore x)) t))
   (local (defun op3 (x0 x1 x2)
            (declare (ignore x0 x1 x2))
            t))
   (defthm op1-op3-property
     (implies (and (op1 x0) (op1 x1) (op1 x2))
              (op3 x0 x1 x2))
     :rule-classes ((:forward-chaining :match-free :all))))

  ; The following succeeds, but takes a little time (about a second in one run).

  (thm (implies
        (and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5)
             (op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11)
             (op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16)
             (op1 a17) (op1 a18) (op1 a19) (op1 a20))
        (op3 a5 a6 a0)))

  (add-match-free-override :once t)

  ; The same theorem now fails because of the add-match-free-override, but is
  ; more than an order of magnitude faster.

  (thm (implies
        (and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5)
             (op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11)
             (op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16)
             (op1 a17) (op1 a18) (op1 a19) (op1 a20))
        (op3 a5 a6 a0)))

  ; A slight variant succeeds in a negligible amount of time (still with the
  ; :once override above).

  (thm (implies
        (and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5)
             (op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11)
             (op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16)
             (op1 a17) (op1 a18) (op1 a19) (op1 a20))
        (op3 a5 a20 a20)))

  ; Reality check: This shouldn't give a free-variables warning, and everything
  ; should work great since there are no free variables with this trigger term.

  :ubt! 1

  (encapsulate
   (((op1 *) => *)
    ((op7 * * * * * * *) => *))
   (local (defun op1 (x)
            (declare (ignore x))
            t))
   (local (defun op7 (x0 x1 x2 x3 x4 x5 x6)
            (declare (ignore x0 x1 x2 x3 x4 x5 x6))
            t))
   (defthm op1-op7-property
     (implies (and (op1 x0) (op1 x1) (op1 x2)
                   (op1 x3) (op1 x4) (op1 x5) (op1 x6))
              (op7 x0 x1 x2 x3 x4 x5 x6))
     :rule-classes ((:forward-chaining
                     :trigger-terms ((op7 x0 x1 x2 x3 x4 x5 x6))))))

  ; The following then succeeds, and very quickly.

  (thm (implies (and (op1 a0) (op1 a1) (op1 a2)
                     (op1 a3) (op1 a4) (op1 a5) (op1 a6))
                (op7 a4 a6 a5 a6 a6 a6 a6)))
 })")

(defxdoc free-variables-examples-rewrite

; The second example below could have been given as follows instead, though
; this one is kind of weird since there are free variables on the right-hand
; side of the ground unit rules.

;     (encapsulate
;      (((p1 *) => *)
;       ((p2 * *) => *)
;       ((p3 *) => *)
;       ((a) => *)
;       ((b) => *))
;      (local (defun p1 (x) x))
;      (local (defun p2 (x y) (list x y)))
;      (local (defun p3 (x) x))
;      (local (defun a () 0))
;      (local (defun b () 0)))
;
;     ; Allow default of :match-free :all (form may be omitted).
;     (set-match-free-error nil)
;
;     (defaxiom ax1
;       (implies (and (p1 x)
;                     (p2 x y))
;                (p3 y)))
;
;     (defaxiom p1-a-equals-p2-a-y
;       (equal (p1 (a)) (p2 (a) y)))
;
;     (defaxiom p1-u-equals-p2-a-y
;       (equal (p1 (b)) (p2 (a) y)))
;
;     ; Succeeds.
;     (thm (implies (p2 (a) y)
;                   (p3 y)))
;
;     (add-match-free-override :once t)
;
;     ; Fails.
;     (thm (implies (p2 (a) y)
;                   (p3 y)))
;
;     (add-match-free-override :clear)
;
;     ; Succeeds.
;     (thm (implies (p2 (a) y)
;                   (p3 y)))
;
;     (add-match-free-override :once (:rewrite string<-l-trichotomy))
;
;     ; Succeeds.
;     (thm (implies (p2 (a) y)
;                   (p3 y)))

  :parents (free-variables-examples)
  :short "Examples pertaining to free variables in @(see rewrite) rules"
  :long "<p>The following examples illustrate ACL2's handling of free variables
 in @(see rewrite) rules, as well as user control over how such free variables
 are handled.  See @(see free-variables) for a background discussion.</p>

 @({
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;;; Example 1
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  (defstub p2 (x y) t) ; introduce unconstrained function

  ; Get warning because of free variable.  This would be an error if you had
  ; first executed (set-match-free-error t) in order to force yourself to
  ; specify :match-free (illustrated later, below).
  (defaxiom p2-trans
    (implies (and (p2 x y)
                  (p2 y z))
             (p2 x z)))

  ; Succeeds.
  (thm (implies (and (p2 a c)
                     (p2 a b)
                     (p2 c d))
                (p2 a d)))

  ; The following causes an error because p2-trans is not a rune.
  (add-match-free-override :once p2-trans)

  ; After the following, the rewrite rule p2-trans will only allow one
  ; attempt per hypothesis to bind free variables.
  (add-match-free-override :once (:rewrite p2-trans))

  ; Now this same theorem fails to be proved.  Here's why.  The
  ; context for proving (p2 a d) happens to include the hypotheses in
  ; reverse order.  So when the first hypothesis of p2-trans, namely
  ; (p2 x y), is relieved, where x is bound to a (as we are attempting
  ; to rewrite the current literal (p2 a d)), we find (p2 a b) in the
  ; context before (p2 a c) and hence y is bound to b.  The
  ; instantiated second hypothesis of p2-trans is thus (p2 b d), and
  ; the proof fails.  Before the add-match-free-override form above,
  ; the proof succeeded because the rewriter was allowed to backtrack
  ; and find the other binding for the first hypothesis of p2-trans,
  ; namely, y bound to c.  Then the instantiated second hypothesis of
  ; p2-trans is (p2 c d), which is known to be true in the current
  ; context.
  (thm (implies (and (p2 a c)
                     (p2 a b)
                     (p2 c d))
                (p2 a d)))

  ; Return to original behavior for binding free variables.
  (add-match-free-override :all t)

  ; Succeeds once again.
  (thm (implies (and (p2 a c)
                     (p2 a b)
                     (p2 c d))
                (p2 a d)))

  (u) ; undo (add-match-free-override :all t)

  ; This is an error, since no further arguments should appear after
  ; :clear.
  (add-match-free-override :clear t)

  ; Return all rules to original behavior for binding free variables,
  ; regardless of which previous add-match-free-override forms have
  ; been executed.
  (add-match-free-override :clear)

  ; This succeeds just as it did originally.
  (thm (implies (and (p2 a c)
                     (p2 a b)
                     (p2 c d))
                (p2 a d)))

  (ubt! 'p2-trans) ; back to the start, except retain the defstub

  ; Require that :match-free be specified for :linear and :rewrite rules with
  ; free variables.
  (set-match-free-error t)

  ; Fails because :match-free is missing.
  (defaxiom p2-trans
    (implies (and (p2 x y)
                  (p2 y z))
             (p2 x z)))

  ; Fails because :match-free must be followed by :once or :all.
  (defaxiom p2-trans
    (implies (and (p2 x y)
                  (p2 y z))
             (p2 x z))
    :rule-classes ((:rewrite :match-free nil)))

  ; Succeeds, this time with no warning at all.
  (defaxiom p2-trans
    (implies (and (p2 x y)
                  (p2 y z))
             (p2 x z))
    :rule-classes ((:rewrite :match-free :once)))

  ; Fails because we only bind once (see earlier long comment).
  (thm (implies (and (p2 a c)
                     (p2 a b)
                     (p2 c d))
                (p2 a d)))

  ; Treat p2-trans as though `:match-free :all' had been specified.
  (add-match-free-override :all (:rewrite p2-trans))

  ; Succeeds since more than one binding is allowed for p2-trans.
  (thm (implies (and (p2 a c)
                     (p2 a b)
                     (p2 c d))
                (p2 a d)))

  (u)
  (u)

  ; Specify that future :linear and :rewrite rules with free variables
  ; that do not have :match-free specified are treated as though
  ; `:match-free :once' were specified.
  (set-match-free-default :once)

  ; Succeeds without error since `:match-free' is specified, as described
  ; above.  But there is a warning, since :match-free is not specified for this
  ; :rewrite rule.
  (defaxiom p2-trans
    (implies (and (p2 x y)
                  (p2 y z))
             (p2 x z)))

  ; Fails since only single bindings are allowed for p2-trans.
  (thm (implies (and (p2 a c)
                     (p2 a b)
                     (p2 c d))
                (p2 a d)))

  ; Treat p2-trans as though `:match-free :all' had been specified.
  (add-match-free-override :all t)

  ; Succeeds.
  (thm (implies (and (p2 a c)
                     (p2 a b)
                     (p2 c d))
                (p2 a d)))

  ; Test searching of ground units, i.e. rewrite rules without variables on the
  ; left side of the conclusion, for use in relieving hypotheses with free
  ; variables.  This is a very contrived example.

  (ubt! 1) ; back to the start

  (encapsulate
   (((p1 *) => *)
    ((p2 * *) => *)
    ((p3 *) => *)
    ((a) => *)
    ((b) => *))
   (local (defun p1 (x) x))
   (local (defun p2 (x y) (list x y)))
   (local (defun p3 (x) x))
   (local (defun a () 0))
   (local (defun b () 0)))

  ; Allow default of :match-free :all (form may be omitted).
  (set-match-free-error nil)

  (defaxiom ax1
    (implies (and (p2 x y)
                  (p1 y))
             (p3 x)))

  (defaxiom p2-a-b
    (p2 (a) (b)))

  (defaxiom p2-a-a
    (p2 (a) (a)))

  (defaxiom p1-b
    (p1 (b)))

  ; Succeeds; see long comment below on next attempt to prove this
  ; theorem.
  (thm (implies (p2 (a) y)
                (p3 (a))))

  ; Now ax1 will only relieve hypothesis (p2 x y) for one binding of y:
  (add-match-free-override :once t)

  ; Fails when ax1 attempts to rewrite the conclusion to true, because
  ; the most recent ground unit for hypothesis (p2 x y) with x bound
  ; to (a) is rule p2-a-a, which binds y to (a).  If more than one ground
  ; unit could be used then we would backtrack and apply rule p2-a-b,
  ; which binds y to (b) and hence hypothesis (p1 y) of ax1 is
  ; relieved by rule p1-b.
  (thm (implies (p2 (a) y)
                (p3 (a))))

  ; Return rules to original :match-free behavior.
  (add-match-free-override :clear)

  ; Succeeds once again.
  (thm (implies (p2 (a) y)
                (p3 (a))))

  ; Just for kicks, change the behavior of a built-in rule irrelevant
  ; to the proof at hand.
  (add-match-free-override :once (:rewrite string<-l-trichotomy))

  ; Still succeeds.
  (thm (implies (p2 (a) y)
                (p3 (a))))
 })

 @({
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;;; Example 2
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 })

 <p>The next example illustrates the use of the @(see break-rewrite) facility
 to get information about handling of free variables by the rewriter.
 Explanation is given after this (edited) transcript.  Input begins on lines
 with a prompt (search for ``ACL2''); the rest is output.</p>

 @({
  ACL2 !>(encapsulate
          ((p1 (u x) t)
           (bad (x) t)
           (p2 (x y z) t)
           (bar (x y) t)
           (foo (x y) t)
           (poo (x y) t)
           (prop (u) t))

          (local (defun p1 (u x) (declare (ignore u x)) nil))
          (local (defun bad (x) (declare (ignore x)) nil))
          (local (defun p2 (x y z) (declare (ignore x y z)) nil))
          (local (defun bar (x y) (declare (ignore x y)) nil))
          (local (defun foo (x y) (declare (ignore x y)) nil))
          (local (defun poo (x y) (declare (ignore x y)) nil))
          (local (defun prop (u) (declare (ignore u)) t))

          (defthm foo-poo
            (implies (syntaxp (equal y 'y3))
                     (equal (foo x y)
                            (poo x y))))

          (defthm lemma-1
            (implies (and (p1 u x)
                          (bad x)
                          (p2 x y z)
                          (bar x y)
                          (equal x x) ; admittedly silly!
                          (foo x y))
                     (prop u))
            :rule-classes ((:rewrite :match-free :all))))

  ; [[ output omitted ]]

  Summary
  Form:  ( ENCAPSULATE ((P1 ...) ...) ...)
  Rules: NIL
  Warnings:  Subsume and Non-rec
  Time:  0.08 seconds (prove: 0.00, print: 0.01, other: 0.06)
   T
  ACL2 !>:brr t
  The monitored runes are:
  NIL
   T
  ACL2 !>:monitor (:rewrite lemma-1) t
  (((:REWRITE LEMMA-1) 'T))
  ACL2 !>(thm (implies (and (p1 u0 x1)
                            (bad x1)
                            (bad x3)
                            (bar x3 y1)
                            (bar x3 y3)
                            (p1 u0 x2)
                            (p1 u0 x3)
                            (p2 x3 y1 z1)
                            (p2 x3 y3 z1))
                       (prop u0)))

  (1 Breaking (:REWRITE LEMMA-1) on (PROP U0):
  1 ACL2 >:eval

  1x (:REWRITE LEMMA-1) failed because :HYP 1 contains free variables.
  The following display summarizes the attempts to relieve hypotheses
  by binding free variables; see :DOC free-variables.

      [1] X : X1
  Failed because :HYP 3 contains free variables Y and Z, for which no
  suitable bindings were found.
      [1] X : X2
  Failed because :HYP 2 rewrote to (BAD X2).
      [1] X : X3
          [3] Z : Z1
              Y : Y1
  Failed because :HYP 6 rewrote to (FOO X3 Y1).
          [3] Z : Z1
              Y : Y3
  Failed because :HYP 6 rewrote to (POO X3 Y3).

  1 ACL2 >:unify-subst
       U : U0
  1 ACL2 >
 })

 <p>The @(':eval') command above asks the rewriter to attempt to apply the
 rewrite rule @('lemma-1') to the term @('(prop u0)'), shown just above the
 line with @(':eval').  As we can see at the end, the variable @('u') in the
 conclusion of @('lemma-1') is being bound to the variable @('u0') in the
 conjecture.  The first hypothesis of @('lemma-1') is @('(p1 u x)'), so the
 rewriter looks for some @('x') for which @('(p1 u0 x)') is known to be true.
 It finds @('x1'), and then goes on to consider the second hypothesis, @('(bad
 x)').  Since the theorem we are proving has @('(bad x1)') in the hypothesis
 and @('x') is currently bound to @('x1'), the rewriter is satisfied and moves
 on to the third hypothesis of @('lemma-1'), @('(p2 x y z)').  However, @('x')
 is bound to @('x1') and there are no instances of @('y') and @('z') for which
 @('(p2 x1 y z)') is known in the current context.  All of the above analysis
 is summarized in the first part of the output from @(':eval') above:</p>

 @({
      [1] X : X1
  Failed because :HYP 3 contains free variables Y and Z, for which no
  suitable bindings were found.
 })

 <p>Thus, the binding of @('x') to @('x1') on behalf of the first hypothesis
 has failed.</p>

 <p>The rewriter now backs up to look for other values of @('x') that satisfy
 the first hypothesis, and finds @('x2') because our current theorem has a
 hypothesis of @('(p1 u0 x2)').  But this time, the second hypothesis of
 @('lemma-1'), @('(bad x)'), is not known to be true for @('x'); that is,
 @('(bad x2)') does not rewrite to @('t'); in fact, it rewrites to itself.
 That explains the next part of the output from @(':eval') above:</p>

 @({
      [1] X : X2
  Failed because :HYP 2 rewrote to (BAD X2).
 })

 <p>The rewriter now backs up again to look for other values of @('x') that
 satisfy the first hypothesis, and finds @('x3') because our current theorem
 has a hypothesis of @('(p1 u0 x3)').  This time, the second hypothesis of
 @('lemma-1') is not a problem, and moreover, the rewriter is able to bind
 @('y') and @('z') to @('y1') and @('z1'), respectively, in order to satisfy
 the third hypothesis, @('(p2 x y z)'): that is, @('(p2 x2 y1 z1)') is known in
 the current context.  That explains more of the above output from
 @(':eval'):</p>

 @({
      [1] X : X3
          [3] Z : Z1
              Y : Y1
 })

 <p>Unfortunately, the sixth hypothesis, @('(foo x y)'), rewrites to itself
 under the above bindings:</p>

 @({
  Failed because :HYP 6 rewrote to (FOO X3 Y1).
 })

 <p>So the rewriter looks for other bindings to satisfy the third hypothesis
 and finds these.</p>

 @({
          [3] Z : Z1
              Y : Y3
 })

 <p>This time, the sixth hypothesis can be rewritten under the above bindings,
 from @('(foo x3 y3)') to @('(poo x3 y3)') by lemma @('foo-poo'), but still not
 to @('t').</p>

 @({
  Failed because :HYP 6 rewrote to (POO X3 Y3).
 })

 <p>There are no more free variable bindings to try, so this concludes the
 output from @(':eval').</p>

 @({
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;;; Example 3
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 })

 <p>The next pair of examples illustrates so-called ``binding hypotheses'' (see
 @(see free-variables)) and explores some of their subtleties.  The first shows
 binding hypotheses in action on a simple example.  The second shows how
 binding hypotheses interact with equivalence relations and explains the role
 of @(tsee double-rewrite).</p>

 <p>Our first example sets up a theory with two user-supplied rewrite rules,
 one of which has a binding hypothesis.  Below we explain how that binding
 hypothesis contributes to the proof.</p>

 @({
  ; Define some unary functions.
  (defun f (x) (declare (ignore x)) t)
  (defun g (x) x)
  (defun h (x) x)
  (defun k (x) x)

  ; Prove some simple lemmas.  Note the binding hypothesis in g-rewrite.
  (defthm f-k-h
    (f (k (h x))))
  (defthm g-rewrite
         (implies (and (equal y (k x)) ; binding hypothesis
                       (f y))
                  (equal (g x) y)))

  ; Restrict to a theory that includes the above lemmas but avoids the above
  ; definitions.
  (in-theory (union-theories (theory 'minimal-theory)
                             '(f-k-h g-rewrite)))

  ; Prove a theorem.
  (thm (equal (g (h a)) (k (h a))))
 })

 <p>Let us look at how ACL2 uses the above binding hypothesis in the proof of
 the preceding @('thm') form.  The rewriter considers the term @('(g (h a))')
 and finds a match with the left-hand side of the rule @('g-rewrite'), binding
 @('x') to @('(h a)').  The first hypothesis binds @('y') to the result of
 rewriting @('(k x)') in the current context, where the variable @('x') is
 bound to the term @('(h a)'); thus @('y') is bound to @('(k (h a))').  The
 second hypothesis, @('(f y)'), is then rewritten under this binding, and the
 result is @('t') by application of the rewrite rule @('f-k-h').  The rule
 @('g-rewrite') is then applied under the already-mentioned binding of @('x')
 to @('(h a)').  This rule application triggers a recursive rewrite of the
 right-hand side of @('g-rewrite'), which is @('y'), in a context where @('y')
 is bound (as discussed above) to @('(k (h a))').  The result of this rewrite
 is that same term, @('(k (h a))').  The original call of @('equal') then
 trivially rewrites to @('t').</p>

 <p>We move on now to our second example, which is similar but involves a
 user-defined equivalence relation.  You may find it helpful to review
 @(':equivalence') rules; see @(see equivalence).</p>

 <p>Recall that when a hypothesis is a call of an equivalence relation other
 than @('equal'), the second argument must be a call of @(tsee double-rewrite)
 in order for the hypothesis to be treated as a binding hypothesis.  That is
 indeed the case below; an explanation follows.</p>

 @({
  ; Define an equivalence relation.
  (defun my-equiv (x y) (equal x y))
  (defequiv my-equiv) ; introduces rule MY-EQUIV-IS-AN-EQUIVALENCE

  ; Define some unary functions
  (defun f (x) (declare (ignore x)) t)
  (defun g (x) x)
  (defun h1 (x) x)
  (defun h2 (x) x)

  ; Prove some simple lemmas.  Note the binding hypothesis in lemma-3.
  (defthm lemma-1
    (my-equiv (h1 x) (h2 x)))
  (defthm lemma-2
    (f (h2 x)))
  (defthm lemma-3
         (implies (and (my-equiv y (double-rewrite x)) ; binding hypothesis
                       (f y))
                  (equal (g x) y)))

  ; Restrict to a theory that includes the above lemmas but avoids the above
  ; definitions.
  (in-theory (union-theories (theory 'minimal-theory)
                             '(lemma-1 lemma-2 lemma-3
                                       my-equiv-is-an-equivalence)))

  ; Prove a theorem.
  (thm (equal (g (h1 a)) (h2 a)))
 })

 <p>The proof succeeds much as in the first example, but the following
 observation is key: when ACL2 binds @('y') upon considering the first
 hypothesis of @('lemma-3'), it rewrites the term @('(double-rewrite x)') in a
 context where it need only preserve the equivalence relation @('my-equiv').
 At this point, @('x') is bound by applying @('lemma-3') to the term @('(g (h1
 a))'); so, @('x') is bound to @('(h1 a)').  The rule @('lemma-1') then applies
 to rewrite this occurrence of @('x') to @('(h2 a)'), but only because it
 suffices to preserve @('my-equiv').  Thus @('y') is ultimately bound to @('(h2
 a)'), and the proof succeeds as one would expect.</p>

 <p>If we tweak the above example slightly by disabling the user's @(see
 equivalence) @(see rune), then the proof of the @(tsee thm) form fails because
 the above rewrite of @('(double-rewrite x)') is done in a context where it no
 longer suffices to preserve @('my-equiv') as we dive into the second argument
 of @('my-equiv') in the first hypothesis of @('lemma-3'); so, @('lemma-1')
 does not apply this time.</p>

 @({
  (in-theory (union-theories (theory 'minimal-theory)
                             '(lemma-1 lemma-2 lemma-3)))

  ; Proof fails in this case!
  (thm (equal (g (h1 a)) (h2 a)))
 })")

(defxdoc free-variables-type-prescription
  :parents (free-variables)
  :short "Matching for free variable in @(see type-prescription) rules"
  :long "<p>We assume familiarity with the issue of dealing with free variables
 in hypotheses; see @(see free-variables).</p>

 <p>By default, starting with Version 4.3, ACL2 attempts all possible matches
 for free variables.  Consider the following example.</p>

 @({
  (defstub f1 (x) t)
  (defstub f2 (x y) t)
  (defstub f3 (y) t)

  (defaxiom f1-prop
    (implies (and (f2 x y) ; <-- y is free in this hypothesis
                  (f3 y))
             (f1 x))       ; <-- (f1 x) is the type-term (type is `non-nil')
    :rule-classes :type-prescription)

  ; Succeeds:
  (thm (implies (and (f2 a b)
                     (f3 b))
                (f1 a)))

  ; The following fails unless we try more than one match for free variables in
  ; hypotheses.
  (thm (implies (and (f2 a b)
                     (f2 a c)
                     (f2 a d)
                     (f3 b))
                (f1 a)))
 })

 <p>There may be times when you want to match only the first free variable.  In
 that case, you can write a function of two arguments, the
 <i>type-prescription</i> @(see rune) being applied and the current ACL2 world,
 that prohibits multiple matching for those times.  Your function is then
 `attached' to the built-in constrained function, @('oncep-ts').  The following
 examples are intended to explain how this works.</p>

 <p>First, let us disallow all multiple matching of free variables (i.e.,
 implement the behavior often referred to as ``@(':match-free :once')''; see
 @(see free-variables)).</p>

 @({
  (defun oncep-tp-always (rune wrld)
    (declare (ignore rune wrld)
             (xargs :mode :logic :guard t))
    t)

  (defattach oncep-tp oncep-tp-always)
 })

 <p>The second @('thm') form above will now fail, because only one
 free-variable match is permitted for the first hypothesis of rule @('f1-prop')
 above.</p>

 <p>Now suppose that instead, we want to disallow multiple matches for free
 variables in hypotheses of type-prescription rules <i>except</i> for the rule
 @('f1-prop') above.  With the following events, the second @('thm') form above
 once again succeeds.</p>

 @({
  (defun oncep-tp-always-except-f1-prop (rune wrld)
    (declare (ignore wrld)
             (xargs :mode :logic :guard (and (consp rune)
                                             (consp (cdr rune))
                                             (symbolp (cadr rune)))))
    (not (eq (base-symbol rune) 'f1-prop)))

  (defattach oncep-tp oncep-tp-always-except-f1-prop)
 })

 <p>In general, your @(tsee defattach) event will attach a function symbol to
 @('oncep-tp').  The @(see guard) of that function symbol must be implied by
 the guard of @('oncep-tp'):</p>

 @({
  ACL2 !>:args oncep-tp

  Function         ONCEP-TP
  Formals:         (RUNE WRLD)
  Signature:       (ONCEP-TP * *)
                   => *
  Guard:           (AND (PLIST-WORLDP WRLD)
                        (CONSP RUNE)
                        (CONSP (CDR RUNE))
                        (SYMBOLP (CADR RUNE)))
  Guards Verified: T
  Defun-Mode:      :logic
  Type:            built-in (or unrestricted)

   ONCEP-TP
  ACL2 !>
 })")

(defxdoc frequently-asked-questions-by-newcomers
  :parents (introduction-to-the-theorem-prover)
  :short "Some questions newcomers frequently ask"
  :long "<p>This FAQ is for people who've read through all the other sections
 of the tutorial introduction to the theorem prover (see @(see
 introduction-to-the-theorem-prover) and all the links from it that are not
 marked with the little warning sign (``<see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>'').
 Do not expect to understand our answers if you haven't taken the time to read
 through the tutorial.  In the answers below you will see more links into the
 hypertext reference manual.  While such links were marked ``<see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>''
 in the tutorial, they are not marked that way here.  When you enter the
 reference manual be prepared to explore and assemble a mini-course on the
 topic of interest, not a quick fix.</p>

 <p><b>Q</b>.  How do I find something in the <b>ACL2 documentation</b>?
 <b>A</b>.  Try the ``Jump to'' or ``Search'' boxes at the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/current/combined-manual/index.html'>ACL2+Books Manual</a>.</p>

 <p><b>Q</b>.  How does the theorem prover work?  <b>A</b>.  We really don't
 think you need to know much about the inner workings of the prover to become
 an effective user.  That doesn't mean the system is self-explanatory!  It
 means that stuff you need to learn is not how the theorem prover works but how
 to interact with it!  That is what @(see introduction-to-the-theorem-prover)
 is about.  However, if you want the most basic overview of the prover, see
 @(see architecture-of-the-prover).</p>

 <p><b>Q</b>. How do I <b>define a new function</b>?  <b>A</b>. See @(see
 defun).</p>

 <p><b>Q</b>. How do I <b>define a new predicate</b>?  <b>A</b>. See @(see
 defun).</p>

 <p><b>Q</b>. How do I <b>define a new relation</b>?  <b>A</b>. See @(see
 defun).</p>

 <p><b>Q</b>. How do I define a <b>function or predicate that takes a varying
 number of arguments</b>?  <b>A</b>. You can't.  However, see @(see defmacro)
 to learn how to define a macro that takes a varying number of arguments and
 expands into an arbitrary term that you compute.</p>

 <p><b>Q</b>. How do I define a <b>macro that is sensitive to the state</b>?
 <b>A</b>.  You can't.  However, advanced users should consider @(tsee
 make-event).</p>

 <p><b>Q</b>. How do I define <b>mutually recursive</b> functions?  <b>A</b>.
 See @(see mutual-recursion).  However, you should realize that when two
 functions, say @('f') and @('g'), are mutually recursive, properties of @('f')
 generally have to be stated simultaneously with properties of @('g'), since
 inductive proofs about one function require inductive hypotheses about the
 other.  Furthermore, ACL2 does not know how to do inductions for mutually
 recursive functions and must be told.  See @(see
 mutual-recursion-proof-example).</p>

 <p><b>Q</b>. How do I declare the <b>type signature of a function</b>?
 <b>A</b>.  You can't.  ACL2 is a syntactically untyped language and all
 functions are defined on all objects in the ACL2 universe.  We recommend that
 the new user get used to this and only then explore the use of ACL2 to express
 and enforce a type regime.  In ACL2, the <i>guard</i> of a function is akin to
 the type signature of a function in typed languages.  However, ACL2 guards may
 be arbitrary terms, not just type conditions, they only concern the inputs to
 the function (not its result), and do not affect the axiom defining the
 function &mdash; all functions are defined on every combination of objects.
 You may, of course, prove theorems that establish that every function called
 in a definition or theorem is supplied with input satisfying its guards (which
 necessarily involves describe the outputs too).  These formulas are called
 <i>guard conjectures</i> and the process of proving them is called <i>guard
 verification</i>.  Since guards are arbitrary ACL2 formulas, the ``type
 regimes'' one tends to enforce in ACL2 can be much for flexible and expressive
 than those in most programming languages.  However, that expressibility also
 means guard verification can be challenging (indeed undecidable).  On the
 other hand, if one limits oneself to simple type-like guards, lemmas can be
 proved that make most guard verification fully automatic and one can configure
 ACL2 to do guard verification automatically at @('defun')-time.  One may also
 delay guard verification until ``the right'' lemmas have been proved.  By
 doing guard verification one can make functions execute faster by allowing the
 code to avoid runtime checks.  This is especially valuable to industrial users
 who have large models used both in verification and as simulation engines for
 designed artifacts.  In addition, guard verification can give you the
 assurance that you are using your functions within their intended domains and
 hence is a form of functional specification and verification.  However, all
 these advantages aside, it is remarkably easy to drift away from the simplest
 type regimes and write a guard that raises deep mathematical problems.  New
 users should not try to confront these problems until they are comfortable
 with the theorem prover and with lemma development.  Therefore, we
 <b>strongly</b> recommend that you forget about types and guards and get used
 to reasoning about total functions.  When you do decide to learn about them,
 be prepared for a complex story involving specification, execution efficiency,
 and proof management.  See @(see guard).</p>

 <p><b>Q</b>. How do I tell @('defun') <b>what measure to use</b>?
 <b>A</b>. See @(see xargs), specifically @(':measure').</p>

 <p><b>Q</b>.  I specified a measure that always returns a natural number but
 ACL2 is acting like it's not a natural number.  <b>A</b>.  There are two
 likely problems.  The most likely one is that your measure isn't really always
 a natural!  Suppose the formals of your @('defun') are @('x') and @('y') and
 your measure is @('(m x y)').  Suppose the recursive calls of your function
 are protected by tests that insure that @('x') and @('y') are naturals.  Then
 you might assume @('x') and @('y') are naturals in the measure.  But ACL2 has
 to prove @('(o-p (m x y))'), where @(tsee o-p) is the predicate that
 recognizes ordinals (and naturals are ordinals).  Note that the theorem
 doesn't have any hypotheses!  You might intuitively think that your measure
 has to be an ordinal just under the conditions that lead to recursive calls.
 That's not what ACL2 enforces.  It has to be an ordinal, always.  So you must
 change your specified measure.  For example, consider wrapping @(tsee nfix)
 around it or around its uses of @('x') and @('y') to coerce those quantities
 to naturals.  The second most likely explanation is that your measure returns
 a natural, always, but ACL2 doesn't know that and it takes induction to prove.
 This might happen if @('m') involves some recursive functions.  In this case,
 prove @('(natp (m x y))') before your @('defun').  Perhaps you should consider
 making the @('natp') lemma a @(':')@(tsee type-prescription) lemma to make
 ACL2's typing algorithm aware of it.</p>

 <p><b>Q</b>. How do I tell @('defun') <b>what well-founded relation to
 use</b>?  <b>A</b>. See @(see xargs), specifically
 @(':well-founded-relation').</p>

 <p><b>Q</b>. How do I show that a <b>relation is well-founded</b>?
 <b>A</b>. Prove a theorem establishing that there is an order preserving
 embedding into the ordinals and store it with @(':rule-classes')
 @(':well-founded-relation') @(see well-founded-relation-rule).</p>

 <p><b>Q</b>.  What is an <b>ordinal</b>?  What does it mean to be
 <b>well-founded</b>?  <b>A</b>.  Ordinals are an extension of the natural
 numbers used to insure that a process can't go on forever.  Like naturals,
 they can be added, multiplied, and exponentiated.  There is a sense of one
 ordinal being less than another.  Unlike the naturals, each of which is
 finite, the ordinals include infinite objects.  Now imagine ``standing'' on an
 ordinal and ``stepping'' to a smaller one.  Like the naturals, this ``walk
 down the ordinals'' can't go on forever, even if you start on an infinite
 ordinal.  That is because the ordinals are <i>well-founded</i>.  See @(tsee
 o-p) for more information about ordinals in ACL2 and about well-foundedness.
 See @(see ordinals) for a deeper discussion and a discussion of books that can
 help configure ACL2 to reason about ordinals.</p>

 <p><b>Q</b>. How can provide <b>hints for the termination proofs</b> in
 @('defun')?  <b>A</b>. See @(see xargs), specifically @(':hints') (for the
 termination proofs) and @(':guard-hints') (for the guard verification
 proofs).</p>

 <p><b>Q</b>. How do I define a <b>constant</b> (something like a <b>global
 variable</b>)?  <b>A</b>. See @(see defconst).  But remember that as an
 applicative programming language, ACL2 does not have global variables!  You
 can define a symbol to have a fixed value and use the symbol sort of like a
 global variable in function definitions: you may refer to the value of the
 symbol in your functions without passing the variable in as formal parameter.
 But you may not ever change the value of the symbol!</p>

 <p><b>Q</b>. How do I save the value of a top-level computation for future
 use?  <b>A</b>. See @(see assign) and see @(see @).</p>

 <p><b>Q</b>. How do I introduce <b>new syntactic form</b> or
 <b>abbreviation</b>?  <b>A</b>. See @(see defmacro).</p>

 <p><b>Q</b>.  How can create and modify an array?  <b>A</b>.  ACL2 is a
 functional language, so it is impossible to destructively modify an existing
 object; technically, all ``updates'' to objects must be implemented by
 ``copy-on-write'' semantics.  That said, ACL2 provides support for @(see
 arrays), provided you use them in a restricted way.  They give you
 constant-time access and change under the use restrictions.</p>

 <p><b>Q</b>.  How do I read from or write to a file?  How do I do IO?
 <b>A</b>.  To manipulate files, your function must have @(tsee state) as an
 argument, so you should read about the restrictions that imposes.  For
 input/output facilities, see @(see io).</p>

 <p><b>Q</b>. How do I define a <b>structure that can be destructively
 modified</b>?  <b>A</b>. ACL2 is an <i>applicative programming language</i>.
 You can't modify objects arbitrarily!  You basically have to ``copy on
 write,'' which means you construct new objects from old ones, making the
 changes you want in the new one.  If the @('car') of some object is @('1') at
 one moment and @('2') later, then the basic logical axiom @('(car x)') =
 @('(car x)') is violated!  However, if the only reference to the old object,
 e.g., <i>x</i>, was to pass it to the code that copied and ``changed'' it,
 then ACL2 can re-use the old object to produce the new one and the axioms
 would not object.  Such syntactic restrictions can make <i>x</i> a modifiable
 structure but they will impose a heavy burden on you as a programmer: if pass
 such an <i>x</i> to a function and the function modifies it, then you must
 pass <i>x</i> only to that function and you must return the modified value and
 use it henceforth.  Such objects are said to be <i>single threaded</i>.  See
 @(see defstobj).</p>

 <p><b>Q</b>.  How do I write a universal quantifier?  An existential
 quantifier?  How can I say ``for all'' or ``there exists''?  <b>A</b> You
 can't literally write quantifiers.  But ACL2 has the power of full first order
 logic with quantification.  See @(see quantifiers).</p>

 <p><b>Q</b>.  How do I introduce an undefined or uninterpreted function
 symbol?  Can I constrain it to have certain properties?  <b>A</b>.  See @(see
 encapsulate).</p>

 <p><b>Q</b>.  How can I hide a lemma?  I want to prove a lemma temporarily to
 use in another proof but I don't want the lemma around thereafter.  <b>A</b>.
 One way to get a similar effect is to prove the lemma and then disable it with
 an @('(in-theory (disable ...))') event; see @(see in-theory).  Another way is
 to put the lemma and the theorem that needs it into an @(tsee encapsulate) and
 wrap a @(tsee local) around the lemma.</p>

 <p><b>Q</b>. What is an <b>event</b>?  <b>A</b>. An <i>event</i> is a command
 that adds information to the ACL2 database (the ``logical world''), like
 @('defun') or @('defthm').  See @(see events).</p>

 <p><b>Q</b>. How do I say that I <b>do not want a rewrite rule</b> generated
 from a theorem?  <b>A</b>. The command</p>

 <code>
 (defthm <i>name</i> <i>formula</i>
         :rule-classes nil)
 </code>

 <p>will attempt to prove <i>formula</i> and, if successful, give
 <i>formula</i> the name <i>name</i>, which you may use in hints as a theorem,
 but it will build no rules from the formula.</p>

 <p><b>Q</b>. How do I say that I want a formula to be <b>stored as a rewrite
 rule</b>?  <b>A</b>. The command</p>

 <code>
 (defthm <i>name</i> <i>formula</i>)
 </code>

 <p>will attempt to prove <i>formula</i> and, if successful, it will give
 <i>formula</i> the name <i>name</i> and generate a rewrite rule from it, with
 the runic name @('(:rewrite ')<i>name</i>)].  It could happen that
 <i>formula</i> generates more than one rewrite rule, e.g., this happens if the
 conclusion is an @('AND').  In this case, each conjunctive branch through the
 conclusion generates a rule named @('(:rewrite ')<i>name</i>@(' . i)'), for
 <i>i</i>=1,2,...  For more details, see @(see rewrite).</p>

 <p><b>Q</b>. How do I say that I want a formula to be <b>stored as a rewrite
 rule</b> <b>and some other kinds of rules</b>?  <b>A</b>. The command</p>

 <code>
 (defthm <i>name</i> <i>formula</i>
         :rule-classes (<i>:class1</i> ... <i>classk</i>))
 </code>

 <p>will attempt to prove <i>formula</i> and, if successful, it will give
 <i>formula</i> the name <i>name</i> and generate a rule of each <i>:classi</i>
 specified.  Each <i>:classi</i> should either be a keyword, like @(':REWRITE')
 or @(':GENERALIZE'), naming a rule class (see @(see rule-classes)), or else
 should be a list that starts with a rule class and then lists the relevant
 modifiers.  Be sure to include @(':REWRITE') among the rule classes if you
 want the formula to generate a rewrite rule.  It doesn't do that automatically
 if you explicitly specify @(':rule-classes')!</p>

 <p><b>Q</b>. How do I <b>rearrange</b> the shape of a formula before
 generating a rule from it?  <b>A</b>. See @(see rule-classes) and read about
 the @(':corollary') modifier.</p>

 <p><b>Q</b>. What is a <b>type-prescription</b>?  <b>A</b>. ACL2 has an
 algorithm for determining the type of object returned by a term, where a type
 is one of the Common Lisp primitive datatypes such as natural, integer,
 Boolean, cons, true-listp, etc.  Rules provided by you can influence this
 algorithm.  See @(see type-prescription).</p>

 <p><b>Q</b>. How do <b>rewrite rules work</b>?  <b>A</b>. Re-read the tutorial
 sections: @(see introduction-to-rewrite-rules-part-1) and @(see
 introduction-to-rewrite-rules-part-2).</p>

 <p><b>Q</b>. How do I <b>see what's in the database</b>?  <b>A</b>. You can't
 look at the entire database with user-friendly tools.  You can print the
 command that introduced a particular name, print the entire sequence of user
 commands, print the commands in the region between two commands, print all the
 rewrite rules that apply to a given term or function symbol, and many other
 options.  See @(see history).  If you have loaded a book from another user,
 you might wish to read the source file.  For example, the source file for
 @('(include-book \"arithmetic-5/top\" :dir :system)') is the file named
 @('arithmetic-5/top.lisp') on the @('acl2-sources/books/') directory where
 ever your ACL2 sources are installed.  Often, books are well-documented by
 comments by their authors.  Some books have @('Readme') or @('README') files
 on the same directory.</p>

 <p><b>Q</b>. How do I <b>undo</b> a command?  <b>A</b>. See @(see history),
 especially see @(see u) (``undo'') and see @(see ubt) (``undo back
 through''). <b>Q</b>. What <b>rewrite rules match</b> a given term?
 <b>A</b>. See @(see pl).</p>

 <p><b>Q</b>.  What were those <b>questions to ask when looking at key
 checkpoints</b>?  <b>A</b>.  See @(see introduction-to-key-checkpoints).</p>

 <p><b>Q</b>. How do I figure out <b>why a rewrite rule won't fire</b>?
 <b>A</b>. If you activate rewrite rule monitoring (see @(see brr)) and then
 install a monitor (see @(see monitor)) on the rule in question, ACL2 will
 enter an interactive break whenever the pattern of the rule is matched against
 a target in a proof.  So after installing the monitor, re-try the proof and
 then interact with the rewriter via break commands (see @(see brr-commands)).
 Like all trace and break packages, you have to know what you're doing to use
 the break rewrite facility, so read the material in the reference manual.  If
 no interactive break happens after you've installed the monitor on your rule
 and re-tried the proof, it means no suitable target ever arose.  Don't forget
 to turn off monitoring when you're done as it slows down the system.</p>

 <p><b>Q</b>. <b>Why is a proof taking so long?</b> <b>A</b>. Unexpectedly poor
 performance on simple problems is usually a sign of cyclic rewriting or
 combinatoric explosion.  See @(see dmr) and see @(see
 accumulated-persistence).</p>

 <p><b>Q</b>. How do I tell ACL2 <b>what induction to do</b> for a particular
 formula?  <b>A</b>. When issuing the @('defthm') command for the formula,
 supply an @(':induct') hint:</p>

 <code>
 (defthm <i>name</i>
         <i>formula</i>
         :hints ((\"Goal\" :induct (f x1 ... xn))))
 </code>

 <p>where @('f') is a function that recurs the way you want the induction to
 unfold and @('x1 ... xn') are the relevant variables in <i>formula</i>.  You
 usually have to define @('f') appropriately for each formula that needs an
 induct hint, though sometimes you can re-use an earlier @('f') or one of the
 functions in the formula itself.  It doesn't matter what value @('(f x1
 ... xn)') returns.  All that matters is how it recurs.  The termination
 analysis for @('f') justifies the induction done.  See @(see hints),
 especially the section on @(':induct') hints; also see @(see induction).</p>

 <p><b>Q</b>. ACL2 doesn't know <b>simple arithmetic</b> that can simplify the
 term @('(+ 1 -1 x)').  <b>A</b>.  You should load an arithmetic book whenever
 you're dealing with an arithmetic problem.  The simplest arithmetic book is
 typically loaded with the event @('(include-book \"arithmetic/top-with-meta\"
 :dir :system)').  If you're using @('floor') and @('mod') or non-linear
 arithmetic like @('(* x y)') you should use @('(include-book
 \"arithmetic-5/top\" :dir :system)').  See also the discussion of arithmetic
 books under the ``Lemma Libraries and Utilities'' link of the ACL2 home page,
 and see @(see community-books).</p>

 <p><b>Q</b>. ACL2 is not using an <b>arithmetic lemma</b> that I proved.
 <b>A</b>. Lemmas concluding with arithmetic inequalities, like</p>

 @({
  (implies (member e x)
           (< (len (delete e x)) (len x)))
 })

 <p>are not good rewrite rules because they rarely match targets because of
 intervening arithmetic operators.  For example, the above conclusion doesn't
 match @('(< (LEN (DELETE E X)) (+ 1 (LEN X)))').  You should store such lemmas
 as @(':linear') rules by using the command:</p>

 @({
  (defthm len-delete
    (implies (member e x)
             (< (len (delete e x)) (len x)))
    :rule-classes :linear)
 })

 <p>See @(see linear).</p>

 <p><b>Q</b>.  What is a <b>linear rule</b>?  <b>A</b>.  See @(see linear).</p>

 <p><b>Q</b>. How do I make ACL2 <b>treat a relation as an equality</b>?
 <b>A</b>. We assume you mean to treat the relation as an equivalence, i.e.,
 replace one term by another when they are equivalent under your relation.  See
 @(see equivalence), see @(see congruence), and see @(see refinement).</p>

 <p><b>Q</b>. One of my rewrite rules has a <b>hypothesis that doesn't
 rewrite</b> to true.  What do I do?  <b>A</b>. Prove a rewrite rule that
 establishes that hypothesis under the relevant assumptions from the context of
 the intended target.  Alternatively, undo the rule and restate it with a
 @(tsee force) around the problematic hypothesis, making ACL2 assume the
 hypothesis when the rule is applied and raising the truth of the hypothesis as
 an explicit subgoal of the proof.  See also @(tsee case-split).  Of course,
 you should always state the strongest rewrite rules you can think of,
 eliminating hypotheses or shifting them to the right-hand side inside of
 @('IF')s; see @(see strong-rewrite-rules).</p>

 <p><b>Q</b>. How do I make ACL2 ``guess'' the <b>right instantiation of a free
 variable</b>?  <b>A</b>. You can provide a @(':restrict') hint that names the
 problematic lemma and provides an instantiation of the free variable.  See
 @(see hints), specifically @(':restrict').  You could alternatively give a
 hint that @(':uses') the rule and provides the appropriate instantiation in
 full.  See @(see hints), specifically @(':use').  Recall that ACL2 guesses
 free variable instantiations by matching the problematic hypothesis to the
 assumptions in the context of the target.  If the appropriate assumption is
 present but ACL2 is finding another one, try undoing the problematic rule and
 proving it again, specifying the @(':match-free :all') modifier of the
 @(':rewrite') or @(':linear') rule class.  See @(see rule-classes).
 Alternatively, undo and prove the problematic rule again and use a @(tsee
 bind-free) form to compute the appropriate instantiation.</p>

 <p><b>Q</b>. How can I make ACL2 do a <b>case split</b> to prove a certain
 subgoal?  <b>A</b>. See @(see hints), specifically @(':cases').</p>

 <p><b>Q</b>. How can I <b>prevent ACL2 from using a rewrite rule</b>?
 <b>A</b>.  See @(see hints), specifically @(':in-theory (disable ...)').  If
 the use of the rule is problematic in only one subgoal and the lemma is needed
 in other subgoals, disable the lemma only in the problematic subgoal by
 specifying the subgoal name (e.g., @('\"Subgoal 1/3.2.1\"')) as the goal
 specifier in the hint.  If the rule isn't needed anywhere in the proof, you
 could use the specifier @('\"Goal\"').  If you don't think the rule will ever
 be needed for a while, you could globally disable it with the event
 @('(in-theory (disable ...))')  (see @(see in-theory)) executed before the
 first problematic proof.  If the rule has never been used or must always be
 disabled, undo it and prove it again with @(':')@(tsee rule-classes)
 @('nil').</p>

 <p><b>Q</b>.  How can I prevent ACL2 from running a definition on constants?
 I tried disabling the function but that didn't work.  <b>A</b>.  If you have a
 function named @('f') then disabling @('f') will disable the definitional
 axiom about @('f').  But ACL2 has another kind of rule about @('f'), telling
 it how to evaluate @('f').  The @(see rune) of this rule is
 @('(:executable-counterpart f)').  Try disabling that, as in the @(':')@(tsee
 hints) @('((')...  @(':in-theory (disable (:executable-counterpart f))
 ...c[))').</p>

 <p><b>Q</b>. How can I make ACL2 <b>use a rule</b> in a proof?  <b>A</b>. See
 @(see hints), specifically @(':use').</p>

 <p><b>Q</b>.  How can I make ACL2 expand a function call in a proof?
 <b>A</b>.  You can give an @(':')See @(see expand) hint.</p>

 <p><b>Q</b>.  ACL2 sometimes aborts the proof attempt before showing me all of
 the subgoals.  How can I make it just keep going instead of aborting early?
 <b>A</b>. See @(see otf-flg), which stands for Onward Thru the Fog FLaG.</p>

 <p><b>Q</b>. How can I <b>compute when I want a rule to fire</b>?  <b>A</b>.
 See @(see syntaxp).</p>

 <p><b>Q</b>.  How can I add <b>pragmatic advice to a lemma after it has been
 proved</b>?  For example, how can add a forced hypothesis, a backchain limit,
 or a @('syntaxp') test?  <b>A</b>.  You can't.  You can undo the lemma,
 restate it appropriately, and prove it again.  This produces the cleanest
 database.  Alternatively, you can prove the restated lemma under a new name
 &mdash; a task that should be easy since the old version is in the database
 and will presumably make the proof trivial &mdash; and then disable the old
 name.</p>

 <p><b>Q</b>. How can I <b>stop ACL2 from rewriting a term</b>?  <b>A</b>. If
 you need rewriting done but want to prevent some particular terms from being
 rewritten, see @(see hints), specifically @(':hands-off').  Alternatively,
 consider embedding the problematic term in a @(tsee hide).  Users sometime
 develop special theories (see @(see theory)) containing just the rules they
 want and then use hints to switch to those theories on the appropriate
 subgoals.</p>

 <p><b>Q</b>.  Can I <b>compute which subgoals a hint refers to</b>?  <b>A</b>.
 Yes, see @(see computed-hints).  This topic is for advanced users but knowing
 that it is possible might come in handy someday.</p>

 <p><b>Q</b>.  I want the rewriter to <b>always use one theory and then switch
 to another</b> so that it doesn't use my most complicated before until doing
 the simple things.  <b>A</b>.  This is possible but is something for the
 advanced user.  It can be done using a form of @(see computed-hints).  See
 @(see using-computed-hints-7).</p>

 <p><b>Q</b>.  Is there a way to attach <b>the same hint to every defthm</b>?
 <b>A</b>.  See @(see default-hints).</p>

 <p><b>Q</b>.  How can I just tell ACL2 the proof steps?  <b>A</b>.  See @(see
 verify) and see @(see proof-builder).</p>

 <p><b>Q</b>. How can I write <b>my own simplifier</b>?  <b>A</b>.  See @(see
 meta).</p>

 <p><b>Q</b>. How can I add an axiom or just assume some lemma without proof?
 <b>A</b>. This is very dangerous but is a good strategy for exploring whether
 or not a certain set of lemmas (and their rules) is sufficient to prove your
 goal.  See @(see defaxiom) and see @(see skip-proofs).</p>

 <p><b>Q</b>. How can redefine a user-defined function?  <b>A</b>.  This is
 tricky.  What if you've already proved theorems about the old definition and
 then wish to change it?  There are several options.  See @(see
 ld-redefinition-action) (and note specifically the discussion of updater
 function for it, @('set-ld-redefinition-action')); also see @(see redef), see
 @(see redef!), see @(see redef+), and see @(see redef-).</p>

 <p><b>Q</b>. How do I <b>change a function from</b> @(':program') <b>mode
 to</b> @(':logic') <b>mode</b>?  <b>A</b>. See @(see verify-termination).</p>

 <p><b>Q</b>. How do I <b>change the guards</b> on a function?  <b>A</b>. You
 can't.  Undo it and redefine it.</p>

 <p><b>Q</b>. What is <b>program mode</b>?  <b>A</b>. See @(see program).</p>

 <p><b>Q</b>. What does the ACL2 <b>prompt</b> mean?  <b>A</b>.  See @(see
 introduction-to-a-few-system-considerations) or, specifically, see @(see
 prompt).</p>

 <p><b>Q</b>. What is <b>logic mode</b>?  <b>A</b>. See @(see logic).</p>

 <p><b>Q</b>. How do I <b>get into or out of</b> @(':program') <b>mode?</b>
 @(':Logic') <b>mode?</b> <b>A</b>. See @(see program) and see @(see logic).
 You can enter these modes temporarily for a particular @(tsee defun) by using
 @('(declare (xargs :mode :program))') or @('(declare (xargs :mode :logic))')
 after the list of formal parameters to the definition.</p>

 <p><b>Q</b>.  How do I quit from ACL2?  <b>A</b>.  This varies depending on
 the interface you're using.  See @(see
 introduction-to-a-few-system-considerations).</p>

 <p><b>Q</b>. How do I <b>load a file</b> of definitions and theorems created
 by someone else?  <b>A</b>. See @(see include-book).</p>

 <p><b>Q</b>. How do I <b>create my own book</b> of definitions and theorems?
 <b>A</b>. See @(see books).</p>

 <p><b>Q</b>. Where are the books referenced by <b>:dir :system</b> on my
 machine?  <b>A</b>. If your ACL2 is installed on the directory
 <i>dir</i>@('/acl2-sources') and you follow the standard installation
 instructions, then the books are typically the files under the directory
 <i>dir</i>@('/acl2-sources/books/').</p>

 <p><b>Q</b>. How can I find out <b>what books are available</b>?  <b>A</b>. Go
 to the ACL2 home page, @('http://www.cs.utexas.edu/u/moore/acl2/') and look at
 the link labeled ``Lemma Libraries and Utilities.''</p>

 <p><b>Q</b>. How do I <b>produce my own book</b>?  <b>A</b>. See @(see
 books).</p>

 <p><b>Q</b>. What is a <b>decision procedure</b>?  What <b>decision procedures
 does ACL2 have</b>?  <b>A</b>. A <i>decision procedure</i> is an algorithm
 that given enough time and space can determine, for all the formulas in a
 certain syntactic class of formulas, whether the formula is a theorem or not.
 The most well-known decision procedure is for propositional calculus: by
 testing a formula under all the combinations Boolean assignments to the
 variables, one can decide if a propositional formula is a theorem.  The
 syntactic class consists of all formulas you can write using just variables,
 constants, and compositions of the functions @('and'), @('or'), @('not'),
 @('implies'), @('iff'), and @('if').  There are, of course, an exponential
 number of different assignments so the algorithm can be slow.  ACL2 contains a
 propositional decision procedure based on symbolic normalization that can be
 faster than trying all the combinations of truth values &mdash; but is not
 guaranteed to be faster.  ACL2 also contains an optional @(see bdd) procedure.
 ACL2 also contains a decision procedure for rational arithmetic involving
 variables, rational constants, addition, multiplication by rational constants,
 equality, and the various versions of arithmetic inequality (@('<'), @('<='),
 @('>='), and @('>')).  It can be extended with @(':')@(tsee linear) lemmas.
 ACL2 is complete for equality over uninterpreted (e.g., undefined and
 unconstrained) function symbols using an algorithm based on transitive closure
 of equivalence classes under functional substitutivity.  Finally, you can make
 ACL2 use other decision procedures, even ones implemented outside of ACL2; see
 @(see clause-processor).</p>

 <p><b>Q</b>. ACL2 has the <b>change of variable</b> trick (<b>destructor
 elimination</b>) that it does to get rid of @('(CAR X)') and @('(CDR X)') by
 replacing @('x') by @('(CONS A B)').  Is there a way to make ACL2 do that for
 other terms?  <b>A</b>. Yes.  See @(see elim).</p>

 <p><b>Q</b>. How can I <b>prevent destructor elimination</b>?  <b>A</b>. See
 @(see hints), specifically @(':do-not '(eliminate-destructors)').</p>

 <p><b>Q</b>. How can I <b>prevent cross-fertilization</b>?  <b>A</b>. See
 @(see hints), specifically @(':do-not '(fertilize)').</p>

 <p><b>Q</b>. How can I <b>prevent generalization</b>?  <b>A</b>. See @(see
 hints), specifically @(':do-not '(generalize)').</p>

 <p><b>Q</b>. How can I make ACL2 <b>impose a restriction on a new variable</b>
 introduced by destructor elimination or generalization?  <b>A</b>.  See @(see
 generalize).</p>

 <p><b>Q</b>. What <b>rule classes</b> are there?  <b>A</b>. See @(see
 rule-classes).</p>

 <p><b>Q</b>. What is a <b>theory</b>?  <b>A</b>. See @(see theories).</p>

 <p><b>Q</b>. How are <b>hints inherited by the children of a subgoal</b>?
 <b>A</b>. See @(see hints-and-the-waterfall).</p>

 <p><b>Q</b>.  How do I use ACL2 under <b>Emacs</b>?  <b>A</b>. See @(see
 emacs).</p>

 <p><b>Q</b>.  How do I use ACL2 under <b>Eclipse</b>?  <b>A</b>. See @(see
 ACL2-Sedan).</p>

 <p><b>Q</b>.  How do I interrupt the prover?  <b>A</b>.  The keyboard sequence
 for interrupting a running process depends your operating system, host Common
 Lisp, and user interface (e.g., Emacs, Eclipse, etc.).  But perhaps a few
 examples will help you discover what you need to know.  If your host Common
 Lisp is GCL or Allegro and you are typing directly to the Common Lisp process,
 then you can interrupt a computation by typing ``ctrl-c'' (hold down the
 Control key and hit the ``c'' key once).  But other Lisps may require some
 other control sequence.  If you are typing to an Emacs process which is
 running the GCL or Allegro Common Lisp process in a shell buffer, you should
 type ctrl-c ctrl-c &mdash; that is, you have to type the previously mentioned
 sequence twice in succession.  If you are running the ACL2 Sedan, you can use
 the <i>Interrupt Session</i> button on the tool bar.  The environment you
 enter when you interrupt depends on various factors and basically you should
 endeavor to get back to the top level ACL2 command loop, perhaps by typing
 some kind of Lisp dependent ``abort'' command like @(':q') or @(':a').  You
 can usually determine what environment you're in by paying attention to the
 prompt.</p>

 <p><b>Q</b>.  What is the <b>ACL2 loop</b>?  <b>A</b>.  That is the name given
 to the interactive environment ACL2 provides, a ``read-eval-print loop'' in
 which the user submits successive commands by typing ACL2 expressions and
 keyword commands.  See @(see introduction-to-a-few-system-considerations).</p>

 <p><b>Q</b>.  What is <b>raw lisp</b>?  <b>A</b>.  That is our name for the
 host Common Lisp in which ACL2 is implemented.  See @(see
 introduction-to-a-few-system-considerations).  There is an ACL2 mode named
 <i>raw mode</i> which is different from ``raw lisp.''  See @(see
 set-raw-mode).</p>

 <p><b>Q</b>.  Can I get a tree-like view of a proof?  <b>A</b>.  See @(see
 proof-tree) for an Emacs utility that displays proof trees and allows you to
 navigate through a proof from the proof tree.  The ACL2 Sedan also supports
 proof trees and you should see the ACL2s documentation on that topic.</p>

 <p><b>Q</b>.  I used the earlier Boyer-Moore theorem prover, Nqthm.  How is
 ACL2 different?  <b>A</b>. See @(see nqthm-to-acl2).</p>

 <p>If you are reading this as part of the tutorial introduction to the theorem
 prover, use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-the-theorem-prover).</p>")

(defxdoc full-book-name
  :parents (books-reference)
  :short "Book naming conventions assumed by ACL2"
  :long "<p>For this discussion we assume that the resident operating system is
 Unix (trademark of AT&amp;T), but analogous remarks apply to other operating
 systems supported by ACL2; see @(see pathname).</p>

 <p>ACL2 defines a ``full book name'' to be an ``absolute filename string,''
 that may be divided into contiguous sections: a ``directory string'', a
 ``familiar name'' and an ``extension''.  See @(see pathname) for the
 definitions of ``absolute,'' ``filename string,'' and other notions pertaining
 to naming files.  Below we exhibit the three sections of one such string:</p>

 @({
  \"/usr/home/smith/project/arith.lisp\"

  \"/usr/home/smith/project/\"           ; directory string
                          \"arith\"      ; familiar name
                               \".lisp\" ; extension
 })

 <p>The sections are marked by the rightmost slash and rightmost dot, as shown
 below.</p>

 @({
  \"/usr/home/smith/project/arith.lisp\"
                          |     |
                          slash dot
                          |     |
  \"/usr/home/smith/project/\"           ; directory string
                          \"arith\"      ; familiar name
                               \".lisp\" ; extension
 })

 <p>The directory string includes (and terminates with) the rightmost slash.
 The extension includes (and starts with) the rightmost dot.  The dot must be
 strictly to the right of the slash so that the familiar name is well-defined
 and nonempty.</p>

 <p>If you are using ACL2 on a system in which file names do not have this
 form, please contact the authors and we'll see what we can do about
 generalizing ACL2's conventions.</p>

 <p>We conclude with a remark about a representation of full book names that is
 used in @(see certificate) files and @(tsee make-event) expansions.  When the
 system books directory is a prefix of a full book name, ACL2 may choose to
 write a full book name as @('(:system . \"suffix\")'), where @('\"suffix\"')
 is the result of removing the system books directory from the front of the
 full book name.  Here is an example.</p>

 @({
  ; full book name:
  \"/Users/smith/acl2/acl2/books/std/portcullis.lisp\"

  ; alternate representation
  ; (where \"/Users/smith/acl2/acl2/books/\" is the system books directory):
  (:SYSTEM . \"std/portcullis.lisp\")
 })

 <p>Conversely, in some contexts ACL2 will convert @(':system . \"suffix\"') to
 an absolute pathname.  Generally @('\"suffix\"') will be a relative pathname,
 such as @('\"dir/filename.lisp\"'); in that case, the system books directory
 will be concatenated with @('\"suffix\"') to form a corresponding full book
 name.  However, if @('\"suffix\"') is an absolute pathname, such as
 @('\"/u/smith/foo.lisp\"'), then the corresponding full book name is simply
 that absolute pathname; essentially, the @(':system') prefix is dropped.</p>"
)

(defxdoc function-theory
  :parents (theories theory-functions)
  :short "Function symbol rules as of logical name"
  :long "@({
  Examples:
  (function-theory :here)
  (function-theory 'lemma3)
 })

 <p>See @(see logical-name).</p>

 @({
  General Form:
  (function-theory logical-name)
 })

 <p>Returns the theory containing all the @(':')@(tsee definition) @(see
 rune)s, whether @(see enable)d or not, that existed immediately after @(tsee
 logical-name) was introduced.  See the documentation for @(see theories),
 @(see logical-name) and @(tsee executable-counterpart-theory).</p>

 <p>You may experience a fencepost problem in deciding which logical name to
 use.  @(tsee Deflabel) can always be used to mark unambiguously for future
 reference a particular point in the development of your theory.  The order of
 @(see events) in the vicinity of an @(tsee encapsulate) is confusing.  See
 @(see encapsulate).</p>

 <p>This ``function'' is actually a macro that expands to a term mentioning the
 single free variable @(tsee world).  When theory expressions are evaluated by
 @(tsee in-theory) or the @(':')@(tsee in-theory) hint, @(tsee world) is bound
 to the current ACL2 @(see world).</p>")

(defxdoc functional-instantiation
  :parents (encapsulate)
  :short "An analogue in ACL2 of higher-order logical reasoning.  Functional
 instantiation allows you to prove theorems ``by analogy'' with previous
 theorems.  See @(see hints) and see @(see lemma-instance).")

(defxdoc functional-instantiation-example
  :parents (functional-instantiation tutorial5-miscellaneous-examples)
  :short "A small proof demonstrating functional instantiation"
  :long "<p>The example below demonstrates the use of functional instantiation,
 that is, the use of a generic result in proving a result about specific
 functions.  In this example we constrain a function to be associative and
 commutative, with an identity or ``root,'' on a given domain.  Next, we define
 a corresponding function that applies the constrained associative-commutative
 function to successive elements of a list.  We then prove that the latter
 function gives the same value when we first reverse the elements of the list.
 Finally, we use functional instantiation to derive the corresponding result
 for the function that multiplies successive elements of a list.</p>

 <p>The details of the proof (such as the @(tsee in-theory) event and
 particulars of the lemmas) are not the point here.  Rather, the point is to
 demonstrate the interaction of @(tsee encapsulate) @(see events) and
 @(':functional-instance') @(see lemma-instance)s.  Of course, if you are
 interested in details then you may find it helpful to run these @(see events)
 through ACL2.</p>

 <p>Also see @(see constraint) for more about @(':functional-instance') and see
 @(see lemma-instance) for general information about the use of
 previously-proved lemmas.</p>

 @({
  (in-package \"ACL2\")

  (encapsulate
   (((ac-fn * *) => *)
    ((ac-fn-domain *) => *)
    ((ac-fn-root) => *))
   (local (defun ac-fn (x y) (+ x y)))
   (local (defun ac-fn-root () 0))
   (local (defun ac-fn-domain (x) (acl2-numberp x)))
   (defthm ac-fn-comm
     (equal (ac-fn x y)
            (ac-fn y x)))
   (defthm ac-fn-assoc
     (equal (ac-fn (ac-fn x y) z)
            (ac-fn x (ac-fn y z))))
   (defthm ac-fn-id
     (implies (ac-fn-domain x)
              (equal (ac-fn (ac-fn-root) x)
                     x)))
   (defthm ac-fn-closed
     (and (ac-fn-domain (ac-fn x y))
          (ac-fn-domain (ac-fn-root)))))

  ;;;;;;;;;;;;;;;;;;;;;;;
  ; End of encapsulate. ;
  ;;;;;;;;;;;;;;;;;;;;;;;

  ; Define a ``fold'' function that iteratively applies ac-fn over a list.
  (defun ac-fn-list (x)
    (if (atom x)
        (ac-fn-root)
      (ac-fn (car x)
             (ac-fn-list (cdr x)))))

  ; Recognize lists all of whose elements are in the intended domain.
  (defun ac-fn-domain-list (x)
    (if (atom x)
        t
      (and (ac-fn-domain (car x))
           (ac-fn-domain-list (cdr x)))))

  ; Define a list reverse function.
  (defun rev (x)
    (if (atom x)
        nil
      (append (rev (cdr x))
              (list (car x)))))

  ; The following is needed for proving ac-fn-list-append, which is
  ; needed for proving ac-fn-list-rev.
  (defthm ac-fn-list-closed
     (ac-fn-domain (ac-fn-list x)))

  ; Needed for proving ac-fn-list-rev:
  (defthm ac-fn-list-append
    (implies (and (ac-fn-domain-list x)
                  (ac-fn-domain-list y))
             (equal (ac-fn-list (append x y))
                    (ac-fn (ac-fn-list x)
                           (ac-fn-list y)))))

  ; Needed for proving ac-fn-list-rev:
  (defthm ac-fn-domain-list-rev
    (equal (ac-fn-domain-list (rev x))
           (ac-fn-domain-list x)))

  ; The following is a good idea because without it, the proof attempt
  ; for ac-fn-list-rev (see just below) fails with the term (HIDE
  ; (AC-FN-LIST NIL)).  It is often a good idea to disable
  ; executable-counterparts of functions that call constrained
  ; functions.
  (in-theory (disable (:executable-counterpart ac-fn-list)))

  (defthm ac-fn-list-rev
    (implies (ac-fn-domain-list x)
             (equal (ac-fn-list (rev x))
                    (ac-fn-list x))))

  ; Our goal now is to apply functional instantiation to ac-fn-list-rev
  ; in order to prove the corresponding theorem, times-list-rev, based
  ; on * instead of ac-fn.

  (defun times-list (x)
    (if (atom x)
        1
      (* (car x)
         (times-list (cdr x)))))

  (defun number-listp (x)
    (if (atom x)
        t
      (and (acl2-numberp (car x))
           (number-listp (cdr x)))))

  ; The following relies on the following built-in rules for * (whose
  ; statements correspond directly to their names): commutativity-of-*,
  ; associativity-of-*, and unicity-of-1.

  (defthm times-list-rev
    (implies (number-listp x)
             (equal (times-list (rev x))
                    (times-list x)))
    :hints ((\"Goal\"
             :use
             ((:functional-instance
               ac-fn-list-rev
               ;; Instantiate the generic functions:
               (ac-fn *)
               (ac-fn-root (lambda () 1))
               (ac-fn-domain acl2-numberp)
               ;; Instantiate the other relevant functions:
               (ac-fn-list times-list)
               (ac-fn-domain-list number-listp))))))
 })")

(defxdoc functional-instantiation-in-acl2r
  :parents (functional-instantiation)
  :short "Additional requirements for @(':functional-instance') hints in
  ACL2(r)"
  :long "<p>This documentation topic relates to ACL2(r), the modification of
 ACL2 that supports the real numbers (see @(see real)).</p>

 <p>See @(see hints) and see @(see lemma-instance) for a discussion of
 @(':use') hints that employ the @(':functional-instance') keyword.  Here, we
 document additional requirements for such hints that applies to ACL2(r).  We
 assume familiarity with lemma instances; see @(see lemma-instance).</p>

 <p>(1) When functionally instantiating a non-classical formula, it is illegal
 to use pseudo-lambda expressions in a lemma instance.</p>

 <p>(2) A classical function symbol must be bound either to a classical
 function symbol or to a lambda (or, if allowed, pseudo-lambda) expression with
 a classical body.  Similarly, a non-classical function symbol must be bound
 either to a non-classical function symbol or to a lambda (or, if allowed,
 pseudo-lambda) expression with a non-classical body.</p>")

(defxdoc further-information-on-rewriting
  :parents (introduction-to-the-theorem-prover)
  :short "A grab bag of advice and information on rewriting"
  :long "<p>In the following paragraphs we give some links to advanced topics,
 marked with ``<see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>''.  If you are reading this topic as part of the
 tutorial on the theorem prover, do not follow these links upon your first
 reading.  Just take note of the existence of the facilities and ideas
 mentioned.</p>

 <p>@(see Arithmetic): If your goal theorem involves even trivial arithmetic,
 such as adding or subtracting @('1'), we recommend that you do</p>

 @({
  (include-book \"arithmetic/top-with-meta\" :dir :system)
 })

 <p>which loads into ACL2 all the rules in one of the so-called ACL2
 ``community books''.  (<i>Books</i> are certified files of definitions,
 lemmas, etc., usually prepared by other ACL2 users and explicitly shared with
 the community.  The ACL2 installation instructions suggest downloading the
 community books.)  The book \"top-with-meta\" is the most elementary and most
 widely used arithmetic book.  Other community books include
 \"arithmetic-5/top\" and various hardware and floating-point arithmetic
 books.</p>

 <p><b>Rules Concluding with Arithmetic Inequalities</b>: If you are tempted to
 create a rewrite rule with an arithmetic inequality as its conclusion or
 left-hand side, think again.  Inequalities such as</p>

 @({
  (<= (len (delete e x)) (len x))
 })

 <p>make poor left-hand sides for rewrite rules.  For example, the inequality
 above does not match the target</p>

 @({
  (<= (LEN (DELETE E X)) (+ 1 (LEN X)))
 })

 <p>even though it is sufficient to prove the target (given some simple
 arithmetic).  We recommend that if you have a theorem that establishes an
 arithmetic inequality, you make it a <i>linear</i> rule.  See @(see linear)
 <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p><b>Rearranging Formulas Before Making Rules</b>: It is possible to
 rearrange the propositional structure of a proved formula before processing it
 as a rule.  This allows you to state a theorem one way ``for publication'' and
 rearrange it to be stored as a more effective rule.  See @(see
 introduction-to-the-database) (a tutorial topic you'll come to later) and its
 discussion of the concept of @('corollary').  Also, see the discussion of
 @('corollary') in @(tsee rule-classes) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p><b>Rewriting with New Equivalence Relations</b>: You may introduce new
 <i>equivalence</i> relations, like ``set-equal'' or ``is-a-permutation'' and
 cause the rewriter to replace equivalents by equivalents in suitable contexts,
 where you use <i>congruence</i> rules to inform ACL2 of where these more
 relaxed notions of equivalence may be used; see @(see equivalence) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> and
 see @(see congruence) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p><b>Pragmatic Advice to Control Rules</b>: You may attach various
 <i>pragmas</i> to a rule that allow you rather fine heuristic control over
 whether and how the rule is applied.  For example, you may mark a hypothesis
 to be <i>forced</i> (see @(see force) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 meaning that the rule is to be applied even if that hypothesis is not relieved
 &mdash; but if the proof is successful the system will turn its attention to
 all forced subgoals.  You may similarly mark a hypothesis so as to cause a
 case split, allowing the relief of the hypothesis on one branch and spawning
 another branch explicitly denying the hypothesis; see @(see case-split) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>.
 You may add a bogus hypothesis that looks at the intended application of the
 rule and decides whether to apply the rule or not, performing an arbitrary
 computation on the syntactic context of the application; see @(see syntaxp)
 <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.  By providing a @(':match-free') modifier to the
 @(':rewrite') rule declaration in your rule-classes, you may tell ACL2 to try
 all or only the first free variable value it guesses (see @(see rule-classes)
 <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>).  You may provide a bogus hypothesis that computes
 from the syntactic environment the values to guess for the free variables in a
 rule; see @(see bind-free) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>.
 You may mark a term so that the rewriter does not dive into it; see @(see
 hide) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p><b>Programming Your Own Rewriter</b>: If you cannot find a way to use
 rewrite rules to make the transformations you desire, you might investigate
 the use of <i>metafunctions</i>.  A metafunction is just a little theorem
 prover of your own design.  It takes as input a list structure representing a
 term and returns a list structure representing a term.  If you can prove that
 the meaning of the input and output terms are equivalent, you can extend the
 ACL2 simplifier to call your metafunction.  See @(see meta) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p><b>The Order in which Targets are Rewritten</b>: The rewriter sweeps
 through terms ``inside-out'' otherwise known as ``left-most innermost first''.
 Thus, before trying to apply rewrite rules to @('(')<i>f a1 ... an</i>@(')'),
 rules are applied to the <i>ai</i>.  This has the good effect of normalizing
 the <i>ai</i>.</p>

 <p>This fact might help you understand why sometimes your rules ``don't seem
 to fire.''  For example, suppose you have a rule for rewriting @('(len (rev
 x))') to @('(len x)') and suppose you wish to prove a theorem about @('(LEN
 (REV (CONS A B)))').  Suppose @('rev') is defined in terms of @('append'), as
 shown in @(see programming-knowledge-taken-for-granted).  Then you might see a
 checkpoint in which the @('(LEN (REV ...))') above has been simplified to
 @('(LEN (APPEND (REV B) (LIST A)))') instead of to @('(LEN (CONS A B))').  Why
 wasn't your rule about @('(len (rev x))') applied?  The reason is that @('(REV
 (CONS A B))') rewrote to @('(APPEND (REV B) (LIST A))') before rules were
 applied to @('(LEN (REV ...))').  You need a rule about @('(len (append x
 y))'), as you will see from the checkpoint.</p>

 <p><b>The Order in which Rules are Tried</b>: The rewriter tries the most
 recently proved rules first.  For example, suppose @('f'), @('g'), and @('h')
 are functions defined so that the following two theorems are provable and
 suppose you executed the following two events in the order shown:</p>

 @({
  (defthm rule1 (equal (f (g x)) (h 1 x)))
  (defthm rule2 (equal (f (g x)) (h 2 X)))
 })

 <p>Then if rewrite rules are applied to @('(F (G A))'), the result will be
 @('(H 2 A)'), because the latter rule, @('rule2'), is applied first.  It is
 generally best not to have conflicting rules or, at least, to understand how
 such conflicts are resolved.  The system will warn you when you propose a rule
 that conflicts with an existing one.</p>

 <p>If you were reading this topic as part of the tutorial introduction to the
 theorem prover, use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-rewrite-rules-part-2).</p>")

(defxdoc future-work-related-to-the-tau-system
  :parents (introduction-to-the-tau-system)
  :short "Some tau system problems that we hope someone will address"
  :long "<p>The tau system is inexpressive compared to modern polymorphic type
 systems &mdash; something that may be unavoidable in an untyped first-order
 language.  However, we believe its effectiveness could be greatly increased by
 the development of some additional tools.  We also believe that most of these
 tools could be provided by ACL2 users creating certified community books that
 exploit the basic tools already provided.  It is likely the initial attempts
 to create such books will show the inadequacy of some of the current
 algorithms and data structures in the tau system and might point the way to
 improvements.</p>

 <p>As implementors of ACL2 our preference is to support the improvement of the
 core algorithms and data structures and provide customizable hooks allowing
 users to exploit them by developing effective and convenient interfaces.
 However, we want the further elaboration and optimization of the tau system to
 be based on user experience not just speculation.</p>

 <p>Some tools we <i>think</i> might help are listed below.  We invite
 volunteers and further suggestions.</p>

 <p><i>A tau-centric signature notation</i> for use in function definitions,
 exploited by a macro replacing @('defun') so that input-output relationships
 phrased in tau terms are proved as @(':tau-system') rules immediately after
 functions are introduced:</p>

 <p>We have, for example, experimented with a book defining a macro that allows
 the definition of the function @('ap') (append) accompanied by a signature
 rule.  Subsequent @('defsig') events can add other signatures in the same
 notation.</p>

 @({
  (defsig ap (true-listp * true-listp ==> true-listp) (x y)
     (if (consp x)
         (cons (car x) (ap (cdr x) y))
         y))

  (defsig ap (integer-listp * integer-listp ==> integer-listp))
 })

 <p>This experimental book provides succinct syntax for all tau signatures.
 For example, that book parses the signature</p>

 @({
  (NATP (/= 3 5 7) (< 16) * TRUE-LISTP ==> BOOLEANP * INTEGER-LISTP * NATP)
 })

 <p>to be the signature of a function with two inputs and three outputs.  The
 first input must be a natural number, different from 3, 5, and 7, and less
 than 16.  The second input must be a true list.  The first output is a
 boolean, the second a list of integers, and the third a natural.</p>

 <p>To express this signature for function @('fn') as a formula requires
 significantly more typing by the user:</p>

 @({
  (IMPLIES (AND (NATP X)
                (NOT (EQUAL X 3))
                (NOT (EQUAL X 5))
                (NOT (EQUAL X 7))
                (< X 16)
                (TRUE-LISTP Y))
           (AND (BOOLEANP (MV-NTH 0 (FN X Y)))
                (INTEGER-LISP (MV-NTH 1 (FN X Y)))
                (NATP (MV-NTH 2 (FN X Y)))))
 })

 <p>We suspect that the provision of some succinct tau-centric notation (not
 necessarily the one above) for signatures at definition-time will mean users
 get more benefit from the tau system.</p>

 <p><i>Some tau inference mechanisms</i>: This phrase suggests two different
 improvements.  One is to implement a mechanism that adds or completes
 signatures for function definitions by exploiting knowledge of commonly used
 recursive schemas and the signatures of the subroutines in the body.  For
 example, the definition of @('ap') above rather obviously has the
 signature</p>

 @({
  (integer-listp * integer-listp ==> integer-listp)
 })

 <p>and many others just based on the two recursive schemas that (a) collect
 certain elements from lists and (b) check that all elements have a certain
 property.</p>

 <p>The other ``tau inference'' improvement is to implement a mechanism for
 inferring relations between user-defined Booleans, perhaps by exploiting
 example generation, testing, and knowledge of recursive schemas.  For example,
 it is fairly obvious that @(tsee symbol-alistp) implies @(tsee alistp).
 Making the user state these relations invites omissions that render the tau
 system very unpredictable.</p>

 <p><i>A tau assistant</i>: It would be useful to have a way to find out what
 tau rules are missing.  Given a term that the user believes should
 ``obviously'' have some tau (``type'') what rules might be added to make the
 tau algorithm compute that expected tau?  For example, if @('(g x)') is known
 to satisfy @('P') and @('(f x)') is known to satisfy @('R') when its argument
 satisfies @('S'):</p>

 @({
  g : T ==> P
  f : S ==> R
 })

 <p>then if the user asserts that @('(f (g x))') ``ought'' to have tau @('R'),
 one plausible suggestion is the simple tau rule that @('(P x)') implies @('(S
 x)').  Such assistance &mdash; while still confronting an undecidable problem
 &mdash; might be easier to implement within the tau framework than more
 generally in ACL2.  (Many users have wanted such an assistant to suggest
 lemmas for the rewriter.)</p>")

(defxdoc |Flawed Induction Candidates in App Example|
  :parents (|Pages Written Especially for the Tours|)
  :short "Flawed Induction Candidates in App Example"
  :long "<p>Induction on <b>a</b> is unflawed: every occurrence of <b>a</b> in
 the conjecture</p>

 <code>
 (equal (app (app <b>a</b> b) c)
        (app <b>a</b> (app b c)))
 </code>

 <p>is in a position being recursively decomposed!</p>

 <p>Now look at the occurrences of @('b').  The first (shown in <b>bold</b>
 below) is in a position that is held constant in the recursion of @('(app a
 b)').  It would be ``bad'' to induct on @('b') here.</p>

 <code>
 (equal (app (app a <b>b</b>) c)
        (app a (app b c)))
 </code>")

(defxdoc |Free Variables in Top-Level Input|
  :parents (|Pages Written Especially for the Tours|)
  :short "Free Variables in Top-Level Input"
  :long "<code>
 ACL2 !&gt;<b>(equal (app (app a b) c)</b>
               <b>(app a (app b c))))</b>

 ACL2 Error in TOP-LEVEL:  Global variables, such as C, B, and A, are
 not allowed. See :DOC ASSIGN and :DOC @@.

 </code>

 <p>ACL2 does not allow ``global variables'' in top-level input.  There is no
 ``top-level binding environment'' to give meaning to these variables.</p>

 <p>Thus, expressions involving no variables can generally be evaluated,</p>

 <code>
 ACL2 !&gt;<b>(equal (app (app '(1 2) '(3 4)) '(5 6))</b>
               <b>(app '(1 2) (app '(3 4) '(5 6))))</b>
 (1 2 3 4 5 6)
 </code>

 <p>but expressions containing variables cannot.</p>

 <p>There is an exception to this rule.  References to ``single-threaded
 objects'' may appear in top-level forms.  See @(see stobj) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>.  A
 single-threaded object is an ACL2 object, usually containing many fields,
 whose use is syntactically restricted so that it may be given as input only to
 certain functions and must be returned as output by certain functions.  These
 restrictions allow single- threaded objects to be efficiently manipulated.
 For example, only a single copy of the object actually exists, even though
 from a logical perspective one might expect the object to be ``copied on
 write.''</p>

 <p>The most commonly used single-threaded object in ACL2 is the ACL2 system
 state, whose current value is always held in the variable @(tsee state) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p>ACL2 provides a way for you to use @('state') to save values of
 computations at the top-level and refer to them later.  See @(see assign) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> and
 @(see @) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>")

(defxdoc |Functions for Manipulating these Objects|
  :parents (|Pages Written Especially for the Tours|)
  :short "Functions for Manipulating these Objects"
  :long "<p><see topic='@(url |Modeling in ACL2|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>Consider a typical ``stack'' of control frames.</p>

 <p><img src='res/tours/stack.gif'></img></p>

 <p>Suppose the model required that we express the idea of ``the most recent
 frame whose return program counter points into @('MAIN').''</p>

 <p>The natural expression of this notion involves</p>

 <p><b>function application</b> &mdash; ``fetch the @('return-pc') of this
 frame''</p>

 <p><b>case analysis</b> &mdash; ``<b>if</b> the pc is @('MAIN'), <b>then</b>
 ...''</p>

 <p><b>iteration</b> or <b>recursion</b> &mdash; ``pop this frame off and
 repeat.''</p>

 <p>The designers of ACL2 have taken the position that a <b>programming</b>
 <b>language</b> is the natural language in which to define such notions,
 <b>provided</b> the language has a mathematical foundation so that models can
 be analyzed and properties derived logically.</p>

 <p>Common Lisp is the language supported by ACL2.  To be precise, a small
 applicative subset of Common Lisp is the language supported by ACL2.</p>

 <p><see topic='@(url |Modeling in ACL2|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc gag-mode
  :parents (prover-output)
  :short "Verbosity of proof output"
  :long "<p>Please see @(see set-gag-mode) for an explanation of gag-mode,
 which can take any of the following values:</p>

 @({
  (gag-mode) ; generally evaluates to t, nil, or :goals
 })")

(defxdoc gc$
  :parents (miscellaneous acl2-built-ins)
  :short "Invoke the garbage collector"
  :long "<p>This function is provided so that the user can call the garbage
 collector of the host Lisp from inside the ACL2 loop.  Specifically, a call of
 @('gc$') is translated into a call of a function below on the same
 arguments.</p>

 @({
  Allegro CL:            excl:gc
  CCL                    ccl::gc
  CLISP                  ext:gc
  CMU Common Lisp        system::gc
  GCL                    si::gbc [default argument list: (t)]
  LispWorks              hcl::gc-generation [default argument list:
                                             (7) for 64-bit OS, else (3)]
  SBCL                   sb-ext:gc
 })

 <p>The arguments, if any, are as documented in the underlying Common Lisp.  It
 is up to the user to pass in the right arguments, although we may do some
 rudimentary checks.</p>

 <p>Also see @(see gc-verbose).</p>

 <p>Evaluation of a call of this macro always returns @('nil').</p>

 <p>To include @('gc$') in a book, one can use @('value-triple'):</p>

 @({
 (value-triple (gc$))
 })")

(defxdoc gc-strategy
  :parents (miscellaneous acl2-built-ins)
  :short "The garbage collection strategy"
  :long "<p>The form @('(gc-strategy state)') provides the value the current
 garbage collection strategy if that notion is supported by the underlying host
 lisp (currently, CCL only).  The logical story is that @('gc-strategy') reads
 its value from the @('oracle') field of the ACL2 @(tsee state).  The return
 value is thus a triple of the form @('(mv erp val state)'), where @('erp')
 will always be @('nil') in practice, and logically, @('val') is the top of the
 acl2-oracle field of the state (see @(tsee read-acl2-oracle)) and the returned
 state has the updated (popped) acl2-oracle.</p>

 <p>For more information, see @(see set-gc-strategy).</p>")

(defxdoc gc-verbose
  :parents (gc$)
  :short "Control printing from the garbage collector"
  :long "@({
  General Form:
  (gc-verbose arg &optional arg2)
 })

 <p>Garbage collection (gc) is performed by every Lisp implementation; see
 @(see gc$).  However, different ACL2 builds might see more or fewer messages.
 This macro is intended to provide an interface for controlling the verbosity,
 which is off if the (first) argument evaluates to @('nil') and otherwise is
 on.  The second (optional) argument is currently ignored except when the host
 Common Lisp implementation is CCL, where it specifies verbosity for EGC.</p>

 <p>The above functionality is only supported for the following host Common
 Lisp implementations: CCL, CMUCL, and GCL.  Otherwise, the only effect of this
 macro is to print a notice that it is not supported.  You are welcome to
 contact the ACL2 developers if you would like to help in adding such support
 for another host Common Lisp.</p>

 <p>Evaluation of a call of this macro always returns @('nil').</p>")

(defxdoc gcl
  :parents (miscellaneous)
  :short "Tips on building and using ACL2 based on Gnu Common Lisp"
  :long "<p>See the installation instructions for basic information about
 building ACL2 on top of GCL, including information about where to fetch GCL.
 Here, we provide some tips that may be useful.</p>

 <p>1. You can place forms to evaluate at start-up into file @('init.lsp') in
 the directory where you are starting ACL2 (GCL), or into file
 @('acl2-init.lsp') in your home directory.  For example, in order to evaluate
 both of the lisp forms mentioned in 2 below, you could put them both into
 @('init.lsp') in the current directory or in @('~/acl2-init.lsp') (either way,
 without @('(lp)') or @(':q')):</p>

 @({
  (setq si::*optimize-maximum-pages* nil)
  (si::allocate 'cons 75000 t)
 })

 <p>Note that if you want to put ACL2 patches in this file, you should precede
 them with (in-package \"ACL2\").</p>

 <p>2. Suppose you run out of space, for example with an error like this:</p>

 @({
     Error: The storage for CONS is exhausted.
       Currently, 59470 pages are allocated.
       Use ALLOCATE to expand the space.
 })

 <p>The following suggestion from Camm Maguire will minimize the heap size, at
 the cost of more garbage collection time.</p>

 @({
  :q   ; exit the ACL2 loop
  (setq si::*optimize-maximum-pages* nil)
  (lp) ; re-enter the ACL2 loop
 })

 <p>A second thing to try, suggested by several people, is to preallocate more
 pages before the run, e.g.:</p>

 @({
  :q   ; exit the ACL2 loop
  (si::allocate 'cons 75000 t)
  (lp) ; re-enter the ACL2 loop
 })

 <p>Also see @(see reset-kill-ring) for a suggestion on how to free up
 space.</p>

 <p>3. Windows users have seen this error:</p>

 @({
  cc1.exe: unrecognized option `-fno-zero-initialized-in-bss'
 })

 <p>Camm Maguire suggests that a solution may be to evaluate the following in
 GCL before building ACL2.</p>

 @({
  (in-package 'compiler)
  (let* ((x `-fno-zero-initialized-in-bss')
         (i (search x *cc*)))
          (setq *cc* (concatenate 'string
                                  (subseq *cc* 0 i)
                                  (subseq *cc* (+ i (length x))))))
 })

 <p>4. It is possible to profile using ACL2 built on GCL.  See file
 @('save-gprof.lsp') in the ACL2 source directory.</p>

 <p>5. Some versions of GCL may have garbage-collector bugs that, on rare
 occasions, cause ACL2 (when built on GCL) to break.  If you run into this, a
 solution may be to execute the following:</p>

 @({
  :q
  (si::sgc-on nil)
  (lp)
 })

 <p>Alternatively, put @('(si::sgc-on nil)') in your @('~/acl2-init.lsp')
 file.</p>

 <p>A full regression test and found that this decreased performance by about
 10%.  But even with that, GCL is probably one of the faster Common Lisp
 implementations for ACL2 on Linux.  Performance figures may often be found by
 following the ``Recent changes'' link on the ACL2 home page.</p>

 <p>6. GCL operations on numbers can sometimes be sped up, perhaps by up to two
 orders of magnitude, by suitable @(tsee declare) forms (also see @(see
 type-spec)).  The following example, developed with Warren Hunt and Serita
 Nelesen, illustrates the use of such declarations.</p>

 @({
  ; File iplus.lisp:
  ; Operations on naturals together with positive infinity (represented as -1).

  ; After (ld \"iplus.lisp\"), escape to raw Lisp with :q and then evaluate
  ; (disassemble 'big-test).  You should see lots of arithmetic operations
  ; in C code, but no calls of C functions CMPmake_fixnum or number_plus.

  (in-package \"ACL2\")

  (defmacro i-max ()
    (expt 2 (1- 28)))

  (defmacro i+ (x y)
    `(the (signed-byte 28)
          (let ((x ,x)
                (y ,y))
            (declare (type (signed-byte 28) x y))
            (cond ((or (< x 0)
                       (< y 0))
                   -1)
                  (t (let ((result
                            (the (signed-byte 29) (+ x y))))
                       (declare (type (signed-byte 29) result))
                       (cond ((>= result (i-max)) -1)
                             (t (the (signed-byte 28) result)))))))))

  (defmacro imin (x y)
    `(the (signed-byte 28)
          (let ((x ,x)
                (y ,y))
            (declare (type (signed-byte 28) x y))
            (cond ((< x 0)
                   (cond ((< y 0) -1)
                         (t y)))
                  ((< y 0)
                   x)
                  (t
                   (the (signed-byte 28) (min x y)))))))

  (defun big-test (x y z)
    (declare (type (signed-byte 28) x y z))
    (imin (i+ x y)
          (i+ y (imin x z))))
 })")

(defxdoc generalize
  :parents (rule-classes)
  :short "Make a rule to restrict generalizations"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 @({
  Example:
  (defthm integer-listp-rev
    (implies (integer-listp x)
             (integer-listp (rev x)))
    :rule-classes :generalize)

  General Form:
  any theorem
 })

 <p>To use a @(':generalize') rule, the system waits until it has decided to
 generalize some term, @('term'), by replacing it with some new variable
 @('v').  If any @(':generalize') formula can be instantiated so that some
 non-variable subterm becomes @('term'), then that instance of the formula is
 added as a hypothesis.  Thus for the example above, if the term @('(rev x2)')
 is generalized to the variable @('rv') during a proof, then the following is
 added as a hypothesis when generalizing to a new goal.</p>

 @({
  (implies (integer-listp x2)
           (integer-listp rv))
 })

 <p>At the moment, the best description of how ACL2 @(':generalize') rules are
 used may be found in the discussion of ``Generalize Rules,'' page 248 of A
 Computational Logic Handbook, or ``Generalization,'' page 132 of
 ``Computer-Aided Reasoning: An Approach.''  Also see @(see
 introduction-to-the-theorem-prover) for detailed tutorial on using ACL2 to
 prove theorems, which includes some discussion of generalization.</p>")

(defxdoc generalized-booleans
  :parents (common-lisp)
  :short "Potential soundness issues related to ACL2 predicates"
  :long "<p>The discussion below outlines a potential source of unsoundness in
 ACL2.  Although to our knowledge there is no existing Lisp implementation in
 which this problem can arise, nevertheless we feel compelled to explain this
 situation.</p>

 <p>Consider for example the question: What is the value of @('(equal 3 3)')?
 According to the ACL2 axioms, it's @('t').  And as far as we know, based on
 considerable testing, the value is @('t') in every Common Lisp implementation.
 However, according the Common Lisp draft proposed ANSI standard, any
 non-@('nil') value could result.  Thus for example, @('(equal 3 3)') is
 allowed by the standard to be @('17').</p>

 <p>The Common Lisp standard specifies (or soon will) that a number of Common
 Lisp functions that one might expect to return Boolean values may, in fact,
 return arbitrary values.  Examples of such functions are @(tsee equal), @(tsee
 rationalp), and @(tsee <); a much more complete list is given below.  Indeed,
 we dare to say that every Common Lisp function that one may believe returns
 only Booleans is, nevertheless, not specified by the standard to have that
 property, with the exceptions of the functions @('not') and @('null').  The
 standard refers to such arbitrary values as ``generalized Booleans,'' but in
 fact this terminology makes no restriction on those values.  Rather, it merely
 specifies that they are to be viewed, in an informal sense, as being either
 @('nil') or not @('nil').</p>

 <p>This situation is problematic for ACL2, which axiomatizes these functions
 to return Booleans.  The problem is that because (for efficiency and
 simplicity) ACL2 makes very direct use of compiled Common Lisp functions to
 support the execution of its functions, there is in principle a potential for
 unsoundness due to these ``generalized Booleans.''  For example, ACL2's @(tsee
 equal) function is defined to be Common Lisp's @('equal').  Hence if in Common
 Lisp the form @('(equal 3 3)') were to evaluate to 17, then in ACL2 we could
 prove (using the @(':')@(tsee executable-counterpart) of @(tsee equal))
 @('(equal (equal 3 3) 17)').  However, ACL2 can also prove @('(equal (equal x
 x) t)'), and these two terms together are contradictory, since they imply
 (instantiating @('x') in the second term by @('3')) that @('(equal 3 3)') is
 both equal to @('17') and to @('t').</p>

 <p>To make matters worse, the standard allows @('(equal 3 3)') to evaluate to
 <i>different</i> non-@('nil') values every time.  That is: @('equal') need not
 even be a function!</p>

 <p>Fortunately, no existing Lisp implementation takes advantage of the
 flexibility to have (most of) its predicates return generalized Booleans, as
 far as we know.  We may implement appropriate safeguards in future releases of
 ACL2, in analogy to (indeed, probably extending) the existing safeguards by
 way of guards (see @(see guard)).  For now, we'll sleep a bit better knowing
 that we have been up-front about this potential problem.</p>

 <p>The following list of functions contains all those that are defined in
 Common Lisp to return generalized Booleans but are assumed by ACL2 to return
 Booleans.  In addition, the functions @(tsee acl2-numberp) and @(tsee
 complex-rationalp) are directly defined in terms of respective Common Lisp
 functions @('numberp') and @('complexp').</p>

 @({
  /=
  <
  =
  alpha-char-p
  atom
  char-equal
  char<
  char<=
  char>
  char>=
  characterp
  consp
  digit-char-p
  endp
  eq
  eql
  equal
  evenp
  integerp
  keywordp
  listp
  logbitp
  logtest
  lower-case-p
  minusp
  oddp
  plusp
  rationalp
  standard-char-p
  string-equal
  string<
  string<=
  string>
  string>=
  stringp
  subsetp
  symbolp
  upper-case-p
  zerop
 })")

(defxdoc generalizing-key-checkpoints
  :parents (introduction-to-the-theorem-prover)
  :short "Getting rid of unnecessary specificity"
  :long "<p>Suppose @('MEMBER') determines whether its first argument is a
 member of its second, and @('SUBSETP') determines whether every element of its
 first argument is a member of its second.  Suppose that you're trying to prove
 some Main Theorem and are told the formula below is a key checkpoint.  What
 should you do?</p>

 @({
  Key Checkpoint:
  (IMPLIES (AND (CONSP A)
                (INTEGERP (CAR A))
                (MEMBER (CAR A) B)
                (SUBSETP (CDR A) B)
                (NOT (SUBSETP (CDR A) (APPEND B C))))
           (MEMBER (CAR A) C))
 })

 <p>The key observation is that the fourth hypothesis implies the negation of
 the fifth.  Writing it in the contrapositive:</p>

 @({
  (IMPLIES (AND ...
                (SUBSETP (CDR A) B)
                ...)
           (SUBSETP (CDR A) (APPEND B C)))
 })

 <p>In fact, that is more complicated than it needs to be.  A ``correct''
 response to the key checkpoint above is to prove</p>

 @({
  (defthm subsetp-append
    (implies (subsetp a b)
             (subsetp a (append b c)))).
 })

 <p>A still better response is to prove this:</p>

 @({
  (defthm subsetp-append-2
    (implies (or (subsetp a b)
                 (subsetp a c))
             (subsetp a (append b c)))).
 })

 <p>This version is better because it handles both of the possibilities
 regarding whether @('a') is a subset of the arguments of the @('append').</p>

 <p>It would be nice if we could think of a ``strong'' version, one in which
 @('(SUBSETP a (APPEND b c))') is rewritten to some clearly simpler term, but
 nothing comes to mind.</p>

 <p>In any case, if you cannot see any obvious simplification of the individual
 terms in the Key Checkpoint, you should ask yourself whether there are
 connections between the various propositional parts (as here, with the fourth
 and fifth hypotheses).  It is a good heuristic to look for relations between
 parts with the same top-level function symbol (as here, with @('SUBSETP')).
 It is also a good heuristic to throw out parts of the formula that seem
 disconnected (as here, with the terms involving @('(CAR A)')).</p>

 <p>This discussion suggests several ``modes'' of looking at key checkpoints
 and the idea of trying the modes in sequence:</p>

 <p>(1) look for simplifiable combinations of function symbols within
 propositional components,</p>

 <p>(2) look for relations between propositional components, and</p>

 <p>(3) throw out irrelevant or weakly connected components.</p>

 <p>In all cases you are bringing to bear your intuitions about the
 <i>semantics</i> of the terms.  That is, you're not just slinging symbols.
 You should be looking out for obvious truths about individual parts of the
 checkpoints...  truths that are obvious to you but not to ACL2!</p>

 <p>Ultimately the three ``modes'' are the same and we do not really recommend
 adhering to the given sequence.  You're just looking for simpler theorems
 that, in combination, imply the checkpoint.  Keeping the ``modes'' in mind may
 help focus your attention so you consider all the plausible possibilities.
 After a little experience you'll find yourself looking for all these things
 simultaneously as part ``cleaning up'' the checkpoints.</p>

 <p>When your main goal theorems are harder than these, your main concern will
 be looking at a Key Checkpoint and asking yourself ``why is this true?''  But
 you don't want to do that until you've cleaned it up ``locally'' as much as
 possible and sometimes &mdash; more often than you might think &mdash; local
 considerations can prove many of your checkpoints.</p>

 <p>If you have been working your way through the tutorial introduction to the
 theorem prover, use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-key-checkpoints).</p>")

(defxdoc get-command-sequence
  :parents (history)
  :short "Return list of @(see command)s that are between two @(see command) descriptors"
  :long "@({
  Examples:
  (get-command-sequence 4 12)
  :gcs 4 12 ; same as above
  (get-command-sequence 4 :x)
  :gcs 4 :x ; same as above
 })

 <p>See @(see pcs) for a utility that prints abbreviated information about the
 @(see command)s that are between two command descriptors.  The utility
 @('get-command-sequence') &mdash; or simply @('gcs'), so that you can just
 type @(':gcs') at the prompt &mdash; has the same syntax but instead of
 printing, it simply returns the corresponding list of commands.  More
 precisely, it returns an @(see error-triple) @('(mv erp val state)') such that
 if @('erp') is not @('nil'), then @('val') is the desired list of
 commands.</p>")

(defxdoc get-enforce-redundancy
  :parents (redundant-events)
  :short "Query the @(see world) on whether redundancy is being enforced"
  :long "<p>See @(see set-enforce-redundancy) for relevant background.  For a
 given world, @('wrld') &mdash; typically, @('(w state)') &mdash; the value of
 @('(get-enforce-redundancy wrld)') is @('nil'), @('t'), or @(':warn')
 according to the most recent call of @('set-enforce-redundancy'), @('nil') by
 default.</p>")

(defxdoc get-event-data
  :parents (system-utilities prover-output)
  :short "Obtain data stored after at the conclusion of an event"
  :long "<p>Warning: This is a low-level system utility that may change
 somewhat over time.  For more details, see the ACL2 source code.</p>

 <p>Evaluation of the form @('(get-event-data key state)') returns the value of
 @('key') in an association list, namely, in the value of @(see state) global
 variable @('last-event-data') (see @(see programming-with-state)).  That alist
 contains certain information stored at the conclusion of the immediately
 preceding event.  For each key the corresponding value, @('VAL'), is as
 follows.</p>

 <ul>

 <li>@('ABORT-CAUSES'): @('VAL') is a list of reasons why the proof aborted.
 In particular, if the value @('INTERRUPT') is in the list, then the proof was
 interrupted (typically with Control-C).</li>

 <li>@('FORM'): @('VAL') is the ``context'' for the event, printed in the
 summary, @(see warnings), and @(see errors).</li>

 <li>@('HINT-EVENTS'): @('VAL') is as in the corresponding field of the event
 summary.</li>

 <li>@('NAMEX'): @('VAL') is 0, a single name, or a list of names; see
 comments in ACL2 source function @('access-event-tuple-namex').</li>

 <li>@('PROVER-STEPS-COUNTED'): @('VAL') is as in the corresponding field of
 the event summary.</li>

 <li>@('RULES'): @('VAL') is as in the corresponding field of the event
 summary.</li>

 <li>@('SPLITTER-RULES'): @('VAL') represents the corresponding field of the
 event summary, as the list @('(case-split immed-forced if-intro)').</li>

 <li>@('TIME'): @('VAL') represents the corresponding field of the event
 summary, as the list @('(prove print proof-tree other)').</li>

 <li>@(' WARNINGS'): @('VAL') is as in the corresponding field of the event
 summary.</li>

 </ul>")

(defxdoc get-internal-time
  :parents (programming acl2-built-ins)
  :short "Runtime vs. realtime in ACL2 timings"
  :long "<p>The ACL2 system provides utilities that deal with elapsed time.
 The most visible of these is in the time summaries printed when completing
 evaluation of @(see events).  For others, see @(see with-prover-time-limit),
 see @(see read-run-time), see @(see time-tracker), see @(see
 time-tracker-tau), and see @(see pstack).</p>

 <p>By default, these utilities all use an underlying notion of run time
 provided by the host Common Lisp implementation: specifically, the Common Lisp
 function @('get-internal-run-time').  However, Common Lisp also provides the
 function @('get-internal-real-time'), which returns the real time (wall clock
 time).  While the latter is specified to measure elapsed time, the former is
 left to the implementation, which might well only measure time spent in the
 Lisp process.  Consider the following example, which is a bit arcane but
 basically sleeps for 2 seconds.</p>

 @({
    (defttag t) ; to allow sys-call
    (make-event
     (prog2$ (sys-call \"sleep\" '(\"2\"))
             (value '(value-triple nil))))
 })

 <p>A typical time summary might be as follows, drastically under-reporting the
 elapsed time.</p>

 @({
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
 })

 <p>However, you can instruct ACL2 to switch to using elapsed time (real time),
 in summaries and elsewhere, by evaluating the following form.</p>

 @({
    (assign get-internal-time-as-realtime t)
 })

 <p>To return to using runtime:</p>

 @({
    (assign get-internal-time-as-realtime nil)
 })

 <p>While the above example is rather silly, the issue becomes significant in
 time summaries for proofs that call out to external tools (see @(see sys-call)
 and see @(see clause-processor)).</p>

 <p>Note that a function @('get-internal-time') is defined in raw Lisp but is
 not available inside the ACL2 loop.  However, the expression @('(read-run-time
 state)') provides an interface to this function that is available inside the
 ACL2 loop; see @(see read-run-time).</p>

 <p>We are open to changing the default to elapsed wall-clock time (realtime),
 and may do so in future ACL2 releases.</p>

 <p>Implementation note (GCL only): If the host Lisp is Gnu Common Lisp, then
 @('get-internal-run-time') has a multiple value return, and the first two
 values (runtime and child runtime) are added together to produce a result for
 @('get-internal-time').</p>")

(defxdoc get-wormhole-status
  :parents (wormhole)
  :short "Make a wormhole's status visible outside the wormhole"
  :long "<p>General Form:
 (get-wormhole-status name state)</p>

 <p>@('Name') should be the name of a wormhole (see @(see wormhole)).  This
 function returns an @(see error-triple) of the form @('(mv nil s state)'),
 where @('s') is the status of the named wormhole.  The status is obtained by
 reading the oracle in the ACL2 @(tsee state).</p>

 <p>This function makes the status of a wormhole visible outside the wormhole.
 But since this function takes @(tsee state) and modifies it, the function may
 only be used in contexts in which you may change @(tsee state).  Otherwise,
 the wormhole status may stay in the wormhole.  See @(tsee wormhole-eval) and
 @(tsee wormhole).</p>")

(defxdoc getenv$
  :parents (programming-with-state acl2-built-ins)
  :short "Read an environment variable"
  :long "<p>@('(Getenv$ str state)'), where @('str') is a string, reads the
 value of environment variable @('str'), returning a value of @('nil') if none
 is found or if the read fails.  (Exception: if the value is not a legal ACL2
 string, say because it contains a character with @(tsee char-code) exceeding
 255, then an error is signaled.)  The logical story is that @('getenv$')
 reads its value from the @('oracle') field of the ACL2 @(tsee state).  The
 return value is thus a triple of the form @('(mv erp val state)'), where
 @('erp') will always be @('nil') in practice, and logically, @('val') is the
 top of the acl2-oracle field of the state (see @(tsee read-acl2-oracle)) and
 the returned state has the updated (popped) acl2-oracle.</p>

 @({
  Example:
  (getenv$ \"PWD\" state) ==> (mv nil \"/u/joe/work\" state)
 })

 <p>Also see @(see setenv$).</p>

 @(def getenv$)")

(defxdoc getprop
  :parents (world acl2-built-ins)
  :short "Access fast property lists"
  :long "@({
  General form:
  (getprop symb key default world-name world-alist)
 })

 <p>See @(see getpropc) for a convenient abbreviation, and see @(see world) for
 discussion of both utilities @('getprop') and @(tsee putprop).  Also see
 community book @('books/misc/getprop.lisp') for an example that illustrates
 the use of ACL2 utilities @('getprop') and @('putprop') to take advantage of
 under-the-hood Lisp (hashed) property lists.</p>

 @(def getprop)")

(defxdoc getpropc
  :parents (world acl2-built-ins)
  :short "Access fast property lists"
  :long "@({
  General form:
  (getpropc symb key &optional default world-alist)
 })

 <p>where @('default') is @('nil') if omitted, and @('world-alist') is @('(w
 state)') if omitted.  This is a convenient abbreviation for the common case in
 which @(tsee getprop) is used for system programming, with
 @(''current-acl2-world') as the (implicit, for @('getpropc'))
 world-name.</p>

 @(def getpropc)")

(defxdoc git-quick-start
  :parents (about-acl2)
  :short "Git quick start guide"
  :long "<p>Each of the two topics @(see github-commit-code-using-push) and
 @(see github-commit-code-using-pull-requests) presents a minimal guide to
 using the Github repository for ACL2+Books.  That <a
 href='https://github.com/acl2/acl2'>repository</a> exists on the web and
 contains the ``bleeding edge'' ACL2 source code and @(see community-books),
 available between ACL2 releases (see @(see release-notes)).  Those who are
 familiar with older version control systems, or perhaps with no version
 control systems, might find this guide to be helpful.  For additional
 information, including the use of branches and links to more information about
 git, see <a href='https://github.com/acl2/acl2/wiki/ACL2-repo-git-tips'>the
 wiki page for git tips</a>, @(see books-certification), and the Internet in
 general.  However, both of the above-mentioned guides are intended to be
 sufficient for you to obtain the latest ACL2 source code and community-books,
 and optionally, for you to contribute to the @(see community-books).</p>

 <p>Select the guide that is right for you based upon the headings below.</p>

 <h2>For non-contributors:</h2>

 See sections (A) and (B) in @(see github-commit-code-using-push).

 <h2>For infrequent contributors:</h2>

 For those only planning on contributing a few times per year (or less), see
 @(see github-commit-code-using-pull-requests).

 <h2>For frequent contributors:</h2>

 For those contributing on a monthly or weekly basis, see @(see
 github-commit-code-using-push).")

(defxdoc github-commit-code-using-push
  :parents (git-quick-start)
  :short "How to commit code to the books using direct push access"
  :long "<p>This guide is written for two groups of people:</p>

 <ul>

 <li>Users of the ACL2 System and Books who do not plan to contribute to the
 books, and</li>

 <li>Contributors who commit to the repository on a monthly or weekly basis.
 In this case, a contributor will typically begin with the @(see
 github-commit-code-using-pull-requests) method, and after they are familiar
 with the process and community, they will move to this method.</li>

 </ul>

 <h2>(A) GETTING STARTED</h2>

 <p>Start by obtaining an up-to-date copy of the web-based github repository.
 Here, we show how to put it into into a directory called <tt>ACL2</tt> (but
 name it whatever you like).</p>

 @({
 mkdir ACL2
 cd ACL2
 git clone https://github.com/acl2/acl2 .
 })

 <h2>(B) UPDATING</h2>

 <p>The following commands will update your directory to match the latest
 contents of the github repository (on the web).</p>

 @({
 git fetch --all
 git merge remotes/origin/master
 })

 <h2>(C) CONTRIBUTING (optional)</h2>

 <p>To join the <a href='https://github.com/acl2/acl2/'>github project</a>,
 please send email to one of the following individuals.</p>

 <ul>

 <li>Jared Davis (@('jared.c.davis@gmail.com'))</li>

 <li>David Rager (@('ragerdl@gmail.com'))</li>

 <li>Sol Swords (@('sswords@gmail.com'))</li>

 </ul>

 <p>After you have joined the project, you can proceed as follows when you are
 ready to contribute.</p>

 <h3>Change and Test</h3>

 <ol>

 <li>Update as in (B) above:

 @({
 git fetch --all
 git merge remotes/origin/master
 })</li>

 <li>Build an executable.

 @({
 (time nice make LISP=<your_lisp>) >& make.log
 })</li>

 <li>Make book changes.  If you are creating any new books, tell git that you
 intend to add them (but the repository on the web won't change until the last
 step below is executed).

 @({
 git add file1 file2 ...
 })

 Also, consider adding some high-level information about your changes to the
 Community Books' release notes &mdash; i.e., the appropriate @(see
 release-notes-books) XDOC topic in @('books/doc/relnotes.lisp').</li>

 <li>Run a regression.

 @({
 (time nice make -j 8 regression-fresh) >& make-regression.log
 })</li>

 <li>Look for failures, as indicated by @('**') in the log.

 @({
 fgrep -a '**' make-regression.log
 })</li>

 <li>If there were failures, then go back to Step 1 above to make appropriate
 changes and re-test, but you can replace the '@('make')' step by replacing
 @('regression-fresh') with @('regression'), since '@('make')' is clever enough
 to avoid recertifying more than is necessary.  For example:

 @({
 (time nice make -j 8 regression) >& make-regression-finish-1.log
 })

 Note that the @('-j 8') option specifies the use of 8 hardware threads; feel
 free to omit it or use a more suitable number (especially if your computer has
 other than 8 hardware threads).</li>

 </ol>

 <h3>Update, and Iterate If Necessary</h3>

 <p>Update again as in (B) above:</p>

 @({
 git fetch --all
 git merge remotes/origin/master
 })

 <blockquote>

 <p>The merge may fail if there have been remote updates, that is updates in
 the repository on the web.  In that case, commit your changes locally and then
 try the merge again.  You might want to use the @('-F') option instead of
 @('-m'); see the next section for more on those options.</p>

 @({
 git commit -a -m '<some message, with descriptive first line>'
 git merge remotes/origin/master
 })

 <p>If the second command prompts you for a message, the empty message should
 suffice as a reasonable default.  (In emacs, if vi tries to come up, just type
 @(':q') and @('<RETURN>').</p>

 </blockquote>

 <p>You can now go on to the next step (Contribute Your Changes).  But ideally:
 If the output indicates that anything has changed, then go back to ``Change
 and Test'' above.  Of course, you can skip the build if no ACL2 sources have
 changed, and you can skip making book changes if you are still happy with your
 changes.</p>

 <h3>Contribute Your Changes</h3>

 <p>The following commands will update the github repository on the web.  The
 @('-m ...') option is a log message whose first line should be a summary of
 your changes and other lines may give more details.  You are welcome to
 replace the @('-m ...') option by @('-F <filename>'), where @('<filename>') is
 the name of a file that contains your log message.</p>

 @({
  git commit -a -m '<some message, with descriptive first line>'
  git push origin testing
 })")

(defxdoc github-commit-code-using-pull-requests
  :parents (git-quick-start)
  :short "How to commit code to the books using pull requests"
  :long "<p>This guide is written for contributors who will probably only
 commit to the repository a few times a year. If you find yourself committing
 more often, you should see @(see github-commit-code-using-push).</p>

 A nice result of using pull requests is that all changes will be peer-reviewed
 before being committed.  Also, we sometimes call this method the <it>Fork and
 Pull</it> method.

 <h2>(A) GETTING STARTED</h2>

 <ol>

 <li>Go to <a
  href=\"https://github.com/acl2/acl2\">https://github.com/acl2/acl2</a> and
  click on the @('fork') button on the top-right.  Fork the repository into
  your github space.  This will create a new repository at
  @('https://github.com/<your-github-username>/acl2').</li>

 <li>In your working space on your computer, create a @('clone') of your github
  repository and @('cd') into it:

 @({
 git clone https://github.com/<your-github-username>/acl2
 cd acl2
 })</li>

 <li>Add the Community ACL2 repository as a git remote:

 @({
 git remote add upstream https://github.com/acl2/acl2
 })</li>

 </ol>

 <h2>(B) UPDATING</h2>

 <p>The following commands will update your local repository to match the latest
 contents of the ACL2 Community github repository (on the web).</p>

 @({
 git fetch --all
 git merge remotes/upstream/master
 })

 <h2>(C) CONTRIBUTING</h2>

 <h3>Change and Test</h3>

 <ol>

 <li>Before beginning your edits, update, as in (B) above:

 @({
 git fetch --all
 git merge remotes/upstream/master
 })</li>

 <li>Build an executable.

 @({
 (time nice make LISP=<your_lisp>) >& make.log
 })</li>

 <li>Make book changes.  If you are creating any new books, tell git that you
 intend to add them (but the local repository on the web won't change until the
 @('commit') step below is executed).

 @({
 git add file1 file2 ...
 })

 Also, consider adding some high-level information about your changes to the
 Community Books' release notes &mdash; i.e., the appropriate @(see
 release-notes-books) XDOC topic in @('books/doc/relnotes.lisp').</li>

 <li>Run a regression.

 @({
 (time nice make -j 8 regression-fresh) >& make-regression.log
 })

 Note that the @('-j 8') option specifies the use of 8 hardware threads; feel
 free to omit it or use a more suitable number (especially if your computer has
 other than 8 hardware threads). </li>

 <li>Look for failures, as indicated by @('**') in the log.

 @({
 fgrep -a '**' make-regression.log
 })</li>

 <li>If there were failures, then go back to Step 1 above to make appropriate
 changes and re-test, but you can replace the '@('make')' step by replacing
 @('regression-fresh') with @('regression'), since '@('make')' is clever enough
 to avoid recertifying more than is necessary.  For example:

 @({
 (time nice make -j 8 regression) >& make-regression-finish-1.log
 })</li>

 </ol>

 <h3>Update, and Iterate If Necessary</h3>

 <p>Update again as in (B) above:</p>

 @({
 git fetch --all
 git merge remotes/upstream/master
 })

 <blockquote>

 <p>The merge may fail if there have been remote updates, that is updates in
 the repository on the web.  In that case, commit your changes locally and then
 try the merge again.  You might want to use the @('-F') option instead of
 @('-m'); see the next section for more on those options.</p>

 @({
 git commit -a -m '<some message, with descriptive first line>'
 git merge remotes/upstream/master
 })

 <p>If the second command (the @('git merge')) prompts you for a message, the
 empty message should suffice as a reasonable default (in emacs &mdash; if vi
 tries to come up, just type @(':q') and @('<RETURN>').</p>

 </blockquote>

 <p>You can now go on to the next step (Contribute Your Changes).  But ideally:
 If the output indicates that anything has changed, then go back to ``Change
 and Test'' above.  Of course, you can skip the build if no ACL2 sources have
 changed, and you can skip making book changes if you are still happy with your
 changes.</p>

 <h3>Contribute Your Changes</h3>

 <p>The following commands will update your github repository on the web.  The
 @('-m ...') option is a log message whose first line should be a summary of
 your changes and other lines may give more details.  You are welcome to
 replace the @('-m ...') option by @('-F <filename>'), where @('<filename>') is
 the name of a file that contains your log message.</p>

 @({
  git commit -a -m '<some message, with descriptive first line>'
  git push
 })

 You now need to create a <it>pull request</it>, where you request that changes
 from your github repository be accepted into the Community ACL2 repository.
 To achieve this:

 <ol>

 <li>Goto @('https://github.com/<your-github-username>/acl2').</li>

 <li>Click the @('Pull request') button (you can search for it with your
 browser).</li>

 <li>In the drop-down box labeled \"base\" (next to the box labeled \"base
 fork\"), change the value from \"master\" to \"testing\".</li>

 <li>Click @('Create pull request').</li>

 <li>Put some explanation about what's in the changes in the comments section.
 It's helpful if you quote (possibly abbreviated) versions of your commit log
 messages here, as that way the descriptions are easily read when clicking on
 the Community Repository @('commits') tab, which goes to <a
 href=\"https://github.com/acl2/acl2/commits/master\">
 https://github.com/acl2/acl2/commits/master</a>.</li>

 <li>Click @('Create pull request').</li>

 </ol>
 At this point, the Community ACL2 repository maintainers will be notified,
 check that things seem to be in order, and then adopt your changes.")

(defxdoc goal-spec
  :parents (hints)
  :short "To indicate where a hint is to be used"
  :long "@({
  Examples:
  \"Goal\"
  \"goal\"
  \"Subgoal *1/3''\"
  \"subgoal *1/3''\"
  \"[2]Subgoal *1/3''\"
 })

 <p>When @(see hints) are given to the theorem prover, a goal-spec is provided
 to specify the goal to which the @(see hints) are to be applied.  The @(see
 hints) provided are carried along innocuously until the named goal arises.
 When it arises, the @(see hints) are ``activated'' for that goal and its
 descendents.</p>

 <p>A legal goal specification may be extracted from the theorem prover's
 output.  Certain lines clearly label formulas, as in</p>

 @({
  Subgoal *1/3.2'
  (IMPLIES ... ...)
 })

 <p>and these lines all give rise to goal specifications.  In general, these
 lines all start either with ``Goal'' or ``Subgoal'' or else with those words
 preceded by a number in square brackets, as in</p>

 @({
  [1]Subgoal *1/3.2'
  (IMPLIES ... ...).
 })

 <p>A goal specification may be obtained by deleting any surrounding whitespace
 from such a line and embedding the text in string quotation marks.  Thus</p>

 @({
  \"[1]Subgoal *1/3.2'\"
 })

 <p>is the goal specifier for the goal above.</p>

 <p>As noted, a hint is applied to a goal when the hint's goal specification
 matches the name ACL2 assigns to the goal.  The matching algorithm is
 case-insensitive.  Thus, alternative goal specifications for the goal above
 are @('\"[1]subgoal *1/3.2'\"') and @('\"[1]SUBGOAL *1/3.2'\"').  The matching
 algorithm does not tolerate non-case discrepancies.  Thus,
 @('\"[1]Subgoal*1/3.2'\"') and @('\" [1]Subgoal *1/3.2'\"') are
 unacceptable.</p>

 <p>Sometimes a formula is given two names, e.g.,</p>

 @({
  Subgoal *1/14.2'
  (IMPLIES ...
           ...)
  Name the formula above *1.1.
 })

 <p>It is the first name (the one that starts with ``Goal'' or ``Subgoal'') and
 not the second which constitutes a legal goal-spec.  Roughly speaking, when
 the system prints the line containing the goal specification, it activates any
 @(see hints) that are attached to that goal-spec.  Consider the example above.
 Suppose @('Subgoal *1/14.2'') could be proved by using a certain lemma
 instance.  Then the appropriate entry in the @(see hints) would be:</p>

 @({
  (\"Subgoal *1/14.2'\" :use ...)
 })

 <p>This might surprise you because the system appears to do nothing to
 @('*1/14.2'') besides push it for a subsequent induction.  But actually
 between the time the system printed the goal-spec line and the time it decides
 to push the goal, you can think of the system as trying everything it has.  So
 a @('use') hint activated when @('Subgoal *1/14.2'') arises is just what you
 want.</p>

 <p>But what if you want to give an @(':induct') hint?  By the time induction
 is tried, the formula has been given the name @('*1.1').  Well, this is one
 you just have to remember:</p>

 @({
  (\"Subgoal *1/14.2'\" :induct ...).
 })

 <p>When the above hint is activated the @(':induct') directive short-circuits
 the rest of the processing and sends immediately the formula into the pool of
 goals to prove by induction.  The induct hint is attached to the formula in
 the pool and when the time comes to turn our attention to that goal, the
 induct advice is followed.</p>

 <p>We conclude by emphasizing a point made above, that a hint is applied to a
 goal when the hint's goal specification matches the name ACL2 assigns to the
 goal.  If there is no such match, then the hint is ignored.  Consider the
 following example.</p>

 @({
  (thm (equal (append (append x y) z) (append x y z))
       :hints ((\"Subgoal *1/\" :in-theory nil)))
 })

 <p>Normally, @(':in-theory') hints are inherited by subgoals (see @(see
 hints-and-the-waterfall)), so you might expect that the empty theory is used
 in @('Subgoal *1/2') and @('Subgoal *1/1').  But in fact, since there is no
 subgoal printed that is labeled @('Subgoal *1/'), the above @(':in-theory')
 hint is ignored.  The above example is in contrast to the following, where the
 hint makes the proof fail, because there really is a @('Subgoal *1/') in the
 proof this time.</p>

 @({
  (thm (implies (and (not (endp x)) (not (endp (cdr x))))
                (equal (append (append x y) z) (append x y z)))
       :hints ((\"Subgoal *1/\" :in-theory nil)))
 })")

(defxdoc good-atom-listp
  :parents (atom lists acl2-built-ins)
  :short "Recognizer for a true list of ``good'' @(see atom)s"
  :long "<p>The predicate @('good-atom-listp') tests whether its argument is a
 @(tsee true-listp) of ``good'' @(see atom)s, i.e., where each element is a
 number, a symbol, a character, or a string.</p>

 <p>Also see @(see atom-listp).</p>

 @(def good-atom-listp)")

(defxdoc good-bye
  :parents (basics acl2-built-ins)
  :short "Quit entirely out of Lisp"
  :long "@({
  Examples:
  ACL2 !>(good-bye)
  ; [ACL2 is exited]

  ACL2 !>(good-bye 3)
  ; [ACL2 is exited with Unix exit status 3]
 })

 <p>Note: Your entire session will disappear forever when you evaluate
 @('(good-bye)').</p>

 <p>The command @('(good-bye)') quits not only out of the ACL2 @(see command)
 loop, but in fact quits entirely out of the underlying Lisp.  Thus, there is
 no going back!  You will <b>not</b> be able to re-enter the @(see command)
 loop after typing @('(good-bye)')!  All your work will be lost!!!</p>

 <p>This command may not work in some underlying Common Lisp implementations.
 In such cases, there is no harm in trying; ACL2 will let you know how to
 proceed if it cannot exit.</p>

 <p>In some systems, typing @('control-d') at the top-level ACL2 prompt
 (@('control-c control-d') if inside emacs) will call this function.</p>

 <p>The optional argument for @('good-bye') (default 0) indicates the
 Unix (Linux) exit status.  If it is not an integer, it will be treated as
 0.</p>

 <p>If you merely want to exit the ACL2 @(see command) loop, use @(':q')
 instead (see @(see q)).</p>

 <p>We conclude with the following technical remark, to be ignored unless you
 are trying to do things in raw Lisp that involve quitting the session.  The
 mechanism that ACL2 and Lisp use for quitting the session is slightly
 involved.  In particular, if you trace the underlying raw Lisp function
 @('exit-lisp'), you may see that it is called twice; the second call happens
 while cleaning up from an @('unwind-protect') call.</p>")

(defxdoc granularity
  :parents (parallel-programming)
  :short "Limit the amount of parallelism"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 <p>Some function calls are on arguments whose evaluation time is long enough
 to warrant parallel execution, while others are not.  A granularity form can
 be used to make appropriate restrictions on the use of parallelism.</p>

 <p>For example, consider the Fibonacci function.  Experiments have suggested
 that execution time can be reduced if whenever the argument is less than 27, a
 serial version of the Fibonacci function is called.  One way to utilize this
 information is to write two definitions of the Fibonacci function, one serial
 and one parallel.</p>

 @({
  (defun fib (x)
    (declare (xargs :guard (natp x)))
    (cond ((or (zp x) (<= x 0)) 0)
          ((= x 1) 1)
          (t (binary-+ (fib (- x 1))
                       (fib (- x 2))))))

  (defun pfib (x)
    (declare (xargs :guard (natp x)))
    (cond ((or (zp x) (<= x 0)) 0)
          ((= x 1) 1)
          ((< x 27) (binary-+ (fib (- x 1))
                              (fib (- x 2))))
          (t (pargs (binary-+ (pfib (- x 1))
                              (pfib (- x 2)))))))
 })

 <p>We realize quickly that writing both of these function definitions is
 cumbersome and redundant.  This problem can be avoided by using a
 @('granularity') declaration with a parallelism primitive.  This form ensures
 that a call is parallelized only if resources are available and the
 granularity form evaluates to a non-@('nil') value at the time of the call.
 Below is a definition of the Fibonacci function using a granularity form.</p>

 @({
  (defun pfib (x)
    (declare (xargs :guard (natp x)))
    (cond ((or (zp x) (<= x 0)) 0)
          ((= x 1) 1)
          (t (pargs (declare (granularity (>= x 27)))
                    (binary-+ (pfib (- x 1))
                              (pfib (- x 2)))))))
 })

 <p>A granularity form can reference an extra formal parameter that describes
 the call depth of the function the user is parallelizing.  Consider for
 example the following parallel @('mergesort') function, based on Davis's
 Ordered Sets library.  It splits the data into symmetric chunks for
 computation, so we increment the @('depth') argument during the recursive call
 on both the @('car') and @('cdr').</p>

 @({
  (include-book \"finite-set-theory/osets/sets\" :dir :system)
  (defun set::pmergesort-exec (x depth)
    (declare (xargs :mode :program))
    (cond ((endp x) nil)
          ((endp (cdr x)) (set::insert (car x) nil))
          (t (mv-let (part1 part2)
                     (set::split-list x nil nil)
                     (pargs
                      (declare (granularity (< depth 2)))
                      (set::union (set::pmergesort-exec part1
                                                          (1+ depth))
                                   (set::pmergesort-exec part2
                                                          (1+ depth))))))))
 })

 <p>A less intrusive method (i.e., not requiring an extra formal parameter like
 the @('depth') argument just above), which however can be less efficient,
 involves analyzing the data itself for structural properties.  For
 example:</p>

 @({
  (defun some-depth-exceeds (x n)
    (declare (xargs :guard (natp n)))
    (if (atom x)
        nil
      (if (zp n)
          t
        (or (some-depth-exceeds (car x) (1- n))
            (some-depth-exceeds (cdr x) (1- n))))))

  (defun valid-tip (x)
    (declare (xargs :guard t))
    (or (eq x 'A)
        (eq x 'T)
        (eq x 'C)
        (eq x 'G)))

  (defun pvalid-tree (x)
    (declare (xargs :guard t))
    (if (atom x)
        (valid-tip x)
      (pand (declare (granularity (some-depth-exceeds x 3)))
            (pvalid-tree (car x))
            (pvalid-tree (cdr x)))))
 })

 <p>If you experiment with calls of @('pvalid-tree'), you are likely to find
 that the ``speedup'' it provides over a corresponding serial version is, in
 fact, a slowdown!  The problem is likely that @('some-depth-exceeds') is an
 expensive function to run repeatedly.  Instead of the approach above, it is
 often handy to add an extra formal parameter in order to allow for more
 efficient granularity forms, as we have done above in the definition of
 @('SET::pmergesort-exec').</p>")

(defxdoc ground-zero
  :parents (theories theory-functions)
  :short "@(see enable)d rules in the @(see startup) theory"
  :long "<p>ACL2 concludes its initialization @('(boot-strapping)') procedure
 by defining the theory @('ground-zero'); see @(see theories).  In fact, this
 theory is just the theory defined by @('(current-theory :here)') at the
 conclusion of initialization; see @(see current-theory).</p>

 <p>Note that by evaluating the event</p>

 @({
  (in-theory (current-theory 'ground-zero))
 })

 <p>you can restore the current theory to its value at the time you started up
 ACL2.</p>")

(defxdoc gthm
  :parents (history guard-formula-utilities)
  :short "The @(see guard) theorem for a given function symbol"
  :long "<p>This utility (pronounced ``gee-thumb'') generates the guard proof
 obligation for a given function symbol.</p>

 @({
 Example Forms:
 :gthm FN
 (gthm 'FN)       ; equivalent to the above
 (gthm 'FN t nil) ; equivalent to the above
 (gthm 'FN nil t) ; avoid any simplification and include guard-debug info

 General Forms:
 :gthm FN ; equivalent to (gthm 'FN)
 (gthm x &optional simp-p guard-debug)
 })

 <p>where @('FN') is a function symbol and @('x') evaluates to a function
 symbol.  Evaluation returns the user-level (untranslated) version of that
 guard theorem.  The optional argument @('simp-p'), described below, is @('t')
 by default.  The optional argument @('guard-debug') is @('nil') by default;
 when non-@('nil'), the guard theorem is modified as with the option
 @(':guard-debug') for @(tsee verify-guards); see @(see guard-debug).</p>

 <p>See @(see lemma-instance) for how to provide the result of @(':gthm') as a
 @(':guard-theorem') prover hint.  Also see @(see guard-formula-utilities) for
 related utilities.</p>

 <p>Normally one will evaluate @(':gthm FN') or equivalently (see @(see
 keyword-commands)), the form @('(gthm 'FN)').  In this case the guard theorem
 may be simplified before it is returned, by using a form of ``subsumption'' to
 eliminate redundancy and by deleting tautologies as well as instances of @(see
 built-in-clause) rules that come with ACL2.  The @('simp-p') argument should
 be @('nil') to avoid such simplification; that is, use @('(gthm 'FN
 nil)').</p>

 <p>Note that the result from evaluating @('(gthm x simp-p guard-debug)') is an
 <i>untranslated</i> term, that is, a user-level term; see @(see termp).  The
 corresponding call @('(guard-theorem x simp-p guard-debug (w state) state)')
 returns a translated term.</p>")

(defxdoc guard
  :parents (programming xargs)
  :short "Restricting the domain of a function"
  :long "<p>NOTE: Novices are often best served by avoiding guards.</p>

 <p>The ACL2 system provides a mechanism for restricting a function to a
 particular domain.  Such restrictions are called ``guards.''  A definition's
 guard has no effect on the logical axiom added when that definition is
 accepted by ACL2.  Moreover, the guard has NO EFFECT on the proof that a
 recursive definition is admissible &mdash; informally, that it terminates).
 (See @(see mbt) for a discussion of one way to use the guard explicitly to
 assist with that proof while avoiding execution overhead.)</p>

 <p>Guards can be useful as a specification device or for increasing execution
 efficiency.  To make such a restriction, use the @(':guard') keyword (see
 @(see xargs)) or, especially if you want the host Lisp compiler to use this
 information, use @('type') declarations (see @(see declare); also see @(see
 xargs) for a discussion of the @(':split-types') keyword).  The general issue
 of guards and guard verification is discussed in the topics listed below.</p>

 <p>To begin further discussion of guards, see @(see guard-introduction).  That
 section directs the reader to further sections for more details.  To see just
 a summary of some @(see command)s related to guards, see @(see
 guard-quick-reference).  For a discussion of the use of proof to verify the
 absence of guard violations, see @(see verify-guards).</p>")

(defxdoc guard-checking-inhibited
  :parents (evaluation guard)
  :short "Evaluating ACL2 expressions"
  :long "<p>ACL2 sometimes omits the checking of @(see guard)s on recursive
 calls of functions.  This omission is signaled by a message like the one shown
 below.</p>

 @({
 ACL2 !>(factorial 3)

 ACL2 Warning [Guards] in TOP-LEVEL:  Guard-checking will be inhibited
 for some recursive calls for FACTORIAL and perhaps other functions;
 see :DOC guard-checking-inhibited.

 6
 ACL2 !>
 })

 <p>More precisely, the warning is printed only when guard-checking is the
 default, @('t') (see @(see set-guard-checking)) and guards are not verified
 for the indicated function.  No further such message is printed (for any
 function) before the next top-level form is submitted.</p>

 <p>To check guards on all recursive calls:</p>

 @({
 (set-guard-checking :all)
 })

 <p>To leave the current behavior unchanged except for inhibiting such
 messages:</p>

 @({
 (set-guard-checking :nowarn)
 })")

(defxdoc guard-debug
  :parents (guard debugging)
  :short "Generate markers to indicate sources of @(see guard) proof obligations"
  :long "<p>ACL2 guard verification (see @(see guard)) is often best avoided by
 beginning users of ACL2.  When guard verification is employed, it can generate
 numerous goals, some of which may not be theorems if the definition being
 processed has bugs.  It can be difficult to find such bugs.  This @(see
 documentation) topic explains a capability provided by ACL2 to help find such
 bugs.</p>

 <p>For a similar utility appropriate for proving @(see measure) conjectures
 (that is, for termination proofs), see @(see measure-debug).</p>

 <p>We begin with the following example.  Although it is contrived and a bit
 simplistic, it illustrates how the guard-debug utility works.</p>

 @({
  (defun length-repeat (x)
    (length (append x x)))
  (verify-guards length-repeat :guard-debug t)
 })

 <p>The output produces two top-level key checkpoints, as follows.</p>

 @({
  Subgoal 2
  (IMPLIES (EXTRA-INFO '(:GUARD (:BODY LENGTH-REPEAT))
                       '(APPEND X X))
           (TRUE-LISTP X))

  Subgoal 1
  (IMPLIES (AND (EXTRA-INFO '(:GUARD (:BODY LENGTH-REPEAT))
                            '(LENGTH (APPEND X X)))
                (NOT (TRUE-LISTP (APPEND X X))))
           (STRINGP (APPEND X X)))
 })

 <p>The upper subgoal (numbered 2) says that the body of the definition of
 @('length-repeat') contains a call @('(APPEND X X)'), which is the source of
 the goal.  In this case, that makes sense: the @(see guard) for a call
 @('(append arg1 arg2)') is @('(true-listp arg1)'), which in this case is
 @('(TRUE-LISTP X)').  The lower subgoal (numbered 1) says that the same
 definition contains the call @('(LENGTH (APPEND X X))'), which generates the
 proof obligation that if @('(APPEND X X)') does not satisfy @('true-listp'),
 then it must satisfy @('stringp').  That proof obligation comes directly from
 the @(see guard) for @(tsee length).</p>

 <p>Of course, the example above is a bit obvious.  But for large definitional
 bodies such information can be very helpful.  Note that guard-debug can be
 specified not only in @(tsee verify-guards) events but also in @(tsee xargs)
 @(tsee declare) forms of @(tsee defun) events.</p>

 <p>We now describe the guard-debug utility in some detail.</p>

 <p>@('(Extra-info x y)') always returns @('t') by definition.  However, if
 @(see guard) verification takes place with a non-@('nil') setting of
 @('guard-debug') (see below), then the goals generated for guard verification
 can include hypotheses that are calls of @('extra-info').  Typically, such a
 hypothesis is of the following form:</p>

 @({
  (extra-info '(:guard (:body F))
              '(G ARG1 ... ARGk))
 })

 <p>The above form indicates that the goal in which it occurs was generated to
 verify that the @(see guard) of the function @('F') is satisfied by the
 arguments @('ARG1') through @('ARGk'), where the term @('(G ARG1 ... ARGk)')
 occurs in the body of the function @('F') whose guard verification is in
 progress.  If however the above call of @('G') occurs in the guard of @('F')
 instead of the body of @('F'), then @(':body') is replaced by @(':guard')
 above:</p>

 @({
  (extra-info '(:guard (:guard F))
              '(G ARG1 ... ARGk))
 })

 <p>If the same proof obligation (goal clause) arises from more than one
 occurrence of the same call, then a single goal will be generated, which has
 several @('extra-info') hypotheses added to show the multiple sources of that
 proof obligation.</p>

 <p>All rules (see @(see rune)) associated with @('extra-info') are @(see
 disable)d by default, so that hypotheses of the form described above are not
 simplified to @('t').  These hypotheses are intended to ride along for free:
 you can generally expect the proof to have the same structure whether or not
 the @(':guard-debug') option is supplied, though on rare occasions the proofs
 may diverge.</p>

 <p>It remains to explain the notion of a @('guard-debug') setting of @('t'),
 that is, to explain how to obtain the additional hypotheses described above.
 If guards are being verified during processing of a @(tsee defun) event
 (whether or not inside a call of @(tsee mutual-recursion)), then one specifies
 @(':guard-debug t') in an @(tsee xargs) declaration of a @(tsee declare) form;
 see @(see xargs).  If however the guard verification is on behalf of a @(tsee
 verify-guards) call, whether for a definition or a theorem, then one specifies
 the keyword argument @(':guard-debug t').</p>

 <p>Also see @(see print-gv) for a utility for debugging guard violations, in
 contrast to the above guard-debug mechanism, which is for debugging failed
 proofs arising from guard verification.</p>")

(defxdoc guard-evaluation-examples-log
  :parents (guard)
  :short "Log showing combinations of @(see defun-mode)s and @(see
 guard)-checking"
  :long "<p>See @(see guard-evaluation-examples-script) for a script that shows
 the interaction of @(see defun-mode)s with the value set by @(tsee
 set-guard-checking).  Here, we present a log resulting from running this
 script.  It may also be helpful to see @(see evaluation).</p>

 <p>See @(see set-guard-checking) for discussion of the interaction between
 @(see defun-mode)s and @(see guard)-checking that is illustrated by this
 script.  Also see @(see guard-evaluation-table) for a succinct table, with
 associated discussion, that covers in detail the interactions illustrated
 here.</p>

 @({
  ACL2 !>(defun fact (x)
           (declare (xargs :guard (integerp x)
                           :mode :program))
           (if (posp x)
               (* x (fact (1- x)))
             1))

  Summary
  Form:  ( DEFUN FACT ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FACT
  ACL2 !>(trace$ fact)
   ((FACT))
  ACL2 !>:set-guard-checking t

  Guard-checking-on already has value T.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)

  ACL2 Error in TOP-LEVEL:  The guard for the :program function symbol
  FACT, which is (INTEGERP X), is violated by the arguments in the call
  (FACT T).  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 !>:set-guard-checking :all

  Leaving guard checking on, but changing value to :ALL.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)

  ACL2 Error in TOP-LEVEL:  The guard for the :program function symbol
  FACT, which is (INTEGERP X), is violated by the arguments in the call
  (FACT T).  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 !>: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 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:set-guard-checking nil

  Masking guard violations but still checking guards except for self-
  recursive calls.  To avoid guard checking entirely, :SET-GUARD-CHECKING
  :NONE.  See :DOC set-guard-checking.

  ACL2 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
    2> (FACT T)
    <2 (FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:u

            0:x(EXIT-BOOT-STRAP-MODE)
  ACL2 >(defun fact (x)
           (declare (xargs :guard t
                           :mode :program))
           (if (posp x)
               (* x (fact (1- x)))
             1))

  Summary
  Form:  ( DEFUN FACT ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FACT
  ACL2 >(trace$ fact)
   ((FACT))
  ACL2 >:set-guard-checking t

  Turning guard checking on, value T.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
    2> (FACT T)
    <2 (FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 !>:set-guard-checking :all

  Leaving guard checking on, but changing value to :ALL.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  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 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:set-guard-checking nil

  Masking guard violations but still checking guards except for self-
  recursive calls.  To avoid guard checking entirely, :SET-GUARD-CHECKING
  :NONE.  See :DOC set-guard-checking.

  ACL2 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
    2> (FACT T)
    <2 (FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:u

            0:x(EXIT-BOOT-STRAP-MODE)
  ACL2 >(defun fact (x)
           (declare (xargs :guard (integerp x)
                           :verify-guards nil
                           :mode :logic))
           (if (posp x)
               (* x (fact (1- x)))
             1))

  For the admission of FACT we will use the relation O< (which is known
  to be well-founded on the domain recognized by O-P) and the measure
  (ACL2-COUNT X).  The non-trivial part of the measure conjecture is

  [[output omitted here]]

  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FACT
  ACL2 >(trace$ fact)
   ((FACT))
  ACL2 >:set-guard-checking t

  Turning guard checking on, value T.

  ACL2 !>(fact 2)
  [[Comment added to the log:
    Normally you would get a message about guard-checking being
    inhibited on recursive calls.  However, when a function is
    traced the guard-checking is done on recursive calls unless
    the guards have been verified (see :DOC verify-guards).
  ]]
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)

  ACL2 Error in TOP-LEVEL:  The guard for the function symbol FACT, which
  is (INTEGERP X), is violated by the arguments in the call (FACT T).
  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 !>:set-guard-checking :all

  Leaving guard checking on, but changing value to :ALL.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)

  ACL2 Error in TOP-LEVEL:  The guard for the function symbol FACT, which
  is (INTEGERP X), is violated by the arguments in the call (FACT T).
  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 !>: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 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:set-guard-checking nil

  Masking guard violations but still checking guards except for self-
  recursive calls.  To avoid guard checking entirely, :SET-GUARD-CHECKING
  :NONE.  See :DOC set-guard-checking.

  ACL2 >(fact 2)
  [[Comment added to the log:
    In spite of the warning above, guards are checked here on
    self-recursive calls, because the function is traced.
  ]]
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >(verify-guards fact)

  Computing the guard conjecture for FACT....

  The guard conjecture for FACT is trivial to prove, given the :compound-
  recognizer rule POSP-COMPOUND-RECOGNIZER, primitive type reasoning
  and the :type-prescription rule FACT.  FACT is compliant with Common
  Lisp.

  Summary
  Form:  ( VERIFY-GUARDS FACT)
  Rules: ((:COMPOUND-RECOGNIZER POSP-COMPOUND-RECOGNIZER)
          (:FAKE-RUNE-FOR-TYPE-SET NIL)
          (:TYPE-PRESCRIPTION FACT))
  Warnings:  None
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
   FACT
  ACL2 >(trace$ fact)
   ((FACT))
  ACL2 >:set-guard-checking t

  Turning guard checking on, value T.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)

  ACL2 Error in TOP-LEVEL:  The guard for the function symbol FACT, which
  is (INTEGERP X), is violated by the arguments in the call (FACT T).
  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 !>:set-guard-checking :all

  Leaving guard checking on, but changing value to :ALL.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)

  ACL2 Error in TOP-LEVEL:  The guard for the function symbol FACT, which
  is (INTEGERP X), is violated by the arguments in the call (FACT T).
  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 !>: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 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:set-guard-checking nil

  Masking guard violations but still checking guards except for self-
  recursive calls.  To avoid guard checking entirely, :SET-GUARD-CHECKING
  :NONE.  See :DOC set-guard-checking.

  ACL2 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:u
   L        1:x(DEFUN FACT (X) ...)
  ACL2 >:u
            0:x(EXIT-BOOT-STRAP-MODE)
  ACL2 >(defun fact (x)
           (declare (xargs :guard (integerp x)
                           :mode :logic))
           (if (posp x)
               (* x (fact (1- x)))
             1))

  For the admission of FACT we will use the relation O< (which is known
  to be well-founded on the domain recognized by O-P) and the measure
  (ACL2-COUNT X).  The non-trivial part of the measure conjecture is

  [[output omitted here]]

  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FACT
  ACL2 >(trace$ fact)
   ((FACT))
  ACL2 >:set-guard-checking t

  Turning guard checking on, value T.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)

  ACL2 Error in TOP-LEVEL:  The guard for the function symbol FACT, which
  is (INTEGERP X), is violated by the arguments in the call (FACT T).
  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 !>:set-guard-checking :all

  Leaving guard checking on, but changing value to :ALL.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)

  ACL2 Error in TOP-LEVEL:  The guard for the function symbol FACT, which
  is (INTEGERP X), is violated by the arguments in the call (FACT T).
  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 !>: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 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:set-guard-checking nil

  Masking guard violations but still checking guards except for self-
  recursive calls.  To avoid guard checking entirely, :SET-GUARD-CHECKING
  :NONE.  See :DOC set-guard-checking.

  ACL2 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:u
            0:x(EXIT-BOOT-STRAP-MODE)
  ACL2 >(defun fact (x)
           (declare (xargs :guard t
                           :verify-guards nil
                           :mode :logic))
           (if (posp x)
               (* x (fact (1- x)))
             1))

  For the admission of FACT we will use the relation O< (which is known
  to be well-founded on the domain recognized by O-P) and the measure
  (ACL2-COUNT X).  The non-trivial part of the measure conjecture is

  [[output omitted here]]

  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FACT
  ACL2 >(trace$ fact)
   ((FACT))
  ACL2 >:set-guard-checking t

  Turning guard checking on, value T.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 !>:set-guard-checking :all

  Leaving guard checking on, but changing value to :ALL.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  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 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:set-guard-checking nil

  Masking guard violations but still checking guards except for self-
  recursive calls.  To avoid guard checking entirely, :SET-GUARD-CHECKING
  :NONE.  See :DOC set-guard-checking.

  ACL2 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (ACL2_*1*_ACL2::FACT 1)
      3> (ACL2_*1*_ACL2::FACT 0)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >(verify-guards fact)

  Computing the guard conjecture for FACT....

  The guard conjecture for FACT is trivial to prove, given the :compound-
  recognizer rule POSP-COMPOUND-RECOGNIZER and the :type-prescription
  rule FACT.  FACT is compliant with Common Lisp.

  Summary
  Form:  ( VERIFY-GUARDS FACT)
  Rules: ((:COMPOUND-RECOGNIZER POSP-COMPOUND-RECOGNIZER)
          (:TYPE-PRESCRIPTION FACT))
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FACT

  [[Note added to log: No need to trace fact again after verify-guards.]]

  ACL2 >:set-guard-checking t

  Turning guard checking on, value T.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
    2> (FACT T)
    <2 (FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 !>:set-guard-checking :all

  Leaving guard checking on, but changing value to :ALL.

  ACL2 !>(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 !>(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
    2> (FACT T)
    <2 (FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  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 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
    2> (FACT T)
    <2 (FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >:set-guard-checking nil

  Masking guard violations but still checking guards except for self-
  recursive calls.  To avoid guard checking entirely, :SET-GUARD-CHECKING
  :NONE.  See :DOC set-guard-checking.

  ACL2 >(fact 2)
  1> (ACL2_*1*_ACL2::FACT 2)
    2> (FACT 2)
      3> (FACT 1)
        4> (FACT 0)
        <4 (FACT 1)
      <3 (FACT 1)
    <2 (FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 2)
  2
  ACL2 >(fact t)
  1> (ACL2_*1*_ACL2::FACT T)
    2> (FACT T)
    <2 (FACT 1)
  <1 (ACL2_*1*_ACL2::FACT 1)
  1
  ACL2 >
 })")

(defxdoc guard-evaluation-examples-script
  :parents (guard)
  :short "A script to show combinations of @(see defun-mode)s and @(see guard)-checking"
  :long "<p>Below is a script that illustrates the combination of @(see
 defun-mode)s &mdash; @(':')@(tsee program) mode, @(':')@(tsee logic) mode
 without @(see guard)s verified, and @(':')@(tsee logic) mode with @(see
 guard)s verified &mdash; with values from @(tsee set-guard-checking) &mdash;
 @('t') (the default), @(':all'), @(':none'), and @('nil').  (It does not
 illustrate the value @(':nowarn'), which is the same as @('t') except for
 inhibiting a warning.)  The script also illustrates cases where the guard is
 not, or is, @('t').</p>

 <p>See @(see guard-evaluation-examples-log) for result of running this script.
 Before presenting the script below, we give some instructions in case you want
 to run it yourself.</p>

 <p>See @(see set-guard-checking) for discussion of the interaction between
 @(see defun-mode)s and @(see guard)-checking that is illustrated by this
 script.  Also see @(see guard-evaluation-table) for a succinct table, with
 associated discussion, that covers in detail the interactions illustrated
 here.</p>

 <p>The script mentions the running of ``Tracing Code''.  The code is the
 following sequence of commands.</p>

 @({
  (trace$ fact)
  :set-guard-checking t
  (fact 2)
  (fact t)
  :set-guard-checking :all
  (fact 2)
  (fact t)
  :set-guard-checking :none
  (fact 2)
  (fact t)
  :set-guard-checking nil
  (fact 2)
  (fact t)
 })

 <p>If you want to run the script yourself, you may find it handy to use the
 following Emacs keyboard macro for running the tracing code in 2-window mode,
 with the cursor in the window with the script and ACL2 running in the other
 window.</p>

 @({
  (fset 'step-guard-script
     [?C-a ?C-  ?C-e ?M-w ?C-a ?C-n
      ?C-x ?o ?M-> ?C-y return ?C-x ?o])

  ; Put it on a key (if you have defined the indicated keymap by using
  ; emacs/emacs-acl2.el):
  (define-key ctl-t-keymap \"r\" 'step-guard-script)
 })

 <p>The script follows.</p>

 @({
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;;; Program mode
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  (defun fact (x)
           (declare (xargs :guard (integerp x)
                           :mode :program))
           (if (posp x)
               (* x (fact (1- x)))
             1))

  ; Run the Tracing Code here.  It shows execution in raw Lisp in the t and nil
  ; cases of :set-guard-checking, but not in the :all or :none cases.  We get a
  ; guard violation for argument t in the case :set-guard-checking t.

  :u

  (defun fact (x)
           (declare (xargs :guard t
                           :mode :program))
           (if (posp x)
               (* x (fact (1- x)))
             1))

  ; Run the Tracing Code here.  It should give the same results as above,
  ; except that we no longer get a guard violation in the case
  ; :set-guard-checking t.

  :u

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;;; Logic mode, guard other than t
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  (defun fact (x)
           (declare (xargs :guard (integerp x)
                           :verify-guards nil
                           :mode :logic))
           (if (posp x)
               (* x (fact (1- x)))
             1))

  ; Run the Tracing Code here.  It should give guard violations for (fact t)
  ; with guard-checking set to t or :all.  It should never run in raw Lisp,
  ; because we have not verified guards.  In the t case, we can get a warning
  ; about avoiding the guard check on recursive calls, but only if we do not
  ; trace the function, fact.

  (verify-guards fact)

  ; Run the Tracing Code here.  The results should be as described just above,
  ; except that now we go into raw Lisp for (fact 2) with guard-checking other
  ; than :none.

  :u
  :u

  ; The following definition is the same as above, except that guards are
  ; verified.

  (defun fact (x)
           (declare (xargs :guard (integerp x)
                           :mode :logic))
           (if (posp x)
               (* x (fact (1- x)))
             1))

  ; Run the Tracing Code here.  We should get the same traces as in the
  ; immediately preceding case, since guards had been verified in both cases.

  :u

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;;; Logic mode, guard t
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  (defun fact (x)
           (declare (xargs :guard t
                           :verify-guards nil
                           :mode :logic))
           (if (posp x)
               (* x (fact (1- x)))
             1))

  ; Run the Tracing Code here.  We should never go in to raw Lisp, because
  ; guards have not been verified.  We will see the same traces for (fact 2) as
  ; with the (integerp x) guard above with :verify-guards nil specified, except
  ; that even without tracing, there is no warning for :set-guard-checking t
  ; about recursive calls.  And, there are no guard violations for (fact t), of
  ; course, since posp (necessarily, if we are to verify guards) has a guard of
  ; t.

  (verify-guards fact)

  ; Run the Tracing Code here.  You shouldn't see any surprises.  Note however
  ; that if we back up to the start (using :u :u) and then define fact as just
  ; above but without :verify-guards nil, then the :none setting will allow us
  ; to go into raw Lisp: although :none generally avoids execution of raw Lisp
  ; counterparts, it allows this when the guard is T and guards have been
  ; verified.
 })")

(defxdoc guard-evaluation-table
  :parents (guard)
  :short "A table that shows combinations of @(see defun-mode)s and @(see guard)-checking"
  :long "<p>See @(see set-guard-checking) for an introduction to the topic
 discussed here.  Also see @(see guard) for a general discussion of guards, and
 see @(see guard-evaluation-examples-script) for a script that illustrates
 combinations presented below.</p>

 <p>Note: The default setting for guard-checking (that is, the initial value
 for @('(@ guard-checking-on)')) is @('T').</p>

 <p>The table below illustrates the interaction of the @(see defun-mode) with
 the value supplied to @(tsee set-guard-checking).  The first row considers
 functions defined in @(':')@(tsee program) mode; the other two consider
 functions defined in @(':')@(tsee logic) mode.  The columns correspond to four
 values of state global @(''guard-checking-on'), as supplied to @(tsee
 set-guard-checking).  (A fifth value, @(':nowarn'), is similar to @('t') but
 suppresses warnings encountered with @('t') (as explained in those warning
 messages), and is not considered here.)  During proofs, @(tsee certify-book),
 and @(tsee include-book), @(''guard-checking-on') is set to @('nil')
 regardless of how this variable has been set in the top-level loop (see the
 ``Essay on Guard Checking'' in source file @('other-events.lisp') if you are
 interested in a rationale).</p>

 <p>Below this table, we make some comments about its entries, ordered by row
 and then by column.  For example, when we refer to ``b2'' we are discussing
 the execution of a @(':')@(tsee logic) mode function whose guards have not
 been verified, after having executed @(':')@(tsee set-guard-checking)@('
 :all').</p>

 @({
     guard-checking-on:  (1)t      (2):all   (3):none   (4)nil

   (a) :program             a1        a2        a3        a4
   (b) guards not verified  b1        b2        b3        b4
   (c) guards verified      c1        c2        c3        c4
 })

 <p>a1. Check the @(see guard) upon entry, then use the raw Lisp code if the
 guard checks (else cause an error).  This is a common setting when one wants a
 little guard checking but also wants the efficiency of raw Lisp.  But note
 that you can get raw Lisp errors.  For example, if you make the definition
 @('(defun foo (x) (car x))') in @(':')@(tsee program) mode and execute
 @(':')@(tsee set-guard-checking)@(' t'), and then execute @('(foo 3)'), you
 will likely get an error from the call @('(car 3)') made in raw Lisp.</p>

 <p>a2. For built-in (predefined) functions, see a1 instead.
 Otherwise:<br></br>

 Check the @(see guard), without exception.  Thus, we never run the raw Lisp
 code in this case.  This can be useful when testing @(':')@(tsee program) mode
 functions, but you may want to run @(':')@(tsee comp)@(' t') or at least
 @(':')@(tsee comp)@(' :exec') in this case, so that the execution is done
 using compiled code.</p>

 <p>a3. For built-in (predefined) functions, see a4 instead.
 Otherwise:<br></br>

 Do not check the @(see guard).  For @(':')@(tsee program) mode functions, we
 never run the raw Lisp code in this case; so if you care about efficiency, see
 the comment in a2 above about @(':')@(tsee comp).  This combination is useful
 if you are using ACL2 as a programming language and do not want to prove
 theorems about your functions or suffer @(see guard) violations.  In this
 case, you can forget about any connection between ACL2 and Common Lisp.</p>

 <p>a4. Run the raw Lisp code without checking @(see guard)s at all.  Thus, for
 @(':')@(tsee program) mode functions, the @('nil') setting is often preferable
 to the @(':none') setting because you get the efficiency of raw Lisp
 execution.  However, with @('nil') you can therefore get hard Lisp errors as
 in a1 above.</p>

 <p>b1. Guards are checked at the top-level, though not at self-recursive
 calls.  We never run the raw Lisp code in this case; guards would need to be
 verified first.</p>

 <p>b2. Unlike the @('t') setting, guards are checked even on self-recursive
 calls.  But like the @('t') setting, we do not run the raw Lisp code.  Use
 this setting if you want guards checked on each recursive call in spite of the
 cost of doing so.</p>

 <p>b3, b4. Execution avoids the raw Lisp code and never checks guards.  The
 @('nil') and @(':none') settings behave the same in this case (i.e., for
 @(':')@(tsee logic) mode functions whose guards have not been verified),
 except that recursive calls are never inlined for @(':none') and tracing (see
 @(see trace)) will show recursive calls for @(':none') but not for
 @('nil').</p>

 <p>c1, c2. Guards are checked.  If the checks pass, evaluation takes place
 using the raw Lisp code.  If the checks fail, we get a guard violation.
 Either way, we do not execute ``in the logic''; we only execute using the raw
 Lisp code.  Note that @('t') and @(':all') behave the same in this case,
 (i.e. for @(':')@(tsee logic) mode functions whose @(see guard)s have been
 verified).</p>

 <p>c3, c4. For the @(':none') and @('nil') settings, @(':')@(tsee logic) mode
 functions whose guards have been verified will never cause guard violations.
 However, with @('nil') and for built-in functions in @(':logic') mode, guards
 are still checked: if the check succeeds, then evaluation is done using the
 raw Lisp code, and if not, it is done by the ``logic'' code, including
 self-recursive calls (though unlike the @('t') case, we will not see a warning
 about this).  But with @(':none') for user-defined functions, no guard
 checking is done, and the only time the raw Lisp code will be executed is when
 the guard is @('t') and guards are verified at the time the
 executable-counterpart of the function is defined (i.e., when the function is
 admitted unless it is later defined again and compiled using @(':')@(tsee
 comp)).  Thus, if you use @(':none') and you want a function @('(foo x)') with
 guard @('(g x)') to execute using raw Lisp code, you can write a
 ``wrapper''function with a guard of @('t'):</p>

 @({
  (defun foo-wrap (x)
    (declare (xargs :guard t))
    (if (g x)
        (foo x)
      'do-not-case))
 })

 <p>If you want the speed of executing raw Lisp code and you have non-trivial
 guards on functions that you want to call at the top-level, use @('nil')
 rather than @(':none').</p>")

(defxdoc guard-example
  :parents (tutorial5-miscellaneous-examples guard)
  :short "A brief transcript illustrating @(see guard)s in ACL2"
  :long "<p>This note addresses the question: what is the use of @(see guard)s
 in ACL2?  Although we recommend that beginners try to avoid @(see guard)s for
 a while, we hope that the summary here is reasonably self-contained and will
 provide a reasonable introduction to guards in ACL2.  For a more systematic
 discussion, see @(see guard).  For a summary of that topic, see @(see
 guard-quick-reference).</p>

 <p>Before we get into the issue of @(see guard)s, let us note that there are
 two important ``modes'':</p>

 <p>@(see defun-mode) &mdash; ``Does this @(see defun) add an axiom (`:logic
 mode') or not (`:program mode')?''  (See @(see defun-mode).)  Only
 @(':')@(tsee logic) mode functions can have their ``@(see guard)s verified''
 via mechanized proof; see @(see verify-guards).</p>

 <p>@(tsee set-guard-checking) &mdash; ``Should runtime @(see guard) violations
 signal an error (@(':all'), and usually with @('t') or @(':nowarn')) or go
 undetected (@('nil'), @(':none'))?  Equivalently, are expressions evaluated in
 Common Lisp or in the logic?''  (See @(see set-guard-checking).)</p>

 <p><i>Prompt examples</i></p>

 <p>Here some examples of the relation between the ACL2 @(see prompt) and the
 ``modes'' discussed above.  Also see @(see default-print-prompt).  The first
 examples all have @('ld-skip-proofsp nil'); that is, proofs are <i>not</i>
 skipped.</p>

 @({
    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
 })

 <p>Here are some examples with @(tsee default-defun-mode) of @(':')@(tsee
 logic).</p>

 @({
    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
 })

 <p><i>Sample session</i></p>

 @({
  ACL2 !>(+ 'abc 3)

  ACL2 Error in TOP-LEVEL: The guard for the function symbol
  BINARY-+, which is (AND (ACL2-NUMBERP X) (ACL2-NUMBERP Y)),
  is violated by the arguments in the call (+ 'ABC 3).

  ACL2 !>:set-guard-checking nil
  ;;;; verbose output omitted here
  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))
  Warnings:  None
  Time:  0.03 seconds
     (prove: 0.00, print: 0.00, proof tree: 0.00, other: 0.03)
   SUM-LIST
  ACL2 !>(sum-list '(1 2 3))

  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 SUM-LIST.  To check guards on all recursive calls:
    (set-guard-checking :all)
  To leave behavior unchanged except for inhibiting this message:
    (set-guard-checking :nowarn)

  6
  ACL2 !>(sum-list '(1 2 abc 3))

  ACL2 Error in TOP-LEVEL: The guard for the function symbol
  BINARY-+, which is (AND (ACL2-NUMBERP X) (ACL2-NUMBERP Y)),
  is violated by the arguments in the call (+ 'ABC 3).

  ACL2 !>:set-guard-checking nil
  ;;;; verbose output omitted here
  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))))

  << Starting proof tree logging >>

  Name the formula above *1.

  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.

  ...

  That completes the proof of *1.

  Q.E.D.
 })

 <p><i>Guard verification vs. defun</i></p>

 @({
        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        8  (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)
  The non-trivial part of the guard conjecture for SUM-LIST,
  given the :type-prescription rule SUM-LIST, is

  Goal
  (AND (IMPLIES (AND (INTEGER-LISTP X) (NOT (CONSP X)))
                (EQUAL X NIL))
       (IMPLIES (AND (INTEGER-LISTP X) (NOT (ENDP X)))
                (INTEGER-LISTP (CDR X)))
       (IMPLIES (AND (INTEGER-LISTP X) (NOT (ENDP X)))
                (ACL2-NUMBERP (CAR X)))).

  ...

  ACL2 >:pe sum-list
   lv       8  (DEFUN SUM-LIST (X)
                (DECLARE (XARGS :GUARD (INTEGER-LISTP X)
                                :VERIFY-GUARDS NIL))
  ACL2 >:set-guard-checking t

  Turning guard checking on, value T.

  ACL2 !>(sum-list '(1 2 abc 3))

  ACL2 Error in TOP-LEVEL: The guard for the function symbol
  SUM-LIST, which is (INTEGER-LISTP X), is violated by the
  arguments in the call (SUM-LIST '(1 2 ABC ...)).  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 !>:set-guard-checking nil
  ;;;; verbose output omitted here
  ACL2 >(sum-list '(1 2 abc 3))
  6
  ACL2 >:comp sum-list
  Compiling gazonk0.lsp.
  End of Pass 1.
  End of Pass 2.
  Finished compiling gazonk0.lsp.
  Loading gazonk0.o
  start address -T 1bbf0b4 Finished loading gazonk0.o
  Compiling gazonk0.lsp.
  End of Pass 1.
  End of Pass 2.
  Finished compiling gazonk0.lsp.
  Loading gazonk0.o
  start address -T 1bc4408 Finished loading gazonk0.o
   SUM-LIST
  ACL2 >:q

  Exiting the ACL2 read-eval-print loop.
  ACL2>(trace sum-list)
  (SUM-LIST)

  ACL2>(lp)

  ACL2 Version 1.8.  Level 1.  Cbd \"/slocal/src/acl2/v1-9/\".
  Type :help for help.
  ACL2 >(sum-list '(1 2 abc 3))
  6
  ACL2 >(sum-list '(1 2 3))
    1> (SUM-LIST (1 2 3))>
      2> (SUM-LIST (2 3))>
        3> (SUM-LIST (3))>
          4> (SUM-LIST NIL)>
          <4 (SUM-LIST 0)>
        <3 (SUM-LIST 3)>
      <2 (SUM-LIST 5)>
    <1 (SUM-LIST 6)>
  6
  ACL2 >:pe sum-list-append
            9  (DEFTHM SUM-LIST-APPEND
                       (EQUAL (SUM-LIST (APPEND A B))
                              (+ (SUM-LIST A) (SUM-LIST B))))
  ACL2 >(verify-guards 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 (APPEND A B))
       (INTEGER-LISTP A)
       (INTEGER-LISTP B)).

  ...

  ****** FAILED ******* See :DOC failure ****** FAILED ******
  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)

  << Starting proof tree logging >>

  By the simple :rewrite rule SUM-LIST-APPEND we reduce the
  conjecture to

  Goal'
  (IMPLIES (AND (INTEGER-LISTP A)
                (INTEGER-LISTP B))
           (EQUAL (+ (SUM-LIST A) (SUM-LIST B))
                  (+ (SUM-LIST A) (SUM-LIST B)))).

  But we reduce the conjecture to T, by primitive type
  reasoning.

  Q.E.D.
  ;;;; summary omitted here
  ACL2 >(verify-guards common-lisp-sum-list-append)

  The non-trivial part of the guard conjecture for
  COMMON-LISP-SUM-LIST-APPEND, given the :type-prescription
  rule SUM-LIST, is

  Goal
  (AND (IMPLIES (AND (INTEGER-LISTP A)
                     (INTEGER-LISTP B))
                (TRUE-LISTP A))
       (IMPLIES (AND (INTEGER-LISTP A)
                     (INTEGER-LISTP B))
                (INTEGER-LISTP (APPEND A B)))).

  ...

  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 omitted here.
  ACL2 >(defthm foo (consp (mv x y)))

  ...

  Q.E.D.
 })

 @({
  ACL2 >(verify-guards foo)

  ACL2 Error in (VERIFY-GUARDS FOO): The number of values we
  need to return is 1 but the number of values returned by the
  call (MV X Y) is 2.

  > (CONSP (MV X Y))

  ACL2 Error in (VERIFY-GUARDS FOO): The guards for FOO cannot
  be verified because the theorem has the wrong syntactic
  form.  See :DOC verify-guards.
 })")

(defxdoc guard-formula-utilities
  :parents (guard)
  :short "Utilities that show guard proof obligations"
  :long "<p>See @(see verify-guards) and see @(see guard) for discussions of
 guards.  Here we discuss several utilities that provide the proof obligations
 for guards, and briefly compare what is offered by each.  Of course, see the
 documentation of each utility for details.</p>

 <p>The first pair of utilities captures formulas produced during guard
 verification.</p>

 <blockquote>

 <p>@(csee Verify-guards-formula): Use this to see what the corresponding
 @(tsee verify-guards) event prints, but without following through with a proof
 attempt.  This utility is only for output, without returning an interesting
 value.</p>

 <p>@(csee Guard-obligation): This function is a programmatic version of the
 macro, @(tsee verify-guards-formula).  It provides the guard obligation as a
 set of clauses, along with other information.</p>

 </blockquote>

 <p>The second pair of utilities captures the formula provided when a
 @(':guard-theorem') is supplied for a @(':use') hint.</p>

 <blockquote>

 <p>@(csee Gthm): This macro returns a user-level (``untranslated'')
 representation of the @(see term) that is generated for a @(':guard-theorem')
 @(see lemma-instance).  Options control whether or not simplification and
 @(see guard-debug) are used.</p>

 <p>@(csee Guard-theorem): This utility is like @(see gthm), except that it is
 a function rather than a macro and it returns a translated term (a @(tsee
 termp)).</p>

 </blockquote>

 <p>We conclude by contrasting these two pairs of utilities.  The first pair
 can take as input as either a function symbol or a term; for the second pair a
 function symbol (not a term) is required.  Another difference: the first pair
 simplifies with respect to the @(see current-theory) before producing the
 guard proof obligation formula, as is typically done when verifying guards;
 but the second pair only performs the theory-independent simplification done
 for a @(':guard-theorem') specified in a @(':use') hint, or if a suitable
 option is supplied, no simplification at all.  Finally the two pairs differ in
 their output @(see signature)s: in particular, the utilities in the first pair
 return multiple values while those in the second pair return a single
 value.</p>")

(defxdoc guard-holders
  :parents (rule-classes term guard)
  :short "Remove trivial calls from a @(see term)"
  :long "<p>For many @(see rule-classes), the process of converting terms to
 rules includes the removal of certain trivial calls from the term.  In all
 such cases, the resulting term is provably equivalent to the input term.  A
 common example is to replace the term @('(prog2$ term1 term2)') by the term
 @('term2').  But @('(prog2$ term1 term2)') is really an abbreviation for
 (i.e., macroexpands to) the term @('(return-last 'progn term1 term2)'); so a
 more accurate explanation, at the level of proper ACL2 @(see term)s, is that
 the call of function @(tsee return-last) is replaced by its last argument.
 ACL2 identifies certain such transformations, from a term to a trivial
 simplification of it such that the input and output are provably equal.  We
 historically have referred to the process of making such replacements as
 ``removing guard holders.''  (For a discussion of the connection to guards,
 see the ``Essay on the Removal of Guard Holders'' in the ACL2 sources.)</p>

 <p>The process of removing guard-holders includes the transformations below.
 That process is also applied to each argument of a function call and to the
 bodies of @(see lambda) expressions (see @(see term)).</p>

 @({
 (return-last term0 term1 term2)  ==>  term2

 (mv-list term0 ... termk)        ==>  termk

 (cons-with-hint x y)             ==>  (cons x y)

 ; For replacing a term (the type term) by term:
 ((lambda (y) (the-check guard x y))
  val)                            ==>  val

 ; For replacing equality aliases; for example, this transforms
 ; the macroexpansion of (member x y) to (member-equal x y):
 (('LAMBDA (f1 ... fk) ('RETURN-LAST ''MBE1-RAW exec logic))
  a1 ... ak)
                                  ==>  logic

 })

 <p>Because of how @(tsee mbe) and @(tsee ec-call) are defined in terms of
 @(tsee return-last), the expressions @('(mbe :logic l :exec e)') and
 @('(ec-call (f t1 ... tk))') are effectively transformed by removing guard
 holders into @('l') and @('(f t1 ... tk)'), respectively.</p>")

(defxdoc guard-introduction
  :parents (guard)
  :short "Introduction to @(see guard)s in ACL2"
  :long "<p>Most users can probably profit by avoiding dealing with guards most
 of the time.  If they seem to get in the way, they can be ``turned off'' using
 the command @(':')@(tsee set-guard-checking) @('nil'); for more about this,
 see @(see set-guard-checking).  For more about guards in general, see @(see
 guard).</p>

 <p>The guard on a function symbol is a formula about the formals of the
 function.  To see the guard on a function, use the keyword command
 @(':')@(tsee args).  See @(see args).  To specify the guard on a function at
 @('defun-time'), use the @(':')@(tsee guard) @('xarg') (See @(see xargs)) or
 @('type') declarations (see @(see declare)).  The latter may be preferable if
 you want the host Lisp compiler to use this information.</p>

 <p>Guards can be seen as having either of two roles: (a) they are a
 specification device allowing you to characterize the kinds of inputs a
 function ``should'' have, or (b) they are an efficiency device allowing
 logically defined functions to be executed directly in Common Lisp.  Briefly:
 If the guards of a function definition are ``verified'' (see @(see
 verify-guards)), then the evaluation of a call of that function on arguments
 satisfying its guard will have the following property:</p>

 <blockquote><p>All subsequent function calls during that evaluation will be on
 arguments satisfying the guard of the called function.</p></blockquote>

 <p>The consequence of this fact for (a) is that your specification function is
 well-formed, in the sense that the values returned by this function on
 appropriate arguments only depend on the restrictions of the called functions
 to their intended domains.  The consequence of this fact for (b) is that in
 the ACL2 system, when a function whose guards have been verified is called on
 arguments that satisfy its guard, then the raw lisp function defined by this
 function's @(tsee defun) event is used to evaluate the call.  Note however
 that even when the user-supplied @(tsee defun) is not used, ACL2 uses a
 corresponding executable-counterpart function that generally performs, we
 expect, nearly as well as submitted function; see @(see evaluation) for
 relevant background on these two functions.  See @(see comp) to see how @(see
 compilation) can speed up both kinds of execution.</p>

 <p>Let us turn next to the issue of the relationship between guards and
 evaluation.  See @(see guards-and-evaluation).</p>")

(defxdoc guard-miscellany
  :parents (guard)
  :short "Miscellaneous remarks about guards"
  :long "<p>The discussion of guards concludes here with a few miscellaneous
 remarks.  (Presumably you found this documentation by following a link; see
 @(see guards-for-specification).)  For further information related to guards
 other than what you find under ``@(see guard),'' see any of the following
 documentation topics: @(see guard-example), @(tsee
 set-verify-guards-eagerness), @(tsee set-guard-checking), @(tsee
 verify-guards), and (for a discussion of keyword @(':split-types')) @(tsee
 xargs).</p>

 <p>@(tsee Defun) can be made to try to verify the guards on a function.  This
 is controlled by the ``@(see defun-mode)'' of the @(tsee defun); see @(see
 defun-mode).  The @(see defun-mode) is either as specified with the @(':mode')
 @('xarg') of the @(tsee defun) or else defaults to the default @(see
 defun-mode).  See @(see default-defun-mode).  If the @(see defun-mode) of the
 @(tsee defun) is @(':')@(tsee logic) and either a @(see guard) is specified
 explicitly or @(':')@(tsee verify-guards) @('t') is specified in the @(tsee
 xargs), then we attempt to verify the guards of the function.  Otherwise we do
 not.  (But see @(see set-verify-guards-eagerness) for how to modify this
 behavior.)</p>

 <p>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-@(tsee defun) guard verification is achieved via the event @(tsee
 verify-guards).  See @(see verify-guards).</p>

 <p>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.</p>

 <p>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.</p>

 <p>If @(tsee 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.</p>

 <p>Finally, we note that ACL2 collects up @(see guard)s from @(tsee declare)
 forms in order of appearance.  So for example, the @(tsee declare) form</p>

 @({
  (declare (xargs :guard (foo x))
           (type string x)
 })

 <p>will generate the guard @('(and (foo x) (stringp x))'), while the form</p>

 @({
  (declare (type string x)
           (xargs :guard (foo x))
 })

 <p>will generate the guard @('(and (stringp x) (foo x))').  The only exception
 to this rule is the case that @(':guard') and @(':stobjs') are both specified
 in which case all @(':stobjs') declarations will be treated as through they
 precede all @(':guard') and @('type') declarations.</p>")

(defxdoc guard-obligation
  :parents (guard-formula-utilities)
  :short "The guard proof obligation"
  :long "<p>See @(see verify-guards), and see @(see guard) for a discussion of
 guards.  @('Guard-obligation') is a low-level function for use in system
 programs, not typically appropriate for most ACL2 users.  A corresponding
 user-level utility is @(see verify-guards-formula); also see @(see
 guard-formula-utilities) for related utilities.</p>

 @({
  Example Forms:
  (guard-obligation 'foo nil t 'top-level state)
  (guard-obligation '(if (consp x) (foo (car x)) t) nil nil 'my-function state)

  General Forms:
  (guard-obligation name rrp guard-debug ctx state)
  (guard-obligation term rrp guard-debug ctx state)
 })

 <p>where the first argument is either the name of a function or theorem or is
 a non-variable term that may be in untranslated form; @('rrp') (``return
 redundant p'') is non-@('nil') when it is permissible to return a value of
 @(''redundant') in the first (name) case (and is irrelevant in the term case);
 @('guard-debug') is typically @('nil') but may be @('t') (see @(see
 guard-debug)); @('ctx') is a context (typically, a symbol used in error and
 warning messages); and @(tsee state) references the ACL2 @(see state).</p>

 <p>If you want to obtain the formula but you don't care about the so-called
 ``tag tree'':</p>

 @({
  (mv-let (erp val)
          (guard-obligation x nil guard-debug 'top-level state)
          (if erp
             ( .. code for handling error case, e.g., name is undefined .. )
            (let ((cl-set (cadr val))) ; to be proved for guard verification
              ( .. code using cl-set, which is a list of clauses,
                   implicitly conjoined, each of which is viewed as
                   a disjunction .. ))))
 })

 <p>The form @('(guard-obligation x rrp guard-debug ctx state)') evaluates to a
 pair @('(mv erp val)'), where @('erp') is @('nil') unless there is an
 error.  (Actually, this is a context-message pair; see the source code's
 ``Essay on Context-message Pairs''for relevant information.)  Suppose @('erp')
 is @('nil').  Then @('val') is the keyword @(':redundant') if the
 corresponding @(tsee verify-guards) event would be redundant and @('rrp') is
 not @('nil'); see @(see redundant-events).  Otherwise, @('val') is a tuple
 @('(list* names cl-set ttree)'), where: @('names') is @('(cons :term xt)') if
 @('x') is not a variable, where @('xt') is the translated form of @('x'); and
 otherwise is a list containing @('x') along with, if @('x') is defined in a
 @('mutual-recursion'), any other functions defined in the same @(tsee
 mutual-recursion) nest; @('cl-set') is a list of lists of terms, viewed as a
 conjunction of clauses (each viewed (as a disjunction); and @('ttree') is an
 assumption-free tag-tree that justifies cl-set.  (The notion of ``tag-tree''
 may probably be ignored except for system developers.)</p>

 <p>@('Guard-obligation') is typically used for function names or non-variable
 terms, but as for @(tsee verify-guards), it may also be applied to theorem
 names.</p>

 <p>See the source code for @(tsee verify-guards-formula) for an example of how
 to use @('guard-obligation').</p>")

(defxdoc guard-quick-reference
  :parents (guard)
  :short "Brief summary of guard checking and guard verification"
  :long "<p>For a careful introduction to guards, see @(see guard).</p>

 <p><b>I. GUARD CHECKING DURING EXECUTION</b></p>

 <p><i>Effect</i></p>

 <p>Guards on definitions are checked at execution time (except for guards on
 subsidiary calls of recursive or mutually recursive functions).</p>

 <p><i>When does it happen</i></p>

 <p>By default, guards are checked for all forms submitted at the top
 level.</p>

 <p><i>To disable</i><br></br>

 @(':set-guard-checking nil') ; skip raw Lisp if there is a guard violation
 @(':set-guard-checking :none') ; skip guard checking entirely</p>

 <p><i>To (re-)enable</i><br></br>

 @(':set-guard-checking t')</p>

 <p>See @(see set-guard-checking) for more options.</p>

 <p><b>II. GUARD VERIFICATION</b></p>

 <p><i>Effect</i></p>

 <p>A proof is attempted of the obligations arising from the guards of
 subsidiary functions in a @(tsee defun), @(tsee defthm), or @(tsee defaxiom)
 event.  In the case of a @('defun'), the guard itself is also verified (under
 an implicit guard of @('t')).</p>

 <p><i>When does it happen</i></p>

 <p>Only names of defined functions, @(tsee defthm)s, and @(tsee defaxiom)s are
 subject to guard verification.  Guard verification may occur when functions
 are defined (using @(tsee defun)), but it requires an explicit call of @(tsee
 verify-guards) in order to verify guards for @(tsee defthm)s and @(tsee
 defaxiom)s.  Constrained functions (see @(see encapsulate)) may not have their
 guards verified.</p>

 <p>@('(verify-guards foo ...)')<br></br>

 causes guard verification for the @(tsee defun), @(tsee defthm), or @(tsee
 defaxiom) named by @('foo'), if it has not already been successfully done.
 The default @(see defun-mode) (see @(see default-defun-mode)) must be
 @(':')@(tsee logic), or else this event is ignored.</p>

 <p>@('(defun foo ...)')<br></br>

 causes guard verification of @('foo') if and only if the following two
 conditions are both met.  First, foo is processed in @(':')@(tsee logic)
 mode (either by setting mode @(':')@(tsee logic) globally, or by including
 @(':mode :logic') in the @(tsee xargs) declaration).  Second, at least one of
 the following sub-conditions is met.  Also see @(see xargs), and see @(see
 set-verify-guards-eagerness) for how to change this behavior.</p>

 <blockquote><p>1. The @(tsee xargs) declaration specifies a @(':')@(tsee
 guard).</p>

 <p>2. There is at least one @('type') declaration (see @(see declare)).</p>

 <p>3. The @(tsee xargs) declaration specifies @(':')@(tsee stobj)@('s').</p>

 <p>4. The @(tsee xargs) declaration specifies @(':')@(tsee verify-guards)
 @('t').</p></blockquote>

 <p>@('(verify-termination foo ...)')<br></br>

 causes guard verification of @('foo') if @('foo') is a function currently
 defined in @(':')@(tsee program) mode and the criteria for guard verification
 of a @(tsee defun) form are met, as discussed above.  The default @(see
 defun-mode)
 (see @(see default-defun-mode)) must be @(':')@(tsee logic), or else this
 event is ignored.</p>")

(defxdoc guard-theorem
  :parents (lemma-instance guard-formula-utilities hints)
  :short "Use a previously-proved @(see guard) theorem"
  :long "<p>See @(see lemma-instance) for a discussion of @(':guard-theorem')
 lemma instances, as illustrated in the topic @(see guard-theorem-example).</p>

 <p>The function @('guard-theorem') is a low-level system utility that is
 essentially the functional version of the @(tsee gthm) macro.</p>")

(defxdoc guard-theorem-example
  :parents (lemma-instance guard hints)
  :short "How to use a previously-proved @(see guard) theorem"
  :long "<p>See @(see lemma-instance) for a discussion of @(':guard-theorem')
 lemma instances, and see @(see gthm) for a related user-level query utility.
 In this topic, we illustrate the use of such lemma instances to take advantage
 of a @(see guard) theorem already proved for an existing definition, when
 attempting to admit a new definition.</p>

 <p>The following example is contrived but should get the idea across.  Suppose
 that the event displayed just below was previously executed, for example when
 including a book.  The @(tsee mbe) call generates a guard proof obligation,
 but there is only one thing to know about that for this example: without the
 local lemma shown, the guard proof fails for @('f1').</p>

 @({
 (encapsulate
   ()
   (local (defthm append-revappend
            (equal (append (revappend x y) z)
                   (revappend x (append y z)))))

   (defun f1 (x y)
     (declare (xargs :guard (and (true-listp x)
                                 (true-listp y))))
     (mbe :logic (append (reverse x) y)
          :exec (revappend x y))))
 })

 <p>Now suppose that later, we wish to admit a function with the same guard and
 body.  Since the lemma @('append-revappend') above is @(see local), guard
 verification will likely fail.  However, we can tell the prover to use the
 guard theorem already proved for @('f1'), as follows; then the guard
 verification proof succeeds.</p>

 @({
 (defun f2 (x y)
   (declare (xargs :guard (and (true-listp x)
                               (true-listp y))
                   :guard-hints ((\"Goal\" :use ((:guard-theorem f1))))))
   (mbe :logic (append (reverse x) y)
        :exec (revappend x y)))
 })

 <p>See @(see termination-theorem-example) for an example use of the analogous
 lemma instance type, @(':termination-theorem').  That topic also includes
 discussion of the use of event names in prover output.</p>")

(defxdoc guards-and-evaluation
  :parents (guard)
  :short "The relationship between guards and evaluation"
  :long "<p>For relevant background see @(see evaluation).</p>

 <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>

 <p>For more about guards in general, see @(see guard).  For in-depth
 discussion of the interaction between the @(see defun-mode) and guard
 checking, see @(see set-guard-checking), see @(see guard-evaluation-table),
 see @(see guard-evaluation-examples-script), and see @(see
 guard-evaluation-examples-log).  Also see @(see generalized-booleans) for
 discussion about a subtle issue in the evaluation of certain Common Lisp
 functions.</p>

 <p><i>Guards and evaluation I: the default</i></p>

 <p>Consider the following very simple definition.</p>

 @({
  (defun foo (x) (cons 1 (cdr x)))
 })

 <p>First consider how raw Common Lisp behaves when evaluating calls of this
 function.  To evaluate @('(foo x)') for some expression @('x'), first @('x')
 is evaluated to some value @('v'), and then @('(cons 1 (cdr x))') is evaluated
 with @('x') bound to @('v').  For example, if @('v') is @('(cons 'a 3)'), then
 Common Lisp computes @('(cons 1 3)').  But if (for example) @('v') is a
 number, e.g., @('7'), 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 @('foo') in question is in compiled code.</p>

 <p>Now by default, ACL2 evaluates calls of @('foo') exactly as Common Lisp
 does, except that it uses guards to check the ``legality'' of each function
 call.  So for example, since @('(cdr x)') has a guard of @('(or (consp x)
 (equal x nil))'), the call @('(foo 7)') would cause a ``guard violation,'' as
 illustrated below.</p>

 @({
  ACL2 !>(foo 7)

  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).

  ACL2 !>
 })

 <p>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>

 <p><i>Guards and evaluation II:</i> @(':')@(tsee set-guard-checking).</p>

 <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 @(see
 documentation) for each individual primitive for the specification of what it
 returns when its guard is violated; for example, see @(see cdr).</p>

 <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 @(tsee cdr)
 implies that the @(tsee cdr) of an @(see atom) is @('nil'); see @(see cdr).
 So: should @('(cdr 7)') cause a guard violation error or return @('nil')?</p>

 <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
 @(':')@(tsee set-guard-checking)@(' nil'); or evaluate @(':')@(tsee
 set-guard-checking)@(' :none') to skip guard checking entirely.  To turn
 ``guard checking'' back on, execute the top-level form @(':')@(tsee
 set-guard-checking)@(' t').  The status of guard checking reflected in the
 @(see prompt); guard-checking is ``on'' when the @(see prompt) contains an
 exclamation mark (also see @(see default-print-prompt)).  For example,</p>

 @({
  ACL2 !>
 })

 <p>means guard checking is on and</p>

 @({
  ACL2 >
 })

 <p>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</p>

 @({
  ACL2 !>(car 'abc)
 })

 <p>will signal an error, while</p>

 @({
  ACL2 >(car 'abc)
 })

 <p>will return @('nil').  To return to our previous example: with guard
 checking off, @('(foo 7)') evaluates to @('(cons 1 nil)').  Also see @(see
 set-guard-checking).</p>

 <p><i>Guards and evaluation III: guard verification</i></p>

 <p>Consider the definition of @('foo') given above, but modified so that a
 reasonable guard of @('(consp x)') is specified, as shown below.</p>

 @({
  (defun foo (x)
    (declare (xargs :guard (consp x)))
    (cons 1 (cdr x)))
 })

 <p>We say ``reasonable guard'' above because if @('x') is such that @('(consp
 x)') holds, then the call of @(tsee cdr) in the evaluation of @('(foo x)')
 will not cause a guard violation.  Thus, it ``should'' be legal to evaluate
 @('(foo x)'), for any such @('x'), simply by evaluating this form in raw
 Common Lisp.</p>

 <p>The @(tsee verify-guards) event has been provided for this purpose.
 Details may be found elsewhere; see @(see verify-guards).  Briefly, for any
 defined function @('fn'), the event @('(verify-guards fn)') attempts to check
 the condition discussed above, that whenever @('fn') 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>

 <p>Returning to our example above, the @('(verify-guards foo)') will succeed
 because the guard @('(consp x)') of @('foo') implies the guard generated from
 the call @('(cdr x)') in the body of the definition, namely, @('(or (consp x)
 (equal x nil))') (see @(see cdr)).  Then the evaluation of @('(foo (cons 'a
 3))') will take place in raw Common Lisp, because @('(cons 'a 3)') satisfies
 the guard of @('foo').</p>

 <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>

 <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 signaled the first time
 its guard is violated; but in fact it is also true when guard checking is off.
 See @(see guard-example) for an example.</p>

 <p><i>Guards and evaluation IV: functions having :program mode</i></p>

 <p>Strictly speaking, functions in @(':')@(tsee program) mode (see @(see
 defun-mode)) 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 @(':')@(tsee
 program) functions much as we treat @(':')@(tsee logic) 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 @(':')@(tsee logic) 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 @(':')@(tsee program) 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>

 <p><b>Aside</b>.  There are exceptions to the use of raw Lisp, discussed just
 above, to evaluate calls of @(':')@(tsee program) mode functions.  The primary
 one is that after @(':')@(tsee set-guard-checking)@(' :none'), evaluation of
 user-defined @(':')@(tsee program) mode function calls is done in the ACL2
 logic, not in raw Lisp.  The more obscure exception is that during expansion
 of macros and @(tsee make-event) forms, and during evaluation of @(tsee
 defconst) 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 @(':')@(tsee
 set-guard-checking)@(' :none') if you are happy to skip all guard checking and
 evaluate forms in the logic.</p>

 @({
  ACL2 !>(defun foo (x)
           (declare (xargs :mode :program :guard t))
           (car x))

  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]

  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)

  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 !>(assign safe-mode nil)
   NIL
  ACL2 !>(foo 3)
  Error: Attempt to take the car of 3 which is not listp.
    [condition type: SIMPLE-ERROR]

  Restart actions (select using :continue):
   0: Return to Top Level (an \"abort\" restart).
   1: Abort entirely from this process.
  [1] ACL2(2):
 })

 <p>The other exception occurs after @(tsee set-guard-checking) can be called
 with a value of @(':all'); see @(see set-guard-checking).  <b>End of
 aside.</b></p>

 <p>Thus, as with @(':')@(tsee logic) functions: when a guard has been
 satisfied on a call of a function with @(':')@(tsee program) mode, no
 subsidiary guard checking will be done.</p>

 <p>Notice that by treating functions in @(':')@(tsee program) 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.</p>

 @({
  ACL2 >:program
  ACL2 p>(defun foo (x)
          (declare (xargs :guard t))
          (cons 1 (cdr x)))

  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)

  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>>
 })

 <p>See @(see defun-mode-caveat).</p>

 <p>However, here is a way to get ACL2 to do run-time guard checking for
 user-defined @(':')@(tsee program) mode functions.  With this method, ACL2
 will evaluate calls of user-defined @(':program') 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.''</p>

 @({
  (f-put-global 'safe-mode t state)
 })

 <p>Let us revisit the example above, using safe mode.  Notice that the guard
 of @(tsee cdr) is now being checked, because the executable-counterpart of
 @('foo') is being called even though the @(see guard) is @('t').</p>

 @({
  ACL2 !>(f-put-global 'safe-mode t state)
  <state>
  ACL2 !>:program
  ACL2 p!>(defun foo (x)
            (declare (xargs :guard t))
            (cons 1 (cdr x)))

  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)

  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).  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 p!>
 })

 <p>If we go back into ``unsafe'' mode, then we once again see a raw Lisp
 error, as we now illustrate.</p>

 @({
  ACL2 p!>(f-put-global 'safe-mode nil state)
  <state>
  ACL2 p!>(foo 3)

  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>>
 })

 <p><i>Guards and evaluation V: efficiency issues</i></p>

 <p>We have seen that by verifying the guards for a @(':')@(tsee logic)
 function, we arrange that raw lisp is used for evaluation of calls of such
 functions when the arguments satisfy its guard.</p>

 <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 (see
 @(see compilation)), enormous speed-ups are possible.  Third, if your Common
 Lisp or its compiler does such optimizations as @('tail-recursion') removal,
 raw Common Lisp may be able to compute your functions on input much ``bigger''
 than ACL2 can.</p>

 <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>

 <p>When a function is defined in @(':')@(tsee logic) mode, its @(tsee defun)
 is executed in raw Common Lisp; we call this the ``submitted'' definition of
 the function.  However, a corresponding executable-counterpart also
 executed.  (See @(see evaluation) for an introduction to submitted and
 executable-counterpart definitions.)  The executable-counterpart is a @(tsee
 defun) in raw lisp that checks guards at runtime and escapes to the submitted
 definition if the guard holds of the arguments and the function has already
 had its guards verified.  Otherwise the executable-counterpart evaluates the
 body of the function by calling the executable-counterpart of each subroutine.
 Now it is true that @(see compilation) often speeds up execution
 significantly.  However, the @(':')@(tsee comp) command (see @(see comp))
 compiles both of the raw lisp definitions associated with a function.  Also,
 we have attempted to arrange that for every tail recursion removal done on the
 actual @(tsee defun), a corresponding tail recursion removal is done on the
 executable-counterpart definition.</p>

 <p>We believe that in most cases, the executable-counterpart executes almost
 as fast as the submitted 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 submitted 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>

 <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 @(tsee declare) forms that assign small integer types to formal parameters.
 Note that while type declarations contributed to the guard by default, they
 can be proved from the guard instead; see @(see xargs) for a discussion of the
 @(':split-types') keyword.</p>

 <p>To continue the discussion of guards, see @(see guards-for-specification)
 to read about the use of guards as a specification device.</p>")

(defxdoc guards-for-specification
  :parents (guard)
  :short "Guards as a specification device"
  :long "<p>A use of guard verification that has nothing to do with efficiency
 is as a way to gain confidence in specifications.  This use has the feel of
 ``types'' in many traditional @(see programming) languages, though guards
 allow much greater expressiveness than most systems of types
 (and unfortunately, as a result they are not syntactically checkable).</p>

 <p>For more discussion of guards in general, see @(see guard).</p>

 <p>Suppose you have written a collection of function definitions that are
 intended to specify the behavior of some system.  Perhaps certain functions
 are only intended to be called on certain sorts of inputs, so you attach
 guards to those functions in order to ``enforce'' that requirement.  And then,
 you verify the guards for all those functions.</p>

 <p>Then what have you gained, other than somewhat increased efficiency of
 execution (as explained above), which quite possibly isn't your main concern?
 You have gained the confidence that when evaluating any call of a
 (specification) function whose arguments satisfy that function's guard, all
 subsequent function calls during the course of evaluation will have this same
 property, that the arguments satisfy the guard of the calling function.</p>

 <p>The rest of this topic addresses those who wish to understand @(see guard)s
 from a proof-theoretic perspective instead of (or in addition to) the
 evaluation perspective given above.  In logical terms, we can say that the
 equality of the original call with the returned value is provable from
 weakened versions of the definitions, where each definitional axiom is
 replaced by an implication whose antecedent is the requirement that the
 arguments satisfy the guard and whose consequent is the original axiom.  For
 example,</p>

 @({
  (defun foo (x)
    (declare (xargs :guard (consp x)))
    (cons 1 (cdr x)))
 })

 <p>originally generates the axiom</p>

 @({
  (equal (foo x)
         (cons 1 (cdr x)))
 })

 <p>but in fact, when evaluation involves no guard violation then the following
 weaker axiom suffices in the justification of the evaluation.</p>

 @({
  (implies (consp x)
           (equal (foo x)
                  (cons 1 (cdr x))))
 })

 <p>So for example, suppose we evaluate @('(foo '(a b c))') and get @(''(1 b
 c)').  Then of course the equality of these two terms is provable from the
 original axiom.  The point here is that it's even provable from the weaker
 axiom.</p>

 <p>If you are following links to read this documentation as a hypertext style
 document, then please see @(see guard-miscellany).  This concludes our
 discussion of guards with miscellaneous remarks, and also contains pointers to
 related topics.</p>")

(defxdoc |Guards in ACL2|
  :parents (|Pages Written Especially for the Tours|)
  :short "Guards"
  :long "<p>Common Lisp functions are partial; they are not defined for all
 possible inputs.  But ACL2 functions are total.  Roughly speaking, the logical
 function of a given name in ACL2 is a <b>completion</b> of the Common Lisp
 function of the same name obtained by adding some arbitrary but ``natural''
 values on arguments outside the ``intended domain'' of the Common Lisp
 function.</p>

 <p>ACL2 requires that every ACL2 function symbol have a ``guard,'' which may
 be thought of as a predicate on the formals of the function describing the
 intended domain.  The guard on the primitive function @(tsee car) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>,
 for example, is @('(or (consp x) (equal x nil))'), which requires the argument
 to be either an ordered pair or @('nil').  We will discuss later how to
 specify a guard for a defined function; when one is not specified, the guard
 is @('t') which is just to say all arguments are allowed.</p>

 <p><b>But guards are entirely extra-logical</b>: they are not involved in the
 axioms defining functions.  If you put a guard on a defined function, the
 defining axiom added to the logic defines the function on <b>all</b>
 arguments, not just on the guarded domain.</p>

 <p>So what is the purpose of guards?</p>

 <p>The key to the utility of guards is that we provide a mechanism, called
 ``guard verification,'' for checking that all the guards in a formula are
 true.  See @(see verify-guards).  This mechanism will attempt to prove that
 all the guards encountered in the evaluation of a guarded function are true
 every time they are encountered.</p>

 <p>For a thorough discussion of guards, see the paper [km97] in the ACL2 @(see
 bibliography).</p>")

(defxdoc |Guessing the Type of a Newly Admitted Function|
  :parents (|Pages Written Especially for the Tours|)
  :short "Guessing the Type of a Newly Admitted Function"
  :long "<p>When a function is admitted to the logic, ACL2 tries to ``guess''
 what type of object it returns.  This guess is codified as a term that
 expresses a property of the value of the function.  For @('app') the term
 is</p>

 @({
  (OR (CONSP (APP X Y))
      (EQUAL (APP X Y) Y))
 })

 <p>which says that @('app') returns either a cons or its second argument.
 This formula is added to ACL2's rule base as a @(tsee type-prescription) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 rule.  Later we will discuss how rules are used by the ACL2 theorem prover.
 The point here is just that when you add a definition, the database of rules
 is updated, not just by the addition of the definitional axiom, but by several
 new rules.</p>

 <p>You should now return to <see topic='@(url
 |Revisiting the Admission of App|)'>the Walking Tour</see>.</p>")

(defxdoc |Guiding the ACL2 Theorem Prover|
  :parents (|Pages Written Especially for the Tours|)
  :short "Guiding the ACL2 Theorem Prover"
  :long "<p><see topic='@(url
 |ACL2 as an Interactive Theorem Prover (cont)|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>Now that you have seen the theorem prover in action you might be curious as
 to how you guide it.</p>

 <p><img src='res/tours/interactive-theorem-prover.gif'></img></p>

 <p>Look at the picture above.  It is meant to suggest that <i>Q</i> is an
 important lemma needed for the proof of <i>P</i>.  Note that to lead the
 prover to the proof of <i>P</i> the user first proves <i>Q</i>.  In a way, the
 formulation and proof of <i>Q</i> is a hint to the prover about how to prove
 <i>P</i>.</p>

 <p>The user usually doesn't think of <i>Q</i> or recognize the need to prove
 it separately until he or she sees the theorem prover <b>fail</b> to prove
 <i>P</i> without it ``knowing'' <i>Q</i>.</p>

 <p>The way the user typically discovers the need for <i>Q</i> is to look at
 failed proofs.</p>

 <p><see topic='@(url |ACL2 as an Interactive Theorem Prover (cont)|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc hard-error
  :parents (errors acl2-built-ins)
  :short "Print an error message and stop execution"
  :long "<p>@('(Hard-error ctx str alist)') causes evaluation to halt with a
 short message using the ``context'' @('ctx').  An error message is first
 printed using the string @('str') and alist @('alist') that are of the same
 kind as expected by @(tsee fmt).  See @(see fmt).  Also see @(see er) for a
 macro that provides a unified way of signaling errors.</p>

 <p>@('Hard-error') has a guard of @('t').  Also see @(see illegal) for a
 similar capability which however has a guard of @('nil') that supports static
 checking using @(tsee guard) verification, rather than using dynamic
 (run-time) checking.  This distinction is illustrated elsewhere: see @(see
 prog2$) for examples.</p>

 <p>Semantically, @('hard-error') ignores its arguments and always returns
 @('nil').  But if a call @('(hard-error ctx str alist)') is encountered during
 evaluation, then the string @('str') is printed using the association list
 @('alist') (as in @(tsee fmt)), after which evaluation halts immediately.
 Here is a trivial, contrived example.</p>

 @({
  ACL2 !>(cons 3 (hard-error 'my-context
                              \"Printing 4: ~n0\"
                              (list (cons #\\0 4))))

  HARD ACL2 ERROR in MY-CONTEXT:  Printing 4: four

  ACL2 Error in TOP-LEVEL:  Evaluation aborted.

  ACL2 !>
 })

 <p>Technical note for raw Lisp programmers only.  It is possible to cause hard
 errors to signal actual raw Lisp errors, simply by evaluating the following
 form in raw Lisp: @('(setq *hard-error-is-error* t)').  Indeed, any
 non-@('nil') value for @('*hard-error-is-error*') will cause @('hard-error')
 or @(tsee illegal) &mdash; or indeed @('(er hard ...)'), @('(er hard! ...)'),
 or @('(er hard?  ...)') &mdash; to produce a Lisp error whose condition, when
 printed with @('format') directive @('~a'), is the same error message that
 ACL2 would otherwise print.  Below is a sample log, closely based on an
 example provided by Jared Davis.</p>

 @({
  ACL2 !>(defun f (x)
           (er hard 'f \"F got bad input ~x0.~%\" x))

  Since F is non-recursive, its admission is trivial.  We observe that
  the type of F is described by the theorem (EQUAL (F X) NIL).  We used
  the :type-prescription rule ILLEGAL.

  Summary
  Form:  ( DEFUN F ...)
  Rules: ((:TYPE-PRESCRIPTION ILLEGAL))
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   F
  ACL2 !>:q

  Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
  ? (defun run-f ()
      (let ((*hard-error-is-error* t))
        (handler-case
         (f 3)
         (error (condition)
                (format t \"Got the following error: ~a~%\" condition)))))
  RUN-F
  ? (run-f)
  Got the following error: HARD ACL2 ERROR in F:  F got bad input 3.

  NIL
  ?
 })

 <p>Note that when a raw Lisp error occurs because @('*hard-error-is-error*')
 is non-@('nil'), the error message will not use @(see iprinting).  The reason
 is that the implementation does not make values of iprint indices available
 after the message is printed; so it would be misleading or an error to read
 @('#@i#') after that return.</p>

 @(def hard-error)")

(defxdoc header
  :parents (arrays acl2-built-ins)
  :short "Return the header of a 1- or 2-dimensional array"
  :long "@({
  Example Form:
  (header 'delta1 a)

  General Form:
  (header name alist)
 })

 <p>where @('name') is arbitrary and @('alist') is a 1- or 2-dimensional array.
 This function returns the header of the array @('alist').  The function
 operates in virtually constant time if @('alist') is the semantic value of
 @('name').  See @(see arrays).</p>

 @(def header)")

(defxdoc hidden-death-package
  :parents (packages defpkg)
  :short "Handling @(tsee defpkg) @(see events) that are @(tsee local)"
  :long "<p>This documentation topic explains a little bit about certain errors
 users may see when attempting to evaluate a @(tsee defpkg) event.  In brief,
 if you see an error that refers you to this topic, you are probably trying to
 admit a @(tsee defpkg) event, and you should change the name of the package to
 be introduced by that event.</p>

 <p>Recall that @('defpkg') events introduce axioms, for example as
 follows.</p>

 @({
  ACL2 !>(defpkg \"PKG0\" '(a b))

  Summary
  Form:  ( DEFPKG \"PKG0\" ...)
  Rules: NIL
  Warnings:  None
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
   \"PKG0\"
  ACL2 !>:pr! \"PKG0\"

  Rune:       (:REWRITE PKG0-PACKAGE)
  Status:     Enabled
  Lhs:        (SYMBOL-PACKAGE-NAME (INTERN-IN-PACKAGE-OF-SYMBOL X Y))
  Rhs:        \"PKG0\"
  Hyps:       (AND (STRINGP X)
                   (NOT (MEMBER-SYMBOL-NAME X '(A B)))
                   (SYMBOLP Y)
                   (EQUAL (SYMBOL-PACKAGE-NAME Y) \"PKG0\"))
  Equiv:      EQUAL
  Backchain-limit-lst:    NIL
  Subclass:   BACKCHAIN
  Loop-stopper: NIL
  ACL2 !>
 })

 <p>Now, a @(tsee defpkg) event may be executed underneath an @(tsee
 encapsulate) or @(tsee include-book) form that is marked @(tsee local).  In
 that case, traces of the added axiom will disappear after the surrounding
 @(tsee encapsulate) or @(tsee include-book) form is admitted.  This can cause
 inconsistencies.  (You can take our word for it, or you can look at the
 example shown in the ``Essay on Hidden Packages'' in source file
 @('axioms.lisp').)</p>

 <p>In order to prevent unsoundness, then, ACL2 maintains the following
 invariant.  Let us say that a @('defpkg') event is ``hidden'' if it is in
 support of the current logical @(see world) but is not present in that world
 as an event, because it is @(tsee local) as indicated above.  We maintain the
 invariant that all @(tsee defpkg) @(see events), even if ``hidden'', are
 tracked under-the-hood in the current logical @(see world).  Sometimes this
 property causes @(tsee defpkg) events to be written to the @(see portcullis)
 of a book's @(see certificate) (see @(see books)).  At any rate, if you then
 try to define the package in a manner inconsistent with the earlier such
 definition, that is, with a different imports list, you will see an error
 because of the above-mentioned tracking.</p>

 <p>(By the way, this topic's name comes from Holly Bell, who heard \"hidden
 death package\" instead of \"hidden defpkg\".  The description seemed to fit.
 Thanks, Holly!)</p>")

(defxdoc hidden-defpkg
  :parents (packages defpkg)
  :short "Handling defpkg events that are local"
  :long "<p>See @(see hidden-death-package)</p>")

(defxdoc hide
  :parents (rewrite)
  :short "Hide a term from the rewriter"
  :long "<p>@('Hide') is actually the @(see identity) function: @('(hide x) =
 x') for all @('x').  However, terms of the form @('(hide x)') are ignored by
 the ACL2 rewriter, except when explicit @(':expand') @(see hints) are given
 for such terms (see @(see hints)) or when rewrite rules explicitly about
 @('hide') are available.  An @(':expand') hint that removes all calls of
 @('hide') is:</p>

 @({
  :expand ((:free (x) (hide x)))
 })

 <p>The above hint can be particularly useful when ACL2's equality heuristics
 apply @('hide') to an equality after substituting it into the rest of the
 goal, if that goal (or a subgoal of it) fails to be proved.</p>

 <p>@('Hide') terms are also ignored by the induction heuristics.</p>

 <p>Sometimes the ACL2 simplifier inserts @('hide') terms into a proof attempt
 out of the blue, as it were.  Why and what can you do about it?  Suppose you
 have a constrained function, say @('constrained-fn'), and you define another
 function, say @('another-fn'), in terms of it, as in:</p>

 @({
  (defun another-fn (x y z)
    (if (big-hairy-test x y z)
        (constrained-fn x y z)
        t))
 })

 <p>Suppose the term @('(another-fn 'a 'b 'c)') arises in a proof.  Since the
 arguments are all constants, ACL2 will try to reduce such a term to a constant
 by executing the definition of @('another-fn').  However, after a possibly
 extensive computation (because of @('big-hairy-test')) the execution fails
 because of the unevaluable call of @('constrained-fn').  To avoid subsequent
 attempts to evaluate the term, ACL2 embeds it in a @('hide') expression, i.e.,
 rewrites it to @('(hide (another-fn 'a 'b 'c))').</p>

 <p>You might think this rarely occurs since all the arguments of
 @('another-fn') must be constants.  You would be right except for one special
 case: if @('another-fn') takes no arguments, i.e., is a constant function,
 then every call of it fits this case.  Thus, if you define a function of no
 arguments in terms of a constrained function, you will often see
 @('(another-fn)') rewrite to @('(hide (another-fn))').</p>

 <p>We do not hide the term if the executable-counterpart of the function is
 disabled &mdash; because we do not try to evaluate it in the first place.
 Thus, to prevent the insertion of a @('hide') term into the proof attempt, you
 can globally disable the executable-counterpart of the offending defined
 function, e.g.,</p>

 @({
  (in-theory (disable (:executable-counterpart another-fn))).
 })

 <p>It is conceivable that you cannot afford to do this: perhaps some calls of
 the offending function must be computed while others cannot be.  One way to
 handle this situation is to leave the executable-counterpart enabled, so that
 @('hide') terms are introduced on the calls that cannot be computed, but prove
 explicit :@(tsee rewrite) rules for each of those @('hide') terms.  For
 example, suppose that in the proof of some theorem, thm, it is necessary to
 leave the executable-counterpart of @('another-fn') enabled but that the call
 @('(another-fn 1 2 3)') arises in the proof and cannot be computed.  Thus the
 proof attempt will introduce the term @('(hide (another-fn 1 2 3))').  Suppose
 that you can show that @('(another-fn 1 2 3)') is @('(constrained-fn 1 2 3)')
 and that such a step is necessary to the proof.  Unfortunately, proving the
 rewrite rule</p>

 @({
  (defthm thm-helper
    (equal (another-fn 1 2 3) (constrained-fn 1 2 3)))
 })

 <p>would not help the proof of thm because the target term is hidden inside
 the @('hide').  However,</p>

 @({
  (defthm thm-helper
    (equal (hide (another-fn 1 2 3)) (constrained-fn 1 2 3)))
 })

 <p>would be applied in the proof of thm and is the rule you should prove.</p>

 <p>Now to prove @('thm-helper') you need to use the two ``tricks'' which have
 already been discussed.  First, to eliminate the @('hide') term in the proof
 of @('thm-helper') you should include the hint @(':expand') @('(hide
 (another-fn 1 2 3))').  Second, to prevent the @('hide') term from being
 reintroduced when the system tries and fails to evaluate @('(another-fn 1 2
 3)') you should include the hint @(':in-theory') @('(disable
 (:executable-counterpart another-fn))').  Thus, @('thm-helper') will actually
 be:</p>

 @({
  (defthm thm-helper
    (equal (hide (another-fn 1 2 3)) (constrained-fn 1 2 3))
    :hints
    ((\"Goal\" :expand (hide (another-fn 1 2 3))
             :in-theory (disable (:executable-counterpart another-fn)))))
 })

 <p>See @(see eviscerate-hide-terms) for how to affect the printing of
 @('hide') terms.</p>

 @(def hide)")

(defxdoc hints
  :parents (miscellaneous)
  :short "Advice to the theorem proving process"
  :long "<code>
 Examples:
 The following :hints value is nonsensical.  Nevertheless, it
 illustrates all of the available hint keywords except the
 ``custom keywords'' (see @(see custom-keyword-hints)) definable
 by the user.

 :hints ((\"Goal\"
          :do-not-induct t
          :do-not '(generalize fertilize)
          :expand ((assoc x a)
                   :lambdas
                   (:free (y) (:with member (member y z))))
          :restrict ((&lt;-trans ((x x) (y (foo x)))))
          :hands-off (length binary-append)
          :in-theory (set-difference-theories
                       (current-theory :here)
                       '(assoc))
          :induct (and (nth n a) (nth n b))
          :use ((:instance assoc-of-append
                           (x a) (y b) (z c))
                (:functional-instance
                  (:instance p-f (x a) (y b))
                  (p consp)
                  (f assoc)))
          :bdd (:vars (c a0 b0 a1 b1) :prove nil :bdd-constructors (cons))
          :clause-processor (:function cl-proc :hint (my-hint clause))
          :instructions (:x :prove)
          :cases ((true-listp a) (consp a))
          :by (:instance rev-rev (x (cdr z)))
          :nonlinearp t
          :backchain-limit-rw 3
          :reorder (4 7 2)
          :case-split-limitations (20 10)
          :no-op t
          :no-thanks t
          :error (\"Bad value ~x0.\" 123)
          :or (hint-kwd-alist-1 ... hint-kwd-alist-k)
          :rw-cache-state nil
          :backtrack (my-computed-hint clause processor clause-list)))
 </code>

 <p>Many of these hints affect the how the prover operates not only on the goal
 to which they are applied but also on its subgoals (and its subgoals'
 subgoals, etc.; for a deeper explanation see @(see hints-and-the-waterfall)).
 The following hints, however, have a specific effect only on the goal to which
 they are applied: @(':bdd'), @(':by'), @(':cases'), @(':clause-processor'),
 @(':error'), @(':induct'), @(':or'), and @(':use').  For example, suppose that
 you specify both a @(':cases') hint and an @(':expand') hint for
 @('\"Goal\"').  Then the @(':cases') hint will immediately result in subgoals,
 without calling the ACL2 rewriter; the @(':expand') hint will be used by the
 rewriter in subsequent goals.</p>

 <p>A very common hint is the @(':use') hint, which in general takes as its
 value a list of ``lemma instances'' (see @(see lemma-instance)) but which
 allows a single lemma name as a special case.  Here are two examples, one
 using a single lemma name and one using a lemma instance:</p>

 @({
  ; Attach :use hint to the top-level goal, which is named \"Goal\":
  :hints ((\"Goal\" :use lemma23))

  ; Equivalent to the above: use the trivial instance (i.e., with the empty
  ; substitution of lemma23:
  :hints ((\"Goal\" :use ((:instance lemma23))))

  ; Attach :use hint to the named subgoal, where the indicated lemma is used
  ; with the substitution that maps x to 17 and y to (foo z):
  :hints ((\"[1]Subgoal *1/1.2'\" :use ((:instance lemma23
                                                   (x 17)
                                                   (y (foo z))))))

  ; Equivalent to the above: ACL2 allows you to omit the outer parentheses if
  ; there is only one lemma used.
  :hints ((\"[1]Subgoal *1/1.2'\" :use (:instance lemma23
                                                  (x 17)
                                                  (y (foo z)))))
 })

 <p>ACL2 also provides ``custom keyword'' hints (see @(see
 custom-keyword-hints)) and even more general ``computed hints'' for the
 advanced user (see @(see computed-hints)).</p>

 <p>Only the first hint applicable to a goal, as specified in the user-supplied
 list of @(':hints') followed by the default hints (see @(see
 default-hints-table)), will be applied to that goal.  For an advanced
 exception, see @(see override-hints).  For a detailed discussion of how hints
 fit into the ACL2 waterfall, see @(see hints-and-the-waterfall).  For examples
 of the sophisticated use of hints, primarily for experts, see community book
 @('books/hints/basic-tests.lisp').</p>

 <p>Background: @('Hints') are allowed in all @(see events) that use the
 theorem prover.  During @(tsee defun) @(see events) there are two different
 uses of the theorem prover: one to prove termination and another to verify the
 @(see guard)s.  To pass a hint to the theorem prover during termination
 proofs, use the @(':hints') keyword in the @(tsee defun)'s @(tsee xargs)
 declaration.  To pass a hint to the theorem prover during the @(see guard)
 verification portion of admitting a @(tsee defun), use the @(':guard-hints')
 keyword in the @(tsee defun)'s @(tsee xargs) declaration.  The @(tsee
 verify-guards) event and the @(tsee defthm) event also use the theorem prover.
 To pass hints to them, use the @(':hints') keyword argument to the event.</p>

 @({
  General Form of Common :hints:
    ((goal-spec :key1 val1 ... :keyn valn)
     ...
     (goal-spec :key1 val1 ... :keyn valn))
 })

 <p>where @(tsee goal-spec) is as described elsewhere (see @(see goal-spec))
 and the keys and their respective values are shown below with their
 interpretations.  We also provide ``computed hints'' but discuss them
 separately; see @(see computed-hints).  The hint keywords below are considered
 in alphabetical order.</p>

 <dl>

 <dt>@(':backchain-limit-rw')</dt><p/>

 <dd><p>@('Value') is a natural number or @('nil'), indicating the level of
 backchaining for @(see rewrite), @(see meta), and @(see linear) rules.  This
 overrides, for the current goal and (as with @(':')@(tsee in-theory) hints)
 descendant goals, the default @(see backchain-limit)
 (see @(see set-backchain-limit)).</p></dd>

 <dt>@(':backtrack')</dt><p/>

 <dd><p>This is an advanced hint.  You can probably accomplish its effect by
 the use of ordinary computed hints; see @(see computed-hints).  But if you are
 an expert, read on.  (See @(see hints-and-the-waterfall) for some relevant
 background.)</p>

 <p>@('Value') is a computed hint, which is an expression that evaluates either
 to @('nil') &mdash; indicating that the @(':backtrack') hint is to have no
 effect &mdash; or to a non-empty alternating list of @(':keyi vali') pairs,
 as expected for a hint.  However, unlike ordinary computed hints,
 @(':backtrack') hints are evaluated <b>after</b> a goal has been processed to
 yield zero or more subgoals, not before.  Moreover, variables @('PROCESSOR')
 and @('CLAUSE-LIST') are allowed, but variable
 @('STABLE-UNDER-SIMPLIFICATIONP') is not.  We explain in more detail below,
 but first consider the following simple example.  First we define a standard
 list reversal function:</p>

 @({
  (defun rev (x)
    (if (consp x)
        (append (rev (cdr x)) (cons (car x) nil))
      nil))
 })

 <p>Now we prove:</p>

 @({
  (thm (true-listp (rev x)))
 })

 <p>The successful proof includes the following output.</p>

 @({
  Subgoal *1/1'
  (IMPLIES
    (AND (CONSP X)
         (TRUE-LISTP (REV (CDR X))))
    (TRUE-LISTP (APPEND (REV (CDR X)) (LIST (CAR X))))).

  The destructor terms (CAR X) and (CDR X) can be
  eliminated by using CAR-CDR-ELIM to replace X
  by (CONS X1 X2), (CAR X) by X1 and (CDR X) by
  X2.  This produces the following goal.

  Subgoal *1/1''
  (IMPLIES (AND (CONSP (CONS X1 X2))
                (TRUE-LISTP (REV X2)))
           (TRUE-LISTP (APPEND (REV X2) (LIST X1)))).
 })

 <p>But suppose that we attach a @(':backtrack') hint to the goal above at
 which destructor elimination was applied:</p>

 @({
  (thm (true-listp (rev x))
       :hints ((\"Subgoal *1/1'\"
                :backtrack
                (quote (:do-not '(eliminate-destructors))))))
 })

 <p>Then when ACL2 applies destructor elimination as displayed above, this time
 the @(':backtrack') hint applies, evaluating to @('(:do-not
 '(eliminate-destructors))').  Since this list is not @('nil'), the prover
 decides not to keep the new subgoal, and instead supplies this @(':do-not')
 hint before attacking the goal again.  In this example, ACL2 happens to use a
 technique later in its ``waterfall'' arsenal than destructor elimination,
 namely, generalization:</p>

 @({
  Subgoal *1/1'
  (IMPLIES
    (AND (CONSP X)
         (TRUE-LISTP (REV (CDR X))))
    (TRUE-LISTP (APPEND (REV (CDR X)) (LIST (CAR X))))).

  [Note:  A hint was supplied for our processing
  of the goal above, because of a :backtrack hint
  that is preventing destructor elimination.
  Thanks!]

  We generalize this conjecture, replacing
  (REV (CDR X)) by RV.  This produces

  Subgoal *1/1''
  (IMPLIES (AND (CONSP X) (TRUE-LISTP RV))
           (TRUE-LISTP (APPEND RV (LIST (CAR X))))).
 })

 <p>We now provide a careful explanation of how @(':backtrack') hints work, but
 we suggest that you keep the example above in mind.  If ``@(':backtrack
 form')'' is part of the hint that has been selected for a goal, then @('form')
 is evaluated when one of ACL2's clause processors successfully applies to the
 current goal to produce a list of subgoals.  This evaluation takes place in an
 environment just like that for any computed hint (see @(see computed-hints)),
 with the following exceptions.  First, the variable
 @('STABLE-UNDER-SIMPLIFICATIONP') is not allowed to occur free in @('form'),
 but instead the following new variables are allowed to occur free and are
 bound for this evaluation as follows: @('PROCESSOR') is bound to the processor
 in the list @('*preprocess-clause-ledge*') that has applied to the goal, and
 @('CLAUSE-LIST') is bound to the list of clauses (each a list of literals that
 is implicitly disjoined) returned by that clause processor.  Second, the
 variables @('HIST') and @('PSPV') are bound to the history and pspv returned
 by the clause processor, <b>not</b> the ones that were passed to the clause
 processor.  If this evaluation returns an error, then the proof aborts, as for
 any computed hint whose evaluation returns an error.  If this evaluation
 returns @('nil'), then the @(':backtrack') hint has no effect, and the goal is
 replaced by the list of goals (the value of @('CLAUSE-LIST') described above),
 as usual.  Otherwise, the clause processor is deemed to have failed, and the
 goal clause is tried again starting at the top of the waterfall after
 selecting the hint returned by the above evaluation.  That hint will normally
 be an alternating list of hint keywords and their values, but if it is a
 custom keyword hint (see @(see custom-keyword-hints)), then it will be handled
 in the usual manner but with the first three variables above bound to the
 symbol @(':OMITTED').  Of course, if the new hint includes a value for
 @(':BACKTRACK') then this process can loop; care should be taken to keep that
 from happening.</p>

 <p>A final note about @(':BACKTRACK') hints: since these are a form of
 computed hints, @(see override-hints) (if any) are applied to their evaluation
 result just as with any computed hint.  That is, the backtrack hint is
 successively modified with each override-hint, to produce a final hint that is
 actually used (or, ignored if that final hint is @('nil')).  See @(see
 override-hints).</p></dd>

 <dt>@(':')@(tsee bdd)</dt><p/>

 <dd><p>This hint indicates that ACL2's built-in ordered binary decision
 diagrams (BDDs) with rewriting are to be used to prove or simplify the goal.
 See @(see bdd) for an introduction to the ACL2 BDD algorithm.</p>

 <p>@('Value') is a list of even length, such that every other element,
 starting with the first, is one of the keywords @(':vars'),
 @(':bdd-constructors'), @(':prove'), or @(':literal').  Each keyword that is
 supplied should be followed by a value of the appropriate form, as shown
 below; for others, a default is used.  Although @(':vars') must always be
 supplied, we expect that most users will be content with the defaults used for
 the other values.</p>

 <blockquote>

 <p>@(':vars') &mdash; A list of ACL2 variables, which are to be treated as
 Boolean variables.  The prover must be able to check, using trivial reasoning
 (see @(see type-set)), that each of these variables is Boolean in the context
 of the current goal.  Note that the prover will use very simple heuristics to
 order any variables that do not occur in @(':vars') (so that they are
 ``greater than'' the variables that do occur in @(':vars')), and these
 heuristics are often far from optimal.  In addition, any variables not listed
 may fail to be assumed Boolean by the prover, which is likely to seriously
 impede the effectiveness of ACL2's BDD algorithm.  Thus, users are encouraged
 <i>not</i> to rely on the default order, but to supply a list of variables
 instead.  Finally, it is allowed to use a value of @('t') for @('vars').  This
 means the same as a @('nil') value, except that the BDD algorithm is directed
 to fail unless it can guarantee that all variables in the input term are known
 to be Boolean (in a sense discussed elsewhere; see @(see bdd-algorithm)).</p>

 <p>@(':literal') &mdash; An indication of which part of the current goal
 should receive BDD processing.  Possible values are:</p>

 @({
    :all     treat entire goal as a single literal (the default)
    :conc    process the conclusion
    n        process the hypothesis with index n (1, 2, ...)
 })

 <p>@(':bdd-constructors') &mdash; When supplied, this value should be a list
 of function symbols in the current ACL2 @(see world); it is @('(cons)') by
 default, unless @(':bdd-constructors') has a value in the @(tsee
 acl2-defaults-table) by default, in which case that value is the default.  We
 expect that most users will be content with the default.  See @(see
 bdd-algorithm) for information about how this value is used.</p>

 <p>@(':prove') &mdash; When supplied, this value should be @('t') or @('nil');
 it is @('t') by default.  When the goal is not proved and this value is
 @('t'), the entire proof will abort.  Use the value @('nil') if you are happy
 to the proof to go on with the simplified term.</p>

 </blockquote></dd>

 <dt>@(':by')</dt><p/>

 <dd><p>@('Value') is a @(see lemma-instance), @('nil'), or a new event
 name. If the value is a @(see lemma-instance) (see @(see lemma-instance)),
 then it indicates that the goal (when viewed as a clause) is either equal to
 the proposition denoted by the instance, or is subsumed by that proposition
 when both are viewed as clauses.  To view a formula as a clause, union
 together the negations of the hypotheses and add the conclusion.  For
 example,</p>

 @({
  (IMPLIES (AND (h1 t1) (h2 t2)) (c t1))
 })

 <p>may be viewed as the clause</p>

 @({
  {~(h1 t1) ~(h2 t2) (c t1)}.
 })

 <p>Clause @('c1') is ``subsumed'' by clause @('c2') iff some instance of
 @('c2') is a subset of @('c1').  For example, the clause above is subsumed by
 @('{~(h1 x) (c x)}'), which when viewed as a formula is @('(implies (h1 x) (c
 x))').</p>

 <p>Note that if the value is the name of a function symbol introduced by
 @(tsee defun), then the original form of the body of that definition is used.
 This behavior differs from that provided by a @(':use') hint, which uses the
 normalized (simplified) body; see @(see normalize).</p>

 <p>If the value is @('nil') or a new name, the prover does not even attempt to
 prove the goal to which this hint is attached.  Instead the goal is given a
 ``bye'', i.e., it is skipped and the proof attempt continues as though the
 goal had been proved.  If the prover terminates without error then it reports
 that the proof would have succeeded had the indicated goals been proved and it
 prints an appropriate @(see defthm) form to define each of the @(':by') names.
 The ``name'' @('nil') means ``make up a name.''  Here is an example
 (admittedly contrived for illustration purposes).</p>

 @({
  ACL2 !>(thm (equal (append (append x y) z)
                     (append x y z))
              :hints ((\"Subgoal *1/2'\" :by nil)))

  Name the formula above *1.

  [[... output omitted here ...]]

  [Note:  A hint was supplied for our processing of the goal below.
  Thanks!]

  Subgoal *1/2'
  (IMPLIES (AND (CONSP X)
                (EQUAL (APPEND (APPEND (CDR X) Y) Z)
                       (APPEND (CDR X) Y Z)))
           (EQUAL (APPEND (APPEND X Y) Z)
                  (APPEND X Y Z))).

  But we have been asked to pretend that this goal is subsumed by the
  yet-to-be-proved |THM Subgoal *1/2'|.

  Subgoal *1/1
  [[... proof goes on; further output omitted here ...]]
 })

 <p>The system does not attempt to check the uniqueness of the @(':by') names
 (supplied or made up), since by the time those goals are proved the namespace
 will be cluttered still further.  Therefore, the final list of ``appropriate''
 @(tsee defthm) forms may be impossible to admit without some renaming by the
 user.  If you must invent new names, remember to substitute the new ones for
 the old ones in the @(':by') hints themselves.</p></dd>

 <dt>@(':')@(tsee case-split-limitations)</dt><p/>

 <dd><p>@('Value') is the same as for @(tsee set-case-split-limitations).  The
 simplifier will behave as though the value had instead been supplied to
 @('set-case-split-limitations'); see @(see set-case-split-limitations).  This
 behavior will persist through subgoals unless overridden by another
 @(':CASE-SPLIT-LIMITATIONS') hint.</p></dd>

 <dt>@(':cases')</dt><p/>

 <dd><p>@('Value') is a non-empty list of terms.  For each term in the list, a
 new goal is created from the current goal by assuming that term; and also, in
 essence, one additional new goal is created by assuming all the terms in the
 list false.  We say ``in essence'' because if the disjunction of the terms
 supplied is a tautology, then that final goal will be a tautology and hence
 will in fact never actually be created.</p></dd>

 <dt>@(':')@(tsee clause-processor)</dt><p/>

 <dd><p>@('Value') specifies the application of a user-defined simplifier to
 the current goal.  See @(see clause-processor), which provides necessary
 background and hint syntax.  Also see @(see define-trusted-clause-processor)
 for a discussion of ``trusted clause-processors'': goal-level simplifiers that
 may be external to ACL2 and do not need to be proved correct in ACL2.</p>

 <p>You can see all current @(':clause-processor') rules by issuing the command
 @('(print-clause-processor-rules)'), and you can see the names of all trusted
 clause-processors by issuing the command @('(table
 trusted-clause-processor-table)').</p></dd>

 <dt>@(':do-not')</dt><p/>

 <dd><p>@('Value') is a term having at most the single free variable @(tsee
 world), which when evaluated (with @(tsee world) bound to the current ACL2
 logical @(see world)) produces a list of symbols that is a subset of the
 list</p>

 @({
  (preprocess ;propositional logic, simple rules
   simplify   ;as above plus rewriting, linear arithmetic
   eliminate-destructors
   fertilize  ;use of equalities
   generalize
   eliminate-irrelevance).
 })

 <p>The hint indicates that the ``processes'' named should not be used at or
 below the goal in question.  Thus, to prevent generalization and
 fertilization, say, include the hint</p>

 @({
  :do-not '(generalize fertilize)
 })

 <p>If @('value') is a single symbol, as in</p>

 @({
  :do-not generalize,
 })

 <p>it is taken to be @(''(value)').</p>

 <p>See also @(see do-not-hint) for a way to automatically provide
 @(':do-not') hints across several theorems.</p></dd>

 <dt>@(':do-not-induct')</dt><p/>

 <dd><p>@('Value') indicates whether @(see induction) is permitted under the
 specified goal.  The legal values are @('t'), @(':otf-flg-override'),
 @(':otf'), @('nil'), or a non-keyword symbol other than @('t') or @('nil').
 The default is @('nil'), meaning that induction is permitted as usual.  A
 non-@('nil') value prohibits the use of induction to prove the indicated goal
 or any of its subgoals, as described below.</p>

 <p>If @('value') is @('t') or @(':otf-flg-override'), then the attempt to
 apply @(see induction) to the indicated goal or any subgoal under the
 indicated goal will immediately cause the theorem prover to report @(see
 failure), except that if @(':otf-flg t') is specified (see @(see otf-flg)) and
 @('value') is @('t'), then the proof will continue until the time at which the
 goal pushed for induction is finally encountered and causes failure.  The
 latter behavior is also what occurs if @('value') is @(':otf').  See however
 the @(':induct') hint below.  If @('value') is a non-keyword symbol other than
 @('t') or @('nil'), the theorem prover will skip every subgoal under the
 indicated goal (giving it a ``bye'', as with a ``@(':by')'' hint) that would
 otherwise be attacked with induction.  This will cause the theorem prover to
 fail eventually, printing every subgoal thus skipped in the form of an event
 to prove, each with a name based on the value of the @(':do-not-induct') hint
 that caused that subgoal to be skipped.</p>

 <p>Remarks.  (1) A @(':do-not-induct') hint is ignored for any goal on which
 an @(':induct') hint is supplied.  (2) For an advanced example of the use of
 value @(':otf') for @(':do-not-induct') combined with @(see override-hints),
 see community book @('books/hints/basic-tests.lisp').</p></dd>

 <dt>@(':error')</dt><p/>

 <dd><p>@('Value') is typically a ``fmt message'' to be printed by the @(tsee
 fmt) tilde-directive ~@@ but may be any object.  The effect of this hint is to
 cause an error when the hint is translated.  There is no reason to include an
 @(':ERROR') hint in any user-typein, since it will only cause an error when
 the form is evaluated.  @(':ERROR') hints are useful in the definition of
 functions that generate custom keyword hints (see @(see custom-keyword-hints))
 and computed hints (see @(see computed-hints)).  For example, if you wish to
 define a custom keyword hint @(':my-hint val') and you wish the hint to signal
 an error if there is something inappropriate about @('val') in the context of
 the hint, use the following code to generate the hint</p>

 @({
  (list :ERROR (cons \"Your specified value, ~x0, is inappropriate\"
                     (list (cons #0 val))))
 })

 <p>which is equivalent to</p>

 @({
  (list :ERROR (msg \"Your specified value, ~x0, is inappropriate\"
                    val))
 })

 <p>which, if @('val') has the value @('123'), would evaluate to the hint</p>

 @({
  (:ERROR (\"Your specified value, ~x0, is inappropriate\" (#0 . 123))).
 })

 <p>Note that any time an @(':ERROR') keyword is produced during hint
 processing, including iterations of the expansions of custom keyword hints or
 of @(see override-hints), an error will occur.</p></dd>

 <dt>@(':expand')</dt><p/>

 <dd><p>@('Value') is a true list of terms, each of which is of one of the
 forms @('(let ((v1 t1)...) b)') or @('(fn t1 ... tn)'), where @('fn') is a
 defined function symbol with formals @('v1, ..., vn,') and @('body') @('b').
 Such a term is said to be ``expandable:'' it can be replaced by the result of
 substituting the @('ti')'s for the @('vi')'s in @('b').  The terms listed in
 the @(':expand') hint are expanded when they are encountered by the simplifier
 while working on the specified goal or any of its subgoals.  (There is no
 separate ``expand'' process.)  We permit @('value') to be a single such term
 instead of a singleton list.  <b>Remarks</b>: (1) Allowed are ``terms'' of the
 form @('(:free (var1 var2 ...  varn) pattern)') where the indicated variables
 are distinct and @('pattern') is a term.  Such ``terms'' indicate that we
 consider the indicated variables to be instantiatable, in the following sense:
 whenever the simplifier encounters a term that can be obtained from
 @('pattern') by instantiating the variables @('(var1 var2 ...  varn)'), then
 it expands that term.  (2) Also allowed are ``terms'' of the form @('(:with
 name term)'), where @('name') is a function symbol, a macro name that denotes
 a function symbol (see @(see macro-aliases-table)), or a @(see rune).  The
 corresponding rule of class @(':rewrite'), which is often a @(see definition)
 rule but need not be, is then used in place of the current body for the
 function symbol of @('term'); see @(see show-bodies) and see @(see set-body).
 If the rule is of the form @('(implies hyp (equiv lhs rhs))'), then after
 matching @('lhs') to the current term in a context that is maintaining
 equivalence relation @('equiv'), ACL2 will replace the current term with
 @('(if hyp rhs (hide term))'), or just @('rhs') if the rule is just @('(equal
 lhs rhs)').  (3) A combination of both @(':free') and @(':with'), as described
 above, is legal.  (4) The term @(':LAMBDAS') is treated specially.  It denotes
 the list of all lambda applications (i.e., @(tsee let) expressions)
 encountered during the proof.  Conceptually, this use of @(':LAMBDAS') tells
 ACL2 to treat lambda applications as a notation for substitutions, rather than
 as function calls whose opening is subject to the ACL2 rewriter's
 heuristics (specifically, not allowing lambda applications to open when they
 introduce ``too many'' if terms).</p></dd>

 <dt>@(':hands-off')</dt><p/>

 <dd><p>@('Value') is a true list of function symbols or lambda expressions,
 indicating that under the specified goal applications of these functions are
 not to be rewritten.  Note however that subterms will still be rewritten; see
 @(see hide) if that is not what is intended.  (The community book
 @('books/clause-processors/autohide.lisp') from Jared Davis may also be
 helpful in that case.) @('Value') may also be a single function symbol or
 lambda expression instead of a list.</p></dd>

 <dt>@(':')@(tsee in-theory)</dt><p/>

 <dd><p>@('Value') is a ``theory expression,'' i.e., a term having at most the
 single free variable @(tsee world) which when evaluated (with @(tsee world)
 bound to the current ACL2 logical world (see @(see world))) will produce a
 theory to use as the current theory for the goal specified.  See @(see
 theories).</p>

 <p>Note that an @(':')@(tsee IN-THEORY) hint will always be evaluated relative
 to the current ACL2 logical @(see world), not relative to the theory of a
 previous goal.  Consider the following example.</p>

 @({
  (defthm prop
    (p (f (g x)))
    :hints ((\"Goal\"      :in-theory (disable f))
            (\"Subgoal 3\" :in-theory (enable  g))))
 })

 <p>Consider in particular the theory in effect at @('Subgoal 3').  This call
 of the @(tsee enable) macro enables @('g') relative to the @(tsee
 current-theory) of the current logical @(see world), <i>not</i> relative to
 the theory produced by the hint at @('Goal').  Thus, the @(tsee disable) of
 @('f') on behalf of the hint at @('Goal') will be lost at @('Subgoal 3'), and
 @('f') will be enabled at @('Subgoal 3') if was enabled globally when
 @('prop') was submitted.</p></dd>

 <dt>@(':induct')</dt><p/>

 <dd><p>@('Value') is either @('t') or a term containing at least one
 recursively defined function symbol; if @('t'), this hint indicates that the
 system should proceed to apply its induction heuristic to the specified goal
 produced (without trying simplification, etc.); if @('value') is a term other
 than @('t'), then not only should the system apply induction immediately, but
 it should analyze @('value') rather than the goal to generate its @(see
 induction) scheme.  Merging and the other @(see induction) heuristics are
 applied.  Thus, if @('value') contains several mergeable @(see induction)s,
 the ``best'' will be created and chosen.  E.g., the @(':induct') hint</p>

 @({
   (and (nth i a) (nth j a))
 })

 <p>suggests simultaneous @(see induction) on @('i'), @('j'), and @('a').</p>

 <p>If both an @(':induct') and a @(':do-not-induct') hint are supplied for a
 given goal then the indicated @(see induction) is applied to the goal and the
 @(':do-not-induct') hint is inherited by all subgoals generated.</p></dd>

 <dt>@(':')@(tsee instructions)</dt><p/>

 <dd><p>@('Value') is a list of interactive @(see proof-builder) instructions;
 see @(see instructions).  Unlike other hint keywords described here, this one
 is actually a custom keyword hint (see @(see custom-keyword-hints)) that
 generates a suitable @(':')@(tsee clause-processor) hint.</p></dd>

 <dt>@(':no-op')</dt><p/>

 <dd><p>@('Value') is any object and is irrelevant.  This hint does nothing.
 But empty hints, such as @('(\"Goal\")'), are illegal and there are occasions,
 especially when writing custom keyword hints
 (see @(see custom-keyword-hints)) and computed hints (see @(see
 computed-hints)) where it is convenient to be able to generate a non-empty
 no-op hint.  The standard idiom is @('(\"Goal\" :NO-OP T)') but the @('T') is
 completely ignored.  Unlike other hint keywords, multiple occurrences of the
 keyword @(':NO-OP') are tolerated.</p></dd>

 <dt>@(':no-thanks')</dt><p/>

 <dd><p>@('Value') is any object.  This hint does nothing, except that if
 @('value') is non-@('nil') then the usual ``[Note: A hint was
 supplied... Thanks!]'' is not printed.</p></dd>

 <dt>@(':nonlinearp')</dt><p/>

 <dd><p>@('Value') is @('t') or @('nil'), indicating whether @(see
 non-linear-arithmetic) is active.  The default value is @('nil').  See @(see
 non-linear-arithmetic).</p></dd>

 <dt>@(':or')</dt><p/>

 <dd><p>@('Value') is a list @('(kwd-val-listp-1 ... kwd-val-listp-k)'), where
 each @('kwd-val-listp-i') is a list satisfying @(tsee keyword-value-listp),
 i.e., an alternating list of keywords and values.  This hint causes an attempt
 to prove the specified goal using hints @('kwd-val-listp-i') in
 sequence (first @('kwd-val-listp-1'), then @('kwd-val-listp-2'), and so on),
 until the first of these succeeds.  If none succeeds, then the prover proceeds
 after heuristically choosing the ``best'' result, taking into account the
 goals pushed in each case for proof by induction.</p>

 <p>The following (contrived but illustrative example illustrates how @(':or')
 hints work.</p>

 @({
    ACL2 !>(thm (f x)
                :hints
                ((\"Goal\"
                  :expand ((nth x 3))
                  :or ((:in-theory (disable car-cons))
                       (:use cdr-cons :in-theory (enable append)))
                  :do-not '(generalize))))

    [Note:  A hint was supplied for our processing of the goal above.
    Thanks!]

    The :OR hint for Goal gives rise to two disjunctive branches.  Proving
    any one of these branches would suffice to prove Goal.  We explore
    them in turn, describing their derivations as we go.

    ---
    Subgoal D2
    ( same formula as Goal ).

    The first disjunctive branch (of 2) for Goal can be created by applying
    the hint:
    (\"Subgoal D2\" :EXPAND ((NTH X 3))
                  :IN-THEORY (DISABLE CAR-CONS)
                  :DO-NOT '(GENERALIZE)).

    [Note:  A hint was supplied for our processing of the goal above.
    Thanks!]

    Normally we would attempt to prove this formula by induction.  However,
    we prefer in this instance to focus on the original input conjecture
    rather than this simplified special case.  We therefore abandon our
    previous work on this conjecture and reassign the name *1 to the original
    conjecture.  (See :DOC otf-flg.)  [Note:  Thanks again for the hint.]

    ---
    Subgoal D1
    ( same formula as Goal ).

    The second disjunctive branch (of 2) for Goal can be created by applying
    the hint:
    (\"Subgoal D1\" :EXPAND ((NTH X 3))
                  :USE CDR-CONS
                  :IN-THEORY (ENABLE APPEND)
                  :DO-NOT '(GENERALIZE)).

    [Note:  A hint was supplied for our processing of the goal above.
    Thanks!]

    ACL2 Warning [Use] in ( THM ...):  It is unusual to :USE an enabled
    :REWRITE or :DEFINITION rule, so you may want to consider disabling
    (:REWRITE CDR-CONS).

    We augment the goal with the hypothesis provided by the :USE hint.
    The hypothesis can be obtained from CDR-CONS.  We are left with the
    following subgoal.

    Subgoal D1'
    (IMPLIES (EQUAL (CDR (CONS X Y)) Y)
             (F X)).

    By the simple :rewrite rule CDR-CONS we reduce the conjecture to

    Subgoal D1''
    (F X).
 })

 <p>... and so on.  This example illustrates how ACL2 processes @(':or') hints
 in general.  For each @('i') from 1 to @('k'), a so-called ``disjunctive''
 subgoal is created by splicing @('kwd-val-listp-i') into the other hint values
 (if any) supplied for the given goal, in order.  A corresponding subgoal is
 created for each @('i'), numbered in the usual manner (hence, counting down)
 except that the ``@('D')'' is prefixed to each resulting goal.</p></dd>

 <dt>@(':reorder')</dt><p/>

 <dd><p>@('Value') is a list of positive integers without duplicates,
 corresponding to the numbering of subgoals generated for the @(see goal-spec)
 @('\"G\"'), say @('\"G.k\"') down to @('\"G.1\"').  Those subgoals are
 reordered so that if @('value') is @('(n1 n2 ... nk)'), then the goal now
 numbered @('\"G.k\"') will be the goal originally numbered @('\"G.n1\"'); the
 goal now numbered @('\"G.k-1\"') will be the goal formerly numbered
 @('\"G.n2\"'); and so on, down the list of @('ni'), after which the goals not
 yet printed are printed in their original order.  Note that reordering for
 subgoals of a goal to be proved by induction, such as @('*1'), is not
 supported.</p></dd>

 <dt>@(':restrict')</dt><p/>

 <dd><p>Warning: This is a sophisticated hint, suggested by Bishop Brock, that
 is intended for advanced users.  In particular, @(':restrict') hints are
 ignored by the preprocessor, so you might find it useful to give the hint
 @(':do-not '(preprocess)') when using any @(':restrict') hints, at least if
 the rules in question are abbreviations (see @(see simple)).</p>

 <p>@('Value') is an association list.  Its members are of the form @('(x
 subst1 subst2 ...)'), where: @('x') is either (1) a @(see rune) whose @(tsee
 car) is @(':')@(tsee rewrite) or @(':')@(tsee definition) or (2) an event name
 corresponding to one or more such @(see rune)s; and @('(subst1 subst2 ...)')
 is a non-empty list of substitutions, i.e., of association lists pairing
 variables with terms.  First consider the case that @('x') is a @(':')@(tsee
 rewrite) or @(':')@(tsee definition) @(see rune).  Recall that without this
 hint, the rule named @('x') is used by matching its left-hand side (call it
 @('lhs')) against the term currently being considered by the rewriter, that
 is, by attempting to find a substitution @('s') such that the instantiation of
 @('lhs') using @('s') is equal to that term.  If however the @(':restrict')
 hint contains @('(x subst1 subst2 ...)'), then this behavior will be modified
 by restricting @('s') so that it must extend @('subst1'); and if there is no
 such @('s'), then @('s') is restricted so that it must extend @('subst2'); and
 so on, until the list of substitutions is exhausted.  If no such @('s') is
 found, then the rewrite or definition rule named @('x') is not applied to that
 term.  Finally, if @('x') is an event name corresponding to one or more
 @(':')@(tsee rewrite) or @(':')@(tsee definition) @(see rune)s (that is,
 @('x') is the ``base symbol'' of such @(see rune)s; see @(see rune)), say
 @(see rune)s @('r1'), ... @('rn'), then the meaning is the same except that
 @('(x subst1 subst2 ...)') is replaced by @('(ri subst1 subst2 ...)') for each
 @('i').  Once this replacement is complete, the hint may not contain two
 members whose @(tsee car) is the same @(see rune).</p>

 <p>Note that the substitutions in @(':restrict') hints refer to the variables
 actually appearing in the goals, not to the variables appearing in the rule
 being restricted.</p>

 <p>Here is an example, supplied by Bishop Brock.  Suppose that the database
 includes the following rewrite rule, which is probably kept @(see disable)d.
 (We ignore the question of how to prove this rule.)</p>

 @({
  cancel-<-*$free:
  (implies (and (rationalp x)
                (rationalp y)
                (rationalp z))
           (equal (< y z)
                  (if (< x 0)
                      (> (* x y) (* x z))
                    (if (> x 0)
                        (< (* x y) (* x z))
                      (hide (< y z))))))
 })

 <p>Then ACL2 can prove the following theorem (unless other rules get in the
 way), essentially by multiplying both sides by @('x').</p>

 @({
  (thm
    (implies (and (rationalp x)
                  (< 1 x))
             (< (/ x) 1))
    :hints
    ((\"Goal\"
      :in-theory (enable cancel-<-*$free)
      :restrict ((cancel-<-*$free ((x x) (y (/ x)) (z 1)))))))
 })

 <p>The @(':restrict') hint above says that the variables @('x'), @('y'), and
 @('z') in the rewrite rule @('cancel-<-*$free') above should be instantiated
 respectively by @('x'), @('(/ x)'), and @('1').  Thus @('(< y z)') becomes
 @('(< (/ x) 1)'), and this inequality is replaced by the corresponding
 instance of the right-hand-side of @('cancel-<-*$free').  Since the current
 conjecture assumes @('(< 1 x)'), that instance of the right-hand side
 simplifies to</p>

 @({
  (< (* x (/ x)) (* x 1))
 })

 <p>which in turn simplifies to @('(< 1 x)'), a hypothesis in the present
 theorem.</p></dd>

 <dt>@(':rw-cache-state')</dt><p/>

 <dd><p>@('Value') is an element of the list constant
 @('*legal-rw-cache-states*'): @(':atom') (the default), @('nil'), @('t'), or
 @(':disabled').  This hint applies to the indicated goal and all its
 descendants, to set the so-called ``rw-cache-state'' to the indicated value;
 see @(see set-rw-cache-state).</p></dd>

 <dt>@(':use')</dt><p/>

 <dd><p>Examples of @(':USE') hints are shown near the top of this
 documentation topic.</p>

 <p>@('Value') is a @(see lemma-instance) or a true list of @(see
 lemma-instance)s, indicating that the propositions denoted by the instances be
 added as hypotheses to the specified goal.  Note that @(':use') makes the
 given instances available as ordinary hypotheses of the formula to be proved.
 The @(':instance') form of a @(see lemma-instance) permits you to instantiate
 the free variables of previously proved theorems any way you wish, even
 allowing for differences in @(see packages); see @(see lemma-instance) for
 details.  These new hypotheses participate fully in all subsequent rewriting,
 etc.  If the goal in question is in fact an instance of a previously proved
 theorem, you may wish to use @(':by') below.  Note that @(see theories) may be
 helpful when employing @(':use') hints; see @(see minimal-theory).</p>

 <p>Note that if the value is the name of a function symbol introduced by
 @(tsee defun), then the normalized (simplified) body of that definition is
 used; see @(see normalize).  This behavior differs from that provided by a
 @(':by') hint, where the original body of the definition is used.</p></dd>

 </dl>")

(defxdoc hints-and-the-waterfall
  :parents (hints)
  :short "How @(see hints) fit into the ACL2 proof waterfall"
  :long "<p>Below we describe the flow of an ACL2 proof attempt, with special
 attention to how @(see hints) are applied during a proof.  For most ACL2
 users, only one point is important to take away from this @(see documentation)
 topic: you may specify hints during a proof (see @(see hints); perhaps also
 see @(see computed-hints) and see @(see default-hints)), and they can be
 expected to behave intuitively.  See @(see the-method) for a summary of how to
 interact with the ACL2 prover; see @(see introduction-to-the-theorem-prover)
 for a more detailed tutorial; and see @(see hints) for an introduction to ACL2
 hints, including detailed @(see documentation) for specific hint types.</p>

 <p>The remainder of this topic serves as a reference in case one needs a
 deeper understanding of the workings of ACL2's handling of hints.  Also, for
 examples of the sophisticated use of hints, primarily for experts, see
 community book @('books/hints/basic-tests.lisp').</p>

 <p>First, we describe the ACL2 ``waterfall'', which handles each goal either
 by replacing it with a list (possibly empty) of child goals, or else by
 putting the goal into a ``pool'' for later proof by induction.  Then, we
 describe how hints are handled by the waterfall.</p>

 <p><b>The Waterfall.</b></p>

 <p>Each goal considered by the ACL2 prover passes through a series of proof
 processes, called the ``waterfall processes'', as stored in the constant
 @('*preprocess-clause-ledge*').  The top process applies top-level hints,
 including @(':use') hints; the next is a lightweight ``preprocess'' simplifier
 for ``simple'' rules (see @(see simple)); the next is the main ACL2
 simplifier; and finally ACL2 attempts (in this order) destructor elimination,
 fertilization (heuristic use of equalities), generalization, and elimination
 of irrelevance.  See @(see architecture-of-the-prover) for more information on
 these processes.  Each process may ``hit'', creating zero or more child goals
 that are each then handled at the top of the waterfall; or it may ``miss'', in
 which case the next process in the above sequence is considered.  If all
 processes miss, then a ``push'' process defers the goal until it is later
 considered for proof by induction.  When all goals have been thus handled, the
 goal most recently pushed for proof by induction is considered, and the
 process repeats.</p>

 <p>We next describe the two additional ways in which control can be returned
 to the top of the waterfall.</p>

 <p>When the simplification process is attempted unsuccessfully for a goal, the
 goal is deemed to have ``settled down''.  In this case, and if no ancestor of
 the goal has settled down, then the ``settled-down'' process is deemed to have
 ``hit'' on the goal, the effect being that the goal makes a new pass through
 all the waterfall processes.  (Other processes can then notice that settling
 down has occurred and modify their heuristics accordingly.)  For example, if
 @('\"Goal\"') simplifies to @('\"Subgoal 2\"') (among others), and
 @('\"Subgoal 2\"') simplifies to @('\"Subgoal 2.3\"') (among others), which in
 turn is not further simplified, then the ``settled-down'' process hits on
 @('\"Subgoal 2.3\"') but not on any of its children, their children, and so
 on.</p>

 <p>When simplification has missed (and thus the goal has settled down), the
 next proof process is normally destructor elimination.  However, if a computed
 hint is suitable (in a sense described below; also see @(see computed-hints),
 especially the discussion of @('stable-under-simplificationp')), then that
 hint is selected as control is returned to the top of the waterfall.  A
 subtlety is that in this case, if the most recent hit had been from settling
 down, then the prover ``changes its mind'' and considers that the goal has not
 yet settled down after all as it continues through the waterfall.</p>

 <p>Each time a goal is considered at the top of the waterfall, then before
 passing through the proof processes as described above, ACL2 searches for a
 relevant hint to select unless it has already been provided a hint in the
 ``@('stable-under-simplificationp')'' case mentioned above.  We turn now to a
 more thorough discussion of how hints are selected and applied.</p>

 <p><b>The handling of hints.</b></p>

 <p>In the discussion below we will ignore forcing rounds, as each forcing
 round is simply treated as a new proof attempt that uses the list of hints
 provided at the start of the proof.</p>

 <p>When the theorem prover is called by @(tsee thm) or @(see events) such as
 @(tsee defthm), @(tsee defun), and @(tsee verify-guards), it gathers up the
 hints that have been supplied, often provided as a @(':')@(tsee hints)
 argument, but for example using a @(':guard-hints') argument for @(see guard)
 verification proofs.  (ACL2(r) users (see @(see real)) may also employ
 @(':std-hints').)  It then appends these to the front of the list of default
 hints (see @(see default-hints)).  The resulting list becomes the initial
 value of the list of ``pending hints'', one of two critical lists maintained
 by the theorem prover to manage hints.  The other critical list is a list of
 ``hint settings''; the two lists are maintained as follows.</p>

 <p>When a goal is first considered, a hint is selected from the list of
 pending hints if any is found to apply, as described below.  If a hint is
 selected, then it takes effect and is removed from the pending hints.  Except:
 if the selected hint is a computed hint with value @('t') specified for
 @(':computed-hint-replacement'), then it is not removed; and if that value is
 a list of hints, then that list is appended to the front of the list of
 pending hints after the selected hint is removed (also see @(see
 computed-hints)).  The selected hint is also used to update the hint settings,
 as described below.</p>

 <p>The list of hint settings associates hint keywords with values.  It is
 passed from the current goal to its children (and hence the children's
 children, and so on), though modified by hints selected from pending hints, as
 described below.  This list is maintained so that when a goal is pushed for
 proof by induction, the hint settings are applied at the start of the proof by
 induction.  Note that the list of hint settings is not re-applied to
 descendants of a goal in the current waterfall; a hint is applied only when it
 is selected (and also perhaps later as just described, through the stored hint
 settings at the start of a proof by induction).  For example, if the hint
 selected for @('\"Subgoal 3\"') includes @(':in-theory (enable foo)'), then
 the hint settings are correspondingly updated when processing @('\"Subgoal
 3\"'), and they persist at subgoals such as @('\"Subgoal 3.2\"') and
 @('\"Subgoal 3.2.1\"') (unless overridden by hints on those goals); but the
 theory specifying @('foo') is not re-installed at every such subgoal.</p>

 <p>When a hint is selected, the list of hint settings is updated so that for
 each keyword @(':kwd') and associated value @('val') from the hint, @(':kwd')
 is associated with @('val') in the hint settings, discarding any previous
 association of @(':kwd') with a value in the hint settings.  Except, certain
 ``top-level'' hints are never saved in the hint settings: @(':use'),
 @(':cases'), @(':by'), @(':bdd'), @(':or'), and @(':clause-processor').</p>

 <p>For example, suppose that we specify the following hints, with no default
 hints.</p>

 @({
  ((\"Goal\" :expand ((bar x y)))
   (\"Subgoal 3\" :in-theory (enable foo)))
 })

 <p>These hints then become the initial list of pending hints.  When the proof
 attempt begins, the prover encounters the top-level goal (@('\"Goal\"')) and
 pulls the @('\"Goal\"') hint from the pending hints, so that the list of hint
 settings contains a value only for keyword @(':expand').  This hint setting
 will remain for all children of the top-level goal as well, and their
 children, and so on, and will be inherited by induction &mdash; in other
 words, it will remain throughout the entire proof.  Now consider what happens
 when the proof reaches @('\"Subgoal 3\"').  At this point there is only one
 pending hint, which is in fact attached to that subgoal.  Therefore, this hint
 is pulled from the pending hints (leaving that list empty), and the hint
 settings are extended by associating the @(':in-theory') keyword with the
 theory represented by @('(enable foo)').  That theory is immediately installed
 until the prover finishes addressing @('\"Subgoal 3\"'), its children, their
 children, and so on; and until that completion is reached, the @(':in-theory')
 keyword remains associated with the @('(enable foo)') in the hint settings,
 although of course there is no re-installation of the theory at any ensuing
 child goal.  When finally @('\"Subgoal 3\"') and its descendants have been
 completed and the prover is about to consider @('\"Subgoal 2\"'), the
 @(':in-theory') association is removed from the hint settings and the global
 theory is re-installed.  However, the list of pending hints remains empty.</p>

 <p>It remains to describe how a hint is selected for a goal.  When a goal is
 first considered (hence at the top of the waterfall), the list of pending
 hints is scanned, in order, until one of the hints is suitable for the goal.
 An explicit hint @('(goal-name :kwd1 val1 ... :kwdn valn)') is suitable if
 @('goal-name') is the name of the current goal and there is at least one
 keyword.  A computed hint is suitable if it evaluates to a non-@('nil') value.
 As indicated earlier in this documentation topic, an exception occurs when a
 computed hint is selected after simplification fails (the
 ``@('stable-under-simplificationp')'' case): in that case, the goal returns to
 the top of the waterfall with that hint as the selected hint, and no
 additional search for a hint to select is made at that time.</p>

 <p>The following slightly tricky example illustrates handling of hints.</p>

 @({
  ACL2 !>(set-default-hints '((\"Goal\" :do-not '(preprocess))))
   ((\"Goal\" :DO-NOT '(PREPROCESS)))
  ACL2 !>(thm (equal (append (append x y) z) (append x y z))
              :hints ((\"Goal\" :in-theory (disable car-cons))))

  ACL2 Warning [Hints] in ( THM ...):  The goal-spec \"Goal\" is explicitly
  associated with more than one hint.  All but the first of these hints
  may be ignored.  If you intended to give all of these hints, combine
  them into a single hint of the form (\"Goal\" :kwd1 val1 :kwd2 val2 ...).
  See :DOC hints-and-the-waterfall.

  [Note:  A hint was supplied for our processing of the goal above.
  Thanks!]

  [Note:  A hint was supplied for our processing of the goal above.
  Thanks!]

  Name the formula above *1.
 })

 <p>The warning above is printed because @('\"Goal\"') is associated with two
 pending hints: one given by the @(tsee set-default-hints) call and one
 supplied by the @(':')@(tsee hints) keyword of the @(tsee thm) form.  The
 @(':in-theory') hint is selected because user-supplied hints are ahead of
 default hints in the list of pending hints; we then get the first ``Note''
 above.  The goal progresses through the waterfall without any proof process
 applying to the goal; in particular, it cannot be further simplified.  After
 the simplification process, a ``settled-down'' process applies, as discussed
 above, immediately causing another trip through the waterfall.  Since the
 @(':in-theory') hint was earlier removed from the list of pending hints when
 it was applied, the default (@(':do-not')) hint is now the only pending hint.
 That hint is applied, resulting in the second ``Note'' above.</p>

 <p>Again, more examples may be found in the community book
 @('books/hints/basic-tests.lisp').  A particularly tricky but informative
 example in that book is the one related to @('nonlinearp-default-hint').</p>

 <p>Also see @(see override-hints) for an advanced feature that allows
 modification of the hint selected for a goal.</p>")

(defxdoc history
  :parents (acl2)
  :short "Functions to display or change contents of the logical @(see world)"
  :long "<p>ACL2 keeps track of the @(see command)s that you have executed that
 have extended the logic or the rule database, as by the definition of macros,
 functions, etc.  Using the facilities in this section you can review the
 sequence of @(see command)s executed so far.  For example, you can ask to see
 the most recently executed @(see command), or the @(see command) @('10')
 before that, or the @(see command) that introduced a given function symbol.
 You can also undo back through some previous @(see command), restoring the
 logical @(see world) to what it was before the given @(see command).</p>

 <p>The annotations printed in the margin in response to some of these commands
 (including `P', `L', `V', `D', `d', 'M', and 'm') are explained in the
 documentation for @(':')@(tsee pc).</p>

 <p>Several technical terms are used in the documentation of the history @(see
 command)s.  You must understand these terms to use the @(see command)s.  These
 terms are documented via @(':')@(tsee doc) entries of their own.  See @(see
 command), see @(see events), see @(see command-descriptor), and see @(see
 logical-name).</p>")

(defxdoc hons
  :parents (programming hons-and-memoization acl2-built-ins)
  :short "@('(hons x y)') returns a @(see normed) object equal to @('(cons x
  y)')."
  :long "<p>In the logic, @('hons') is just @(tsee cons); we leave it enabled
 and would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, @('hons') does whatever is necessary to ensure that its
 result is @(see normed).</p>

 <p>What might this involve?</p>

 <p>Since the car and cdr of any normed cons must be normed, we need to @(tsee
 hons-copy) x and y.  This requires little work if x and y are already normed,
 but can be expensive if x or y contain large, un-normed cons structures.</p>

 <p>After that, we need to check whether any normed cons equal to @('(x . y)')
 already exists.  If so, we return it; otherwise, we need to construct a new
 cons for @('(x . y)') and install it as the normed version of @('(x
 . y)').</p>

 <p>Generally speaking, these extra operations make @('hons') much slower than
 @('cons'), even when given normed arguments.</p>

 @(def hons)")

(defxdoc hons-acons
  :parents (fast-alists acl2-built-ins)
  :short "@('(hons-acons key val alist)') is the main way to create or extend
@(see fast-alists)."
  :long "<p>Logically, @('hons-acons') is like @(tsee acons) except that its
 guard does not require @(tsee alistp); we leave it enabled and would think it
 odd to ever prove a theorem about it.</p>

 <p>Under the hood, two things are done differently.  First, the key is copied
 with @(tsee hons-copy); this lets us use EQL-based hash tables instead of
 EQUAL-based hash tables for better performance.  Second, assuming there is a
 valid hash table associated with this alist, we destructively update the hash
 table by binding key to val.  The hash table will no longer be associated with
 alist, but will instead be associated with the new alist returned by
 @('hons-acons').</p>

 <p>Hash Table Creation</p>

 <p>A new hash table is created by @('hons-acons') whenever alist is an atom.
 Unlike ordinary @('acons'), we do not require that alist be nil, and in fact
 you may wish to use a non-nil value for one of two reasons.</p>

 <p>1.  As a size hint</p>

 <p>By default, the new hash table will be given a quite modest default
 capacity of 60 elements.  As more elements are added, the table may need to be
 resized to accommodate them, and this resizing has some runtime cost.</p>

 <p>When a natural number is used as a fast alist's name, we interpret it as a
 size hint.  For example, @('(hons-acons 'foo 'bar 1000)') instructs us to use
 1000 as the initial size for this hash table and binds 'foo to 'bar.  The
 resulting table should not need to be resized until more than 1000 elements
 are added.  We ignore size hints that request fewer than 60 elements.</p>

 <p>Because of hash collisions, hash tables typically need to have a larger
 size than the actual number of elements they contain.  The hash tables for
 fast alists are told to grow when they reach 70% full.  So, an easy rule of
 thumb might be: multiply the expected number of elements you need by 1.5 to
 keep your hash tables about 2/3 full.</p>

 <p>2.  As an alist name</p>

 <p>We also frequently use a symbol for alist, and think of this symbol as the
 name of the new alist.  We have found that naming alists can be valuable for
 two reasons:</p>

 <p>First, the name can be helpful in identifying fast alists that should have
 been freed, see @(tsee fast-alist-summary).</p>

 <p>Second, names can sometimes be used to avoid a subtle and insidious
 table-stealing phenomenon that occurs when using fast-alists that are
 themselves normed; see @(tsee hons-acons!).</p>

 <p>At the moment, there is no way to simultaneously name a fast alist and also
 give it a size hint.  We may eventually allow strings to include embedded name
 and size components, but for now we have not implemented this
 capability.</p>

 @(def hons-acons)")

(defxdoc hons-acons!

; Near the end of the :long string below, we say that hons-acons is "the
; typical way to generate a fast alist that is normed".  We say "typical" not
; only because of fast-alist-fork! (and fast-alist-clean!), but also because of
; the following less direct way to generate a fast alist that is normed:
; (make-fast-alist (hons-copy alist)).

  :parents (fast-alists acl2-built-ins)
  :short "@('(hons-acons! key val alist)') is an alternative to @(tsee
hons-acons) that produces @(see normed), fast alists."
  :long "<p>Logically, @('hons-acons!') is like @(tsee acons) except that its
 guard does not require @(tsee alistp); we leave it enabled and would think it
 odd to ever prove a theorem about it.</p>

 <p>Ordinarily, @(see fast-alists) are constructed with @(tsee hons-acons)
 instead of @('hons-acons!').  In such alists, the keys are honsed, but the
 conses that make up the \"spine\" of the alist itself are ordinary conses.  In
 other words, it is basically correct to say:</p>

 @({
   (hons-acons key val alist) == (cons (cons (hons-copy key) val) alist)
 })

 <p>In contrast, when @('hons-acons!') is used, the conses making up the alist
 itself are also normed.  That is,</p>

 @({
   (hons-acons! key val alist) == (hons (hons key val) alist)
 })

 <p>Generally, you <b>should not use</b> @('hons-acons!') unless you really
 know what you're doing.</p>

 <p>Drawback 1.  @('hons-acons!') requires you to @(tsee hons-copy) all of the
 values that are being stored in the fast alist.  If you are storing large
 values, this may be expensive.</p>

 <p>Drawback 2.  It can be more difficult to maintain the proper discipline
 when using @('hons-acons!').  For instance, consider the following:</p>

 @({
    (let ((al1 (hons-acons 1 'one (hons-acons 2 'two nil)))
          (al2 (hons-acons 1 'one (hons-acons 2 'two nil))))
       ...)
 })

 <p>Here, both al1 and al2 are valid fast alists and they can be extended
 independently without any trouble.  But if these alists had instead been
 constructed with @('hons-acons!'), then since both al1 and al2 are equal,
 normed conses, they will literally be @(tsee eq) and hence will refer to
 precisely the same hash table.  In other words, @('hons-acons!') makes it
 relatively easy to <b>inadvertently</b> steal the hash table associated with
 some other fast alist.  This problem can be alleviated somewhat by uniquely
 naming alists; see the discussion in @(tsee hons-acons) for details.</p>

 <p>Despite these drawbacks, @('hons-acons!') is the typical way to generate a
 fast alist that is normed (but also, for example, see @(see
 fast-alist-fork!)).  It is not adequate to @(tsee hons-copy) a fast alist that
 was generated by ordinary @(tsee hons-acons) calls, because this would produce
 an EQUAL-but-not-EQ object, and this new object would not be associated with
 the fast alist's hash table.</p>

 @(def hons-acons!)")

(defxdoc hons-and-memoization
  :parents (acl2)
  :short "Hash cons, function memoization, and applicative hash tables"
  :long "<p>This topic describes the hash cons, function memoization, and
 applicative hash tables features available in ACL2, sometimes called the
 ``@(see hons-enabled)'' features.</p>

 <p>Bob Boyer and Warren Hunt, and later Jared Davis and Sol Swords, have
 developed a canonical representation for ACL2 data objects and a function
 memoization mechanism to facilitate reuse of previously computed results.
 This facility includes procedures to read and print ACL2 expressions in such a
 way that repetition of some ACL2 objects is eliminated, thereby permitting a
 kind of on-the-fly file compression.  The implementation does not alter the
 semantics of ACL2 except to add a handful of definitions.</p>

 <p>We historically gave the name ``ACL2(h)'' to the experimental extension of
 the ACL2 system including hash cons, function memoization, and fast
 association lists (applicative hash tables).  These features, which we call
 the ``@(see hons-enabled)'' features, are now present in ACL2.  The
 hons-enabled features are optimized for Clozure Common Lisp (CCL) and to some
 extent, GNU Common Lisp (GCL ANSI); but they are also supported in every ACL2
 build.</p>

 <p>Power users who want to take advantage of the @(see hons-enabled) features
 of ACL2 might find it helpful to consult the document @('centaur/README.html')
 in the ACL2 community books.</p>

 <p>Much of the documentation for the remainder of this topic is taken from the
 paper ``Function Memoization and Unique Object Representation for ACL2
 Functions'' by Robert S. Boyer and Warren A. Hunt, Jr., which has appeared in
 the Sixth International Workshop on the ACL2 Theorem Prover and Its
 Applications, ACM Digital Library, 2006.</p>

 <p>In the implementation of the ACL2 logic, ACL2 data objects are represented
 by Common Lisp objects of the same type, and the ACL2 pairing operation is
 internally implemented by the Common Lisp @(tsee cons) function.  In Common
 Lisp, @('cons') is guaranteed to provide a new pair, distinct from any
 previously created pair.  We have defined a new ACL2 function @(tsee HONS)
 that is logically identical to the ACL2 @('cons') function, but whose
 implementation usually reuses an existing pair if its components are identical
 to the components of an existing pair.  A record of ACL2 HONS objects is kept,
 and when an ACL2 function calls @('hons') ACL2 searches for an existing
 identical pair before allocating a new pair; this operation been called ``hash
 consing''.</p>

 <p>It appears that hash consing was first conceived by A. P. Ershov in 1957,
 to speed up the recognition of common subexpressions.  Ershov showed how to
 collapse trees to minimal DAGs by traversing trees bottom up, and he used
 hashing to eliminate the re-evaluation of common subexpressions.  In his 1973
 PhD dissertation L. Peter Deutsch describes a program verifier that uses hash
 cons to represent terms and his rewriter operated on hash consed terms.
 Later, Eiichi Goto implemented a Lisp system with a built-in hash consing
 operation: his h-CONS cells were rewrite protected and free of duplicate
 copies, and Goto used this hash consing operation to facilitate the
 implementation of a symbolic algebra system he developed.</p>

 <p>Memoizing functions also has a long history.  In 1967, Donald Michie
 proposed using memoized functions to improve the performance of machine
 learning.  Rote learning was improved by a learning function not forgetting
 what it had previously learned; this information was stored as memoized
 function values.</p>

 <p>The use of hash consing has appeared many times.  For instance, Henry Baker
 used hash consing to improve the performance of the well-known Boyer rewriting
 benchmark.  Baker used both hash consing and function memoization to improve
 the speed of the Takeuchi function, exactly in the spirit of our
 implementation, but without the automated, system-wide integration we report
 here.</p>

 <p>The ACL2 implementation permits memoization of user-defined functions.
 During execution a user may enable or disable function memoization on an
 individual function basis, may clear memoization tables, and may even keep a
 stack of memoization tables.  This facility takes advantage of our
 implementation where we keep one copy of each distinct ACL2 data object.  Due
 to the functional nature of ACL2, it is sufficient to have at most one copy of
 any data structure; thus, a user may arrange to keep data canonicalized.  This
 implementation extends to the entire ACL2 system the benefits enjoyed by BDDs:
 canonicalization, memoization, and fast equality check.</p>

 <p>We have defined various algorithms using these features, and we have
 observed, in some cases, substantial performance increases.  For instance, we
 have implemented unordered set intersection and union operations that operate
 in time roughly linear in the size of the sets.  Without using arrays, we
 defined a canonical representation for Boolean functions using ACL2 objects.
 We have investigated the performance of rewriting and tree consensus
 algorithms to good effect, and we believe function memoization offers
 interesting opportunities to simplify algorithm definition while
 simultaneously providing performance improvements.</p>

 <p>We recommend that users focus at first on the logical definitions of @(tsee
 hons) and other primitives rather than their underlying Common Lisp
 implementations.  Integrated with this memoization system is a performance
 monitoring system, which can provide real-time feedback on the operation and
 usefulness of @(tsee hons) and function memoization.  For a more detailed
 description of these tools, please see the ACL2 2006 workshop paper mentioned
 above.</p>

 <p>The Fibonacci function is a small example that demonstrates the utility of
 function memoization.  The following definition exhibits a runtime that is
 exponential in its input argument.</p>

 @({
  (defun fib (x)
    (declare (xargs :guard (natp x)))
    (mbe
     :logic
     (cond ((zp x) 0)
           ((= x 1) 1)
           (t (+ (fib (- x 1)) (fib (- x 2)))))
     :exec
     (if (< x 2)
         x
       (+ (fib (- x 1)) (fib (- x 2))))))
 })

 <p>Below we show how the ACL2 @(tsee time$) utility can measure the time to
 execute a call to the @('fib') function (with some editing to avoid noise from
 the underlying Common Lisp implementation).  @(tsee Memoize) is actually an
 ACL2 macro that expands to a call of the ACL2 function used to identify a
 function for memoization; see @(see memoize).  This function also accepts a
 well-formed term that must be true in order for the system to memoize a call
 of the memoized function; to ensure that an instance of the term is safe for
 evaluation in Common Lisp, a check is performed that if the @(see guard) of
 the memoized function is satisfied, then this instance will execute without
 error.</p>

 @({
  ACL2 !>(time$ (fib 40))
  ; (EV-REC *RETURN-LAST-ARG3* ...) took
  ; 0.99 seconds realtime, 0.98 seconds runtime
  ; (1,296 bytes allocated).
  102334155
  ACL2 !>(memoize 'fib)

  Summary
  Form:  ( TABLE MEMOIZE-TABLE ...)
  Rules: NIL
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)

  Summary
  Form:  ( PROGN (TABLE MEMOIZE-TABLE ...) ...)
  Rules: NIL
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
   FIB
  ACL2 !>(time$ (fib 40))
  ; (EV-REC *RETURN-LAST-ARG3* ...) took
  ; 0.00 seconds realtime, 0.00 seconds runtime
  ; (2,864 bytes allocated).
  102334155
  ACL2 !>(time$ (fib 100))
  ; (EV-REC *RETURN-LAST-ARG3* ...) took
  ; 0.00 seconds realtime, 0.00 seconds runtime
  ; (7,024 bytes allocated).
  354224848179261915075
  ACL2 !>(unmemoize 'fib)
 })

 <p>We see that once the function @('fib') is identified as a function for
 which function calls should be memoized, the execution times are substantially
 reduced.  Finally, we can prevent @('fib') from being further memoized; in
 fact, @(tsee unmemoize) erases the previously memoized values.</p>

 <p>The implementation of hash consing, memoization, and applicative hash
 tables involves several facets: canonical representation of ACL2 data,
 function memoization, and the use of Lisp hash tables to improve the
 performance of association list operations.  We discuss each of these in turn,
 and we mention some subtle interrelationships.  Although it is not necessary
 to understand the discussion in this section, it may permit some users to
 better use this implementation.  This discussion may be confusing for some
 ACL2 users as it makes references to Lisp implementation features.</p>

 <p>The ACL2 system is actually implemented as a Lisp program that is layered
 on top of a Common Lisp system implementation.  ACL2 data constants are
 implemented with their corresponding counterparts in Common Lisp; that is,
 ACL2 cons pairs, strings, characters, numbers, and symbols are implemented
 with their specific Common Lisp counterparts.  This choice permits a number of
 ACL2 primitive functions to be implemented with their corresponding Common
 Lisp functions, but there are indeed differences.  ACL2 is a logic, and as
 such, it does not specify anything to do with physical storage or execution
 performance.  When ACL2 is used, the knowledgeable user can write functions to
 facilitate the reuse of some previously computed values.</p>

 <p>Recall the three mechanisms under discussion: hash consing, function
 memoization, and fast association list operations.  The function memoization
 mechanism takes advantage of the canonical representation of data objects
 provided by the @(tsee hons) operation as does the fast association list
 operation mechanism.  Each time @('hons') is invoked, its arguments are
 themselves converted, if necessary, to uniquely represented objects.</p>

 <p>The ACL2 universe is recursively closed under the @('cons') pairing
 operation and the atoms.  Hash consing (@(tsee hons)) is logically identical
 to @('cons'), but a set of tables is used to record each @('hons') pair.  When
 a @('hons') pair is requested, the implementation checks, in the current set
 of tables, whether the requested pair already exists.  If not, a new pair is
 created and a record of that pair is made; otherwise, a reference to the
 previously created pair is returned.  Thus, any data object created with
 @('hons') has a unique representation, as does every subcomponent.  We also
 arrange for strings to have a unique representation &mdash; only one copy of
 each different string is kept &mdash; and when any previously unseen string is
 an argument to @('hons'), we add the string to a unique table of strings.  A
 system-wide benefit of having a canonical representation for data is that
 equality comparisons between any two data objects can be done in constant
 time.</p>

 <p>The definition of @(tsee hons) in no way changes the operation of @('cons')
 &mdash; @('hons') creates a @('cons') pair.  When asked to create a @('hons'),
 the implementation checks to see if there is a @('cons') with the same @(tsee
 car) and @(tsee cdr) as the @('hons') being requested.  Thus, the only
 difference between the results of a @('hons') call and a corresponding
 @('cons') call is a notation in some invisible (to the ACL2 logic) tables
 where we record which @('cons') elements are also @('hons') elements.  Since a
 @('hons') is nothing but a @('cons'), the operation of @('car') and @('cdr')
 is unchanged.  In fact, the implementation is designed so that at any time it
 is safe to clear the table identifying which @('cons') elements are also
 considered @('hons') elements.</p>

 <p>User-defined functions with defined and verified guards can be memoized.
 When a function is memoized, a user-supplied condition restricts the domain
 when memoization is attempted.  When the condition is satisfied, memoization
 is attempted (assuming that memoization for the function is presently
 enabled); otherwise, the function is just evaluated.  Each memoized function
 has a hash table that is used to keep track of a unique list of function
 arguments paired with their values.  If appropriate, for each function the
 corresponding table is checked to see if a previous call with exactly the same
 arguments already exists in the table: if so, then the associated value is
 returned; if not, then the function is evaluated and a new key-value pair is
 added to the table of memoized values so that some future call will benefit
 from the memoization.  With ACL2 user functions memoization can be dynamically
 enabled and disabled.  There is an ACL2 function that clears a specific
 memoization table.  And finally, just as with the @('hons') table, a stack of
 these function memoization tables is maintained; that is, it is possible to
 memoize a function, use it a bit, set the memoized values aside, start a new
 table, use it, and then return to the original table.</p>

 <p>We next discuss the fast lookup operation for association lists.  When a
 pair is added to an association list using the functions @(tsee hons-acons) or
 @(tsee hons-acons!), the system also records the key-value pair in an
 associated hash table.  As long as a user only used these two functions when
 placing key-value pairs on an association list, the key-value pairs in the
 corresponding hash table will be synchronized with the key-value pairs in the
 association list.  Later, if @(tsee hons-get) is used to look up a key, then
 instead of performing a linear search of the association list we consult the
 associated hash table.  If a user does not strictly follow this discipline,
 then a linear search may be required.  In some sense, these association lists
 are much like ACL2 arrays, but without the burden of explicitly naming the
 arrays.  The ACL2 array @(tsee compress1) function is analogous to the
 functions @(tsee fast-alist-clean) and @(tsee fast-alist-clean!).  There are
 user-level ACL2 functions that allow the associated hash tables to be cleared
 and removed.</p>

 <p>As mentioned above, the @(see hons-enabled) features are optimized for CCL
 and GCL.  See @(see ccl-updates) for easy instructions for obtaining the
 latest version of CCL.</p>

 <p>REFERENCES</p>

 <p>Baker, Henry G., The Boyer Benchmark at Warp Speed. ACM Lisp Pointers V,3
 (Jul-Sep 1992), pages 13-14.</p>

 <p>Baker, Henry G., A Tachy 'TAK'.  ACM Lisp Pointers Volume 3,
 July-September, 1992, pages 22-23.</p>

 <p>Robert S. Boyer and Warren A. Hunt, Jr., Function Memoization and Unique
 Object Representation for ACL2 Functions, in the Sixth International Workshop
 on the ACL2 Theorem Prover and Its Applications, ACM Digital Library,
 2006.</p>

 <p>L.P. Deutsch. An Interactive Program Verifier. Tech. Rept. CSL-73-1, Xerox
 Palo Alto Research Center, May, 1973.</p>

 <p>A. P. Ershov.  On Programming of Arithmetic Operations.  In the
 Communications of the ACM, Volume 118, Number 3, August, 1958, pages
 427-430.</p>

 <p>Eiichi Goto, Monocopy and Associative Algorithms in Extended Lisp,
 TR-74-03, University of Tokyo, 1974.</p>

 <p>Richard P. Gabriel.  Performance and Evaluation of Lisp Systems.  MIT
 Press, 1985.</p>

 <p>Donald Michie.  Memo functions: a Language Feature with Rote Learning
 Properties.  Technical Report MIP-R-29, Department of Artificial Intelligence,
 University of Edinburgh, Scotland, 1967.</p>

 <p>Donald Michie.  Memo Functions and Machine Learning.  In Nature, Volume
 218, 1968, pages 19-22.</p>")

(defxdoc hons-assoc-equal
  :parents (fast-alists acl2-built-ins)
  :short "@('(hons-assoc-equal key alist)') is <b>not fast</b>; it serves as
the logical definition for @(tsee hons-get)."
  :long "<p>The definition of @('hons-assoc-equal') is similar to that of
 @(tsee assoc-equal), except that (1) it does not require @(tsee alistp) as a
 guard, and (2) it \"skips over\" any non-conses when its alist argument is
 malformed.</p>

 <p>We typically leave @('hons-get') enabled and reason about
 @('hons-assoc-equal') instead.  One benefit of this approach is that it avoids
 certain \"false\" discipline warnings that might arise from execution during
 theorem proving.</p>

 @(def hons-assoc-equal)")

(defxdoc hons-clear
  :parents (hons acl2-built-ins)
  :short "@('(hons-clear gc)') is a drastic garbage collection mechanism that
clears out the underlying Hons Space."
  :long "<p>Logically, @('hons-clear') just returns nil; we leave it enabled
 and would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, @('hons-clear') brutally (1) clears all the tables that
 govern which conses are @(see normed), then (2) optionally garbage collects,
 per the @('gc') argument, then finally (3) re-norms the keys of @(tsee
 fast-alists) and persistently normed conses; see @(see
 hons-copy-persistent).</p>

 <p>Notes.</p>

 <ul>

 <li>The hash tables making up the Hons Space retain their sizes after being
 cleared.  If you want to shrink them, see @(tsee hons-resize).</li>

 <li>CCL and GCL users might prefer @(tsee hons-wash), which is relatively
 efficient and allows for the garbage collection of normed conses without
 impacting their normed status.</li>

 <li>It is not recommended to interrupt this function.  Doing so may cause
 persistently normed conses and fast alist keys to become un-normed, which
 might lead to less efficient re-norming and/or violations of the fast-alist
 discipline.</li>

 <li>(For ACL2(p) users only; see @(see parallelism)) If parallel execution is
 enabled (see (@see set-parallel-execution)), as it is by default in ACL2(p),
 then @('hons-clear') may be a no-op (other than to print a warning), in order
 to avoid thread-unsafe behavior.  (However, In CCL you are unlikely to see
 this restriction unless you are running more than one thread.)  To get around
 this restriction, you can instead use @(tsee hons-clear!), which however
 requires a @(see trust-tag).</li>

 </ul>

 @(def hons-clear)")

(defxdoc hons-clear!
  :parents (hons acl2-built-ins)
  :short "A version of @(tsee hons-clear) for @(see parallel) execution"
  :long "<p>This function is only of interest to ACL2(p) users; see @(see
 parallelism), because for ACL2 it suffices to use @(tsee hons-clear).
 However, if parallel execution is enabled (see (@see set-parallel-execution)),
 as it is by default in ACL2(p), then @('hons-clear') may be a no-op (other
 than to print a warning), in order to avoid thread-unsafe behavior.  If you
 are not concerned about thread safety, for example when you want to call
 @('hons-clear') directly in the top-level loop, you can use @('hons-clear!'),
 which does not check for parallelism violations.  However, @('hons-clear!')
 requires a trust tag; see @(see defttag).</p>")

(defxdoc hons-copy
  :parents (hons acl2-built-ins)
  :short "@('(hons-copy x)') returns a @(see normed) object that is equal to
  X."
  :long "<p>In the logic, @('hons-copy') is just the identity function; we
 leave it enabled and would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, @('hons-copy') does whatever is necessary to produce a
 @(see normed) version of X.</p>

 <p>What might this involve?</p>

 <p>If X is a symbol, character, or number, then it is already normed and
 nothing is done.</p>

 <p>If X is a string, we check if any normed version of X already exists.  If
 so, we return the already-normed version; otherwise, we install X as the
 normed version for all strings that are @(tsee equal) to X.</p>

 <p>If X is a cons, we must determine if there is a normed version of X, or
 recursively construct and install one.  Norming large cons trees can become
 expensive, but there are a couple of cheap cases.  In particular, if X is
 already normed, or if large subtrees of X are already normed, then not much
 needs to be done.  The slowest case is norming some large ACL2 cons structure
 that has no subtrees which are already normed.</p>

 <p>Note that running @('hons-copy') on an object that was created with @(tsee
 cons) is often slower than just using @(tsee hons) directly when constructing
 the object.</p>

 @(def hons-copy)")

(defxdoc hons-copy-persistent
  :parents (hons acl2-built-ins)
  :short "@('(hons-copy-persistent x)') returns a @(see normed) object that is
equal to X and which will be re-normed after any calls to @(tsee hons-clear)."
  :long "<p>Logically @('hons-copy-persistent') is the identity; we leave it
 enabled and would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, @('hons-copy-persistent') is virtually identical to @(tsee
 hons-copy).</p>

 <p>The only difference is that when @(tsee hons-clear) is used, any
 persistently normed conses are automatically re-normed, and this re-norming
 can be carried out more efficiently than, say, an ordinary @(tsee
 hons-copy).</p>

 @(def hons-copy-persistent)")

(defxdoc hons-enabled
  :parents (hons-and-memoization)
  :short "Hash cons, function memoization, and applicative hash tables"
  :long "<p>ACL2 supports hash cons, function memoization, and applicative hash
 tables; see @(see hons-and-memoization).  These are sometimes called the
 ``hons-enabled features'' of ACL2.</p>")

(defxdoc hons-equal
  :parents (hons equal acl2-built-ins)
  :short "@('(hons-equal x y)') is a recursive equality check that optimizes
when parts of its arguments are @(see normed)."
  :long "<p>In the logic, @('hons-equal') is just @(tsee equal); we leave it
 enabled and would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, when @('hons-equal') encounters two arguments that are both
 normed, it becomes a mere @(tsee eql) check, and hence avoids the overhead of
 recursively checking large cons structures for equality.</p>

 <p>Note.  If @('hons-equal') is given arguments that do not contain many
 normed objects, it can actually be much slower than @(tsee equal)!  This is
 because it checks to see whether its arguments are normed at each recursive
 step, and so you are repeatedly paying the price of such checks.  Also see
 @(see hons-equal-lite), which only checks at the top level whether its
 arguments are normed.</p>

 @(def hons-equal)")

(defxdoc hons-equal-lite
  :parents (hons hons-equal)
  :short "@('(hons-equal-lite x y)') is a non-recursive equality check that
optimizes if its arguments are @(see normed)."
  :long "<p>In the logic, @('hons-equal-lite') is just @(tsee equal); we leave
 it enabled and would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, @('hons-equal-lite') checks whether its arguments are
 normed, and if so it effectively becomes a @(tsee eql) check.  Otherwise, it
 immediately calls @(tsee equal) to determine if its arguments are equal.</p>

 <p>The idea here is to strike a useful balance between @('equal') and @(tsee
 hons-equal).  If both arguments happen to be normed, we get to use a very fast
 equality comparison.  Otherwise, we just get out of the way and let @('equal')
 do its work, without the extra overhead of recursively checking whether the
 subtrees of x and y are normed.</p>

 @(def hons-equal-lite)")

(defxdoc hons-get
  :parents (fast-alists acl2-built-ins)
  :short "@('(hons-get key alist)') is the efficient lookup operation for @(see
fast-alists)."
  :long "<p>Logically, @('hons-get') is just an alias for @(tsee
 hons-assoc-equal); we typically leave it enabled and prefer to reason about
 @('hons-assoc-equal') instead.  One benefit of this approach is that it helps
 to avoids \"false\" discipline warnings that might arise from execution during
 theorem proving.</p>

 <p>Under the hood, when @('alist') is a fast alist that is associated with a
 valid hash table, @('hons-get') first norms @('key') using @(tsee hons-copy),
 then becomes a @('gethash') operation on the hidden hash table.</p>

 @(def hons-get)")

(defxdoc hons-note
  :parents (hons)
  :short "Notes about @(see HONS), especially pertaining to expensive resizing
 operations"
  :long "<p>Certain ``Hons-Notes'' are printed to the terminal to report
 implementation-level information about the management of @(see HONS)
 structures.  Some of these may be low-level and of interest mainly to system
 developers.  But below we discuss what users can learn from a particular
 hons-note, ``ADDR-LIMIT reached''.  In short: If you are seeing a lot of such
 hons-notes, then you may be using a lot of memory.  (Maybe you can reduce that
 memory; for certain BDD operations, for example (as defined in community books
 @('books/centaur/ubdds/')), variable ordering can make a big difference.)</p>

 <p>By way of background:</p>

 <blockquote><p>The ADDR-HT is the main hash table that lets us look up @(see
 normed) conses, i.e., @(see hons)es.  It is an ordinary Common Lisp hash
 table, so when it starts to get too full the Lisp will grow it.  It can get
 really big.  (It has been seen to take more than 10 GB of memory just for the
 hash table's array, not to mention the actual conses!)</p>

 <p>Hons-Notes may be printed when the ADDR-HT is getting really full.  This
 growth can be expensive and can lead to memory problems.  Think about what it
 takes to resize a hash table:</p>

 <p>(1) allocate a new, bigger array<br></br>

   (2) rehash elements, copying them into the new array<br></br>

   (3) free the old array</p>

 <p>Until you reach step (3) and a garbage collection takes place, you have to
 have enough memory to have both the old and new arrays allocated.  If the old
 array was 10 GB and we want to allocate a new one that's 15 GB, this can get
 pretty bad.  Also, rehashing the elements is expensive time-wise when there
 are lots of elements.</p>

 <p>Since resizing a hash table is expensive, we want to avoid it.  There's a
 @(tsee hons-resize) command for this.  You may want your books to start with
 something like the following.</p>

 @({
    (value-triple (set-max-mem (* 30 (expt 2 30))))      ; 30 GB heap
    (value-triple (hons-resize :addr-ht #u_100_000_000)) ; 100M honses
 })

 <p>Basically, if you roughly know how many honses your book will need, you can
 just get them up front and then never to resize.</p></blockquote>

 <p>The Hons-Notes about ``ADDR-LIMIT reached'' are basically there to warn you
 that the ADDR-HT is being resized.  This can help you realize that your @(tsee
 hons-resize) command had too small of an ADDR-HT size, or might suggest that
 your book should have a @(tsee hons-resize) command.  There are also commands
 like @('(')@(tsee hons-summary)@(')'), @(see set-max-mem), and defined in
 community book @('books/centaur/misc/memory-mgmt-logic.lisp'),
 @('(hons-analyze-memory nil)').  These can show you how many honses you
 currently have, how much space they are taking, and that sort of thing.  (A
 nice trick is to call @(tsee hons-summary) at the end of a book, to get an
 idea of how many honses you should ask for in your @(tsee hons-resize)
 command).</p>")

(defxdoc hons-resize
  :parents (hons acl2-built-ins)
  :short "@('(hons-resize ...)') can be used to manually adjust the sizes of
the hash tables that govern which ACL2 Objects are considered @(see normed)."
  :long "<p>General form:</p>

 @({
   (hons-resize [:str-ht size]
                [:nil-ht size]
                [:cdr-ht size]
                [:cdr-ht-eql size]
                [:addr-ht size]
                [:other-ht size]
                [:sbits size]
                [:fal-ht size]
                [:persist-ht size])
 })

 <p>Example:</p>

 @({
   (hons-resize :str-ht 100000
                :addr-ht (expt 2 27))
 })

 <p>Logically, @('hons-resize') just returns nil; we leave it enabled and would
 think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, @('hons-resize') can be used to change the sizes of certain
 hash tables in the Hons Space.</p>

 <p>All arguments are optional.  The size given to each argument should either
 be nil (the default) or a natural number.  A natural number indicates the
 newly desired size for the hash table, whereas nil means \"don't resize this
 table.\" Any non-natural argument is regarded as nil.</p>

 <p>You may wish to call this function for two reasons.</p>

 <p>1.  Improving Performance by Resizing Up</p>

 <p>Since the hash tables in the Hons Space automatically grow as new objects
 are normed, @('hons-resize') is unnecessary.  But automatic growth can be slow
 because it is incremental: a particular hash table might be grown dozens of
 times over the course of your application.  Using @('hons-resize') to pick a
 more appropriate initial size may help to reduce this overhead.</p>

 <p>2.  Reducing Memory Usage by Resizing Down</p>

 <p>Resizing can also be used to shrink the hash tables.  This might possibly
 be useful immediately after a @(tsee hons-clear) to free up memory taken by
 the hash tables themselves.  (Of course, the tables will grow again as you
 create new normed objects.)</p>

 <p>Advice for using @('hons-resize').</p>

 <p>Note that hash tables that are already close to the desired size, or which
 have too many elements to fit into the desired size, will not actually be
 resized.  This makes resizing relatively \"safe.\"</p>

 <p>Note that the @(tsee hons-summary) function can be used to see how large
 and how full your hash tables are.  This may be useful in deciding what sizes
 you want to give to @('hons-resize').</p>

 <p>Note that @('hons-resize') operates by (1) allocating new hash tables, then
 (2) copying everything from the old hash table into the new table.  Because of
 this, for best performance you should ideally call it when the hash tables
 involved are minimally populated, i.e., at the start of your application, or
 soon after a @(tsee hons-clear).</p>")

(defxdoc hons-shrink-alist
  :parents (fast-alist-fork acl2-built-ins)
  :short "Deprecated feature"
  :long "<p>Deprecated.  Alias for @(tsee fast-alist-fork).</p>")

(defxdoc hons-shrink-alist!
  :parents (fast-alist-fork! acl2-built-ins)
  :short "Deprecated feature"
  :long "<p>Deprecated.  Alias for @(tsee fast-alist-fork!).</p>")

(defxdoc hons-summary
  :parents (hons acl2-built-ins)
  :short "@('(hons-summary)') prints basic information about the sizes of the
tables in the current Hons Space."
  :long "<p>Logically, @('hons-summary') just returns nil; we leave it enabled
 and would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, this function gathers and prints some basic information
 about the sizes of the tables in the Hons Space.</p>

 <p>This information may be useful for deciding if you want to garbage collect
 using functions such as @(tsee hons-clear) or @(tsee hons-wash).  It may also
 be useful for determining good initial sizes for the Hons Space hash tables
 for your particular computation; see @(see hons-resize).  For information
 about @(see fast-alists), see @(see fast-alist-summary).</p>

 @(def hons-summary)")

(defxdoc hons-wash
  :parents (hons acl2-built-ins)
  :short "@('(hons-wash)') is like @(tsee gc$) but can also garbage collect
@(see normed) objects (CCL and GCL Only)."
  :long "<p>Logically, @('hons-wash') just returns nil; we leave it enabled and
 would think it odd to ever prove a theorem about it.</p>

 <p>Under the hood, in CCL and GCL, @('hons-wash') runs a garbage collection
 after taking special measures to allow normed conses to be collected.  In
 Lisps other than CCL, @('hons-wash') does nothing.  This is because the
 efficient implementation of @('hons-wash') is specific to the \"static
 honsing\" scheme which requires CCL-specific features.</p>

 <p>Why is this function needed?  Ordinarily, it is not possible to garbage
 collect any normed conses.  This is because the Hons Space includes pointers
 to any normed conses, and hence Lisp's garbage collector thinks these objects
 are live.  To correct for this, @('hons-wash') (1) clears out these pointers,
 (2) runs a garbage collection, then (3) re-norms any previously-normed conses
 which have survived the garbage collection.</p>

 <p>Notes.</p>

 <ul>

 <li>It is not recommended to interrupt this function.  Doing so may cause
 persistently normed conses and fast alist keys to become un-normed, which
 might lead to less efficient re-norming and/or violations of the fast-alist
 discipline.</li>

 <li>(For ACL2(p) users only; see @(see parallelism)) If parallel execution is
 enabled (see (@see set-parallel-execution)), as it is by default in ACL2(p),
 then @('hons-wash') may be a no-op (other than to print a warning), in order
 to avoid thread-unsafe behavior.  (However, In CCL you are unlikely to see
 this restriction unless you are running more than one thread.)  To get around
 this restriction, you can instead use @(tsee hons-wash!), which however
 requires a @(see trust-tag).</li>

 </ul>

 @(def hons-wash)")

(defxdoc hons-wash!
  :parents (hons acl2-built-ins)
  :short "A version of @(tsee hons-wash) for @(see parallel) execution"
  :long "<p>This function is only of interest to ACL2(p) users; see @(see
 parallelism), because for ACL2 it suffices to use @(tsee hons-wash).  However,
 if parallel execution is enabled (see (@see set-parallel-execution)), as it is
 by default in ACL2(p), then @('hons-wash') may be a no-op (other than to print
 a warning), in order to avoid thread-unsafe behavior.  If you are not
 concerned about thread safety, for example when you want to call
 @('hons-wash') directly in the top-level loop, you can use @('hons-wash!'),
 which does not check for parallelism violations.  However, @('hons-wash!')
 requires a trust tag; see @(see defttag).</p>")

(defxdoc |Hey Wait!  Is ACL2 Typed or Untyped(Q)|
  :parents (|Pages Written Especially for the Tours|)
  :short "Hey Wait!  Is ACL2 Typed or Untyped?"
  :long "<p>The example</p>

 <code>
 ACL2 !&gt;<b>(app 7 27)</b>

 ACL2 Error in TOP-LEVEL:  The guard for the function symbol ENDP, which
 is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the
 call (ENDP 7).
 </code>

 <p>illustrates the fact that while ACL2 is an untyped language the ACL2
 evaluator can be configured so as to check ``types'' at runtime.  We should
 not say ``types'' here but ``guards.''  See @(see |Guards in ACL2|) for a
 discussion of guards.</p>

 <p>The guard on @(tsee endp) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 requires its argument to be a true list.  Since 7 is not a true list, and
 since ACL2 is checking guards in this example, an error is signaled by ACL2.
 How do you know ACL2 is checking guards?  Because the prompt tells us (click
 <see topic='@(url |About the Prompt|)'>here</see>) with its ``!''.</p>")

(defxdoc |How Long Does It Take to Become an Effective User(Q)|
  :parents (|Pages Written Especially for the Tours|)
  :short "How Long Does It Take to Become an Effective User?"
  :long "<p><see topic='@(url |Other Requirements|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>We expect that a talented undergraduate majoring in computer science (or
 perhaps mathematics) will probably take several weeks to become an effective
 ACL2 user.  The time will depend, of course, on that student's familiarity
 with logic (or formal methods) and Lisp programming, as well as willingness to
 read and study the ACL2 User's Manual.</p>

 <p>Of course, it is critical to do some projects in order to gain proficiency.
 (Hence access to an ACL2 implementation is also a requirement, for example by
 downloading and installing following links from the ACL2 home page.)  But it
 is critical to start with ``toy'' projects before tackling a ``grand
 challenge.''</p>

 <p><see topic='@(url |Other Requirements|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |How To Find Out about ACL2 Functions|
  :parents (|Pages Written Especially for the Tours|)
  :short "How To Find Out about ACL2 Functions"
  :long "<p><see topic='@(url
 |How To Find Out about ACL2 Functions (cont)|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>Most ACL2 primitives are documented.  Here is the definition of @('app')
 again, with the documented topics highlighted.  <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 All of the links below lead into the ACL2 User's Manual.  So follow these
 links if you wish, but use your <b>Back Button</b> to return here!</p>

 <code>
 (@(see defun) app (x y)
   (@(see cond) ((@(see endp) x) y)
         (t (@(see cons) (@(see car) x)
                  (app (@(see cdr) x) y)))))
 </code>

 <p>By following the link on @(see endp) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> we
 see that it is a Common Lisp function and is defined to be the same as @(see
 atom) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>, which recognizes non-conses.  But @('endp') has a
 guard.  Since we are ignoring guards for now, we'll ignore the guard issue on
 @('endp').</p>

 <p>So this definition reads ``to @('app') @('x') and @('y'): if @('x') is an
 atom, return @('y'); otherwise, @('app') @('(cdr x)') and @('y') and then cons
 @('(car x)') onto that.''</p>

 <p><see topic='@(url |How To Find Out about ACL2 Functions (cont)|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |How To Find Out about ACL2 Functions (cont)|
  :parents (|Pages Written Especially for the Tours|)
  :short "How To Find Out about ACL2 Functions (cont)"
  :long "<p><see topic='@(url |The Admission of App|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>You can always use the Index <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 icon below to find the documentation of functions.  Try it.  Click on the
 Index icon below.  Then use the Find command of your browser to find ``endp''
 in that document and follow the link.  But remember to come back here.</p>

 <p>The ACL2 documentation is also available in Emacs, via the ACL2-Doc
 browser (see @(see ACL2-Doc)) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>,
 allowing you to explore the hyperlinked documentation in the comfort of a text
 editor that can also interact with ACL2.</p>

 <p>In addition, runtime images of ACL2 have the hyperlinked text as a large
 ACL2 data structure that can be explored with ACL2's <b>:doc</b> command.  If
 you have ACL2 running, try the command <b>:doc endp</b>.</p>

 <p>Another way to find out about ACL2 functions, if you have an ACL2 image
 available, is to use the command :@(tsee args) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 which prints the formals, type, and guard of a function symbol.</p>

 <p>Of course, the ACL2 documentation can also be printed out as a very long
 book but we do not recommend that!  See the ACL2 Home Page to download the
 Postscript.</p>

 <p>Now let's continue with @('app').</p>

 <p><see topic='@(url |The Admission of App|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc i-am-here
  :parents (ld)
  :short "A convenient marker for use with @(tsee rebuild) or @(tsee ld)"
  :long "@({
  Example Input File for Rebuild:
  (defun fn1 (x y) ...)
  (defthm lemma1 ...)
  (defthm lemma2 ...)
  (i-am-here)
  The following lemma won't go through.  I started
  typing the hint but realized I need to prove a
  lemma first.  See the failed proof attempt in foo.bar.
  I'm going to quit for the night now and resume tomorrow
  from home.

  (defthm lemma3 ...
    :hints ((\"Goal\" :use (:instance ???
  ...
 })

 <p>By putting an @('(i-am-here)') form at the ``frontier'' of an evolving file
 of @(see command)s, you can use @(tsee rebuild) to load the file up to the
 @('(i-am-here)').  @('I-am-here') simply returns an @(see error-triple) that
 indicates an error, and any form that ``causes an error'' will do the same
 job.  Note that the text of the file after the @('(i-am-here)') need not be
 machine readable.</p>")

(defxdoc i-close
  :parents (real)
  :short "ACL2(r) test for whether two numbers are infinitesimally close"
  :long "<p>@('(I-close x y)') is true if and only if @('x-y') is an
 infinitesimal number.  This predicate is only defined in ACL2(r) (see @(see
 real)).</p>")

(defxdoc i-large
  :parents (real)
  :short "ACL2(r) recognizer for infinitely large numbers"
  :long "<p>@('(I-large x)') is true if and only if @('x') is non-zero and
 @('1/x') is an infinitesimal number.  This predicate is only defined in
 ACL2(r)
 (see @(see real)).</p>")

(defxdoc i-limited
  :parents (real)
  :short "ACL2(r) recognizer for limited numbers"
  :long "<p>@('(I-limited x)') is true if and only if @('x') is a number that
 is not infinitely large.  This predicate is only defined in ACL2(r)
 (see @(see real)).</p>")

(defxdoc i-small
  :parents (real)
  :short "ACL2(r) recognizer for infinitesimal numbers"
  :long "<p>@('(I-small x)') is true if and only if @('x') is an infinitesimal
 number (possibly 0).  This predicate is only defined in ACL2(r)
 (see @(see real)).</p>")

(defxdoc identity
  :parents (basics acl2-built-ins)
  :short "The identity function"
  :long "<p>@('(Identity x)') equals @('x'); what else can we say?</p>

 <p>@('Identity') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def identity)")

(defxdoc if
  :parents (basics acl2-built-ins)
  :short "If-then-else function"
  :long "<p>@('(if x y z)') is equal to @('y') if @('x') is any value other
 than @('nil'), and is equal to @('z') if @('x') is @('nil').</p>

 <p>Only one of @('y'), @('z') is evaluated when @('(if x y z)') is
 evaluated.</p>

 <p>@('If') has a @(see guard) of @('t').</p>

 <p>@('If') is part of Common Lisp.  See any Common Lisp documentation for more
 information.</p>")

(defxdoc if*
  :parents (bdd)
  :short "For conditional rewriting with BDDs"

  :long "<p>The function @('IF*') is defined to be @(tsee IF), but it is used
 in a special way by ACL2's @(see BDD) package.</p>

 @(def if*)

 <p>As explained elsewhere (see @(see bdd-algorithm)), ACL2's @(see BDD)
 algorithm gives special treatment to @(see term)s of the form @('(IF* TEST TBR
 FBR)').  In such cases, the algorithm simplifies @('TEST') first, and the
 result of that simplification must be a constant (normally @('t') or @('nil'),
 but any non-@('nil') explicit value is treated like @('t') here).  Otherwise,
 the algorithm aborts.</p>

 <p>Thus, @('IF*') may be used to implement a sort of conditional rewriting for
 ACL2's @(see BDD) package, even though this package only nominally supports
 unconditional rewriting.  The following contrived example should make this
 point clear.</p>

 <p>Suppose that we want to prove that @('(nthcdr (length x) (append x y))') is
 equal to @('y'), but that we would be happy to prove this only for lists
 having length 4.  We can state such a theorem as follows.</p>

 @({
  (let ((x (list x0 x1 x2 x3)))
    (equal (nthcdr (length x) (append x y))
           y))
 })

 <p>If we want to prove this formula with a @(':')@(tsee BDD) hint, then we
 need to have appropriate rewrite rules around.  First, note that @('LENGTH')
 is defined as follows (try @(':')@(tsee PE) @(tsee LENGTH)):</p>

 @({
  (length x)
   =
  (if (stringp x)
      (len (coerce x 'list))
      (len x))
 })

 <p>Since @(see BDD)-based rewriting is merely very simple unconditional
 rewriting (see @(see bdd-algorithm)), we expect to have to prove a rule
 reducing @(tsee STRINGP) of a @(tsee CONS):</p>

 @({
  (defthm stringp-cons
    (equal (stringp (cons x y))
           nil))
 })

 <p>Now we need a rule to compute the @('LEN') of @('X'), because the
 definition of @('LEN') is recursive and hence not used by the @(see BDD)
 package.</p>

 @({
  (defthm len-cons
    (equal (len (cons a x))
           (1+ (len x))))
 })

 <p>We imagine this rule simplifying @('(LEN (LIST X0 X1 X2 X3))') in terms of
 @('(LEN (LIST X1 X2 X3))'), and so on, and then finally @('(LEN nil)') should
 be computed by execution (see @(see bdd-algorithm)).</p>

 <p>We also need to imagine simplifying @('(APPEND X Y)'), where still @('X')
 is bound to @('(LIST X0 X1 X2 X3)').  The following two rules suffice for this
 purpose (but are needed, since @(tsee APPEND), actually @(tsee BINARY-APPEND),
 is recursive).</p>

 @({
  (defthm append-cons
    (equal (append (cons a x) y)
           (cons a (append x y))))

  (defthm append-nil
    (equal (append nil x)
           x))
 })

 <p>Finally, we imagine needing to simplify calls of @(tsee NTHCDR), where the
 first argument is a number (initially, the length of @('(LIST X0 X1 X2 X3)'),
 which is 4).  The second lemma below is the traditional way to accomplish that
 goal (when not using BDDs), by proving a conditional rewrite rule.  (The first
 lemma is only proved in order to assist in the proof of the second lemma.)</p>

 @({
  (defthm fold-constants-in-+
    (implies (and (syntaxp (quotep x))
                  (syntaxp (quotep y)))
             (equal (+ x y z)
                    (+ (+ x y) z))))

  (defthm nthcdr-add1-conditional
    (implies (not (zp (1+ n)))
             (equal (nthcdr (1+ n) x)
                    (nthcdr n (cdr x)))))
 })

 <p>The problem with this rule is that its hypothesis makes it a conditional
 @(see rewrite) rule, and conditional rewrite rules are not used by the @(see
 BDD) package.  (See @(see bdd-algorithm) for a discussion of ``BDD rules.'')
 (Note that the hypothesis cannot simply be removed; the resulting formula
 would be false for @('n = -1') and @('x = '(a)'), for example.)  We can solve
 this problem by using @('IF*'), as follows; comments follow.</p>

 @({
  (defthm nthcdr-add1
    (equal (nthcdr (+ 1 n) x)
           (if* (zp (1+ n))
                x
                (nthcdr n (cdr x)))))
 })

 <p>How is @('nthcdr-add1') applied by the @(see BDD) package?  Suppose that
 the @(see BDD) computation encounters a @(see term) of the form @('(NTHCDR (+
 1 N) X)').  Then the @(see BDD) package will apply the @(see rewrite) rule
 @('nthcdr-add1').  The first thing it will do when attempting to simplify the
 right hand side of that rule is to attempt to simplify the term @('(ZP (1+
 N))').  If @('N') is an explicit number (which is the case in the scenario we
 envision), this test will reduce (assuming the executable-counterparts of
 @(tsee ZP) and @(tsee BINARY-+) are @(see enable)d) to @('t') or to @('nil').
 In fact, the lemmas above (not including the lemma
 @('nthcdr-add1-conditional')) suffice to prove our goal:</p>

 @({
  (thm (let ((x (list x0 x1 x2 x3)))
         (equal (nthcdr (length x) (append x y))
                y))
       :hints ((\"Goal\" :bdd (:vars nil))))
 })

 <p>If we execute the following form that disables the definition and
 executable-counterpart of the function @(tsee ZP)</p>

 @({
  (in-theory (disable zp (zp)))
 })

 <p>before attempting the proof of the theorem above, we can see more clearly
 the point of using @('IF*').  In this case, the prover makes the following
 report.</p>

 @({
  ACL2 Error in ( THM ...):  Unable to resolve test of IF* for term

  (IF* (ZP (+ 1 N)) X (NTHCDR N (CDR X)))

  under the bindings

  ((X (CONS X0 (CONS X1 (CONS X2 #)))) (N '3))

  -- use SHOW-BDD to see a backtrace.
 })

 <p>If we follow the advice above, we can see rather clearly what happened.
 See @(see show-bdd).</p>

 @({
  ACL2 !>(show-bdd)

  BDD computation on Goal yielded 21 nodes.
  ------------------------------

  BDD computation was aborted on Goal, and hence there is no
  falsifying assignment that can be constructed.  Here is a backtrace
  of calls, starting with the top-level call and ending with the one
  that led to the abort.  See :DOC show-bdd.

  (LET ((X (LIST X0 X1 X2 X3)))
       (EQUAL (NTHCDR (LENGTH X) (APPEND X Y)) Y))
    alist: ((Y Y) (X3 X3) (X2 X2) (X1 X1) (X0 X0))

  (NTHCDR (LENGTH X) (APPEND X Y))
    alist: ((X (LIST X0 X1 X2 X3)) (Y Y))

  (IF* (ZP (+ 1 N)) X (NTHCDR N (CDR X)))
    alist: ((X (LIST* X0 X1 X2 X3 Y)) (N 3))
  ACL2 !>
 })

 <p>Each of these term-alist pairs led to the next, and the test of the last
 one, namely @('(ZP (+ 1 N))') where @('N') is bound to @('3'), was not
 simplified to @('t') or to @('nil').</p>

 <p>What would have happened if we had used @(tsee IF) in place of @('IF*') in
 the rule @('nthcdr-add1')?  In that case, if @('ZP') and its @(see
 executable-counterpart) were disabled then we would be put into an infinite
 loop!  For, each time a term of the form @('(NTHCDR k V)') is encountered by
 the BDD package (where k is an explicit number), it will be rewritten in terms
 of @('(NTHCDR k-1 (CDR V))').  We would prefer that if for some reason the
 term @('(ZP (+ 1 N))') cannot be decided to be @('t') or to be @('nil'), then
 the BDD computation should simply abort.</p>

 <p>Even if there were no infinite loop, this kind of use of @('IF*') is useful
 in order to provide feedback of the form shown above whenever the test of an
 @('IF') term fails to simplify to @('t') or to @('nil').</p>")

(defxdoc iff
  :parents (basics acl2-built-ins)
  :short "Logical ``if and only if''"
  :long "<p>@('Iff') is the ACL2 biconditional, ``if and only if''.  @('(iff P
 Q)') means that either @('P') and @('Q') are both false (i.e., @('nil')) or
 both true
 (i.e., not @('nil')).</p>

 @(def iff)")

(defxdoc ifix
  :parents (numbers acl2-built-ins)
  :short "Coerce to an integer"
  :long "<p>@('Ifix') simply returns any integer argument unchanged, returning
 @('0') on a non-integer argument.  Also see @(see nfix), see @(see rfix), see
 @(see realfix) and see @(see fix) for analogous functions that coerce to a
 natural number, a rational number, a real, and a number, respectively.</p>

 <p>@('Ifix') has a @(see guard) of @('t').</p>

 @(def ifix)")

(defxdoc ignored-attachment
  :parents (defattach)
  :short "Why attachments are sometimes not used"
  :long "<p>Attachments provide a way to execute constrained functions.  But in
 some cases, ACL2 will not permit such execution.  We discuss this issue
 briefly here.  For more information about attachments, see @(see
 defattach).</p>

 <p>We illustrate this issue with the following example, discussed below.</p>

 @({
    (encapsulate
     ()
     (defstub foo () t)
     (defn foo-impl-1 () t)
     (defattach foo foo-impl-1)
     (defn foo-impl-2 () nil)
     (local (defattach foo foo-impl-2))
     (defmacro mac () (foo)) ; nil in the first pass, t in the second pass
     (defun bar () (mac))    ; nil in the first pass, t in the second pass
     (defthm bar-is-nil
       (equal (bar) nil))
     )
 })

 <p>Here, a non-executable function @('foo') is introduced with no constraints,
 and is provided two contradictory implementations, @('foo-impl-1') and
 @('foo-impl-2').  A function, @('bar'), is defined using a macro, @('mac'),
 whose expansion depends on which of @('foo-impl-1') or @('foo-impl-2') is
 attached to @('foo').  If ACL2 were to allow this, then as indicated by the
 comments above, @('(bar)') would be defined to be @('nil') on the first pass
 of the @(tsee encapsulate) form, where @('foo') is attached to
 @('foo-impl-2'); but @('(bar)') would be defined to be @('t') on the second
 pass, where @('foo') is attached to @('foo-impl-1') because the second @(tsee
 defattach) call is @(tsee local).  Thus, after execution of the
 @('encapsulate') form, @('(bar)') would be provably equal to @('t') even
 though there would be a theorem, @('bar-is-nil') &mdash; proved during the
 first pass of the @('encapsulate') &mdash; saying that @('(bar)') is
 @('nil')!</p>

 <p>Fortunately, ACL2 does not permit this to happen.  The example above
 produces the following output.</p>

 @({
    ACL2 !>>(DEFUN BAR NIL (MAC))

    ACL2 Error in ( DEFUN BAR ...):  In the attempt to macroexpand the
    form (MAC), evaluation of the macro body caused the following error:

    ACL2 cannot ev the call of undefined function FOO on argument list:

    NIL

    Note that because of logical considerations, attachments (including
    FOO-IMPL-2) must not be called in this context.
 })

 <p>We see, then, the importance of disallowing evaluation using attachments
 during macroexpansion.  ACL2 is careful to avoid attachments in situations,
 like this one, where using attachments could be unsound.</p>

 <p>We conclude with an example illustrating how @(tsee make-event) can be used
 to work around the refusal of ACL2 to use attachments during macroexpansion.
 The idea is that @(tsee make-event) expansions are stored, and this avoids the
 issue of @(tsee local) attachments.  In particular, for the example below, the
 second @(tsee defattach) affects the body of @('f2') even though that @(tsee
 defattach) is @(tsee local), because the expansion of the corresponding @(tsee
 make-event) is saved during the first pass of @(tsee certify-book), when full
 admissibility checks are done.  Then even after including the book, the
 definition of @('f2') will be based on the second (@(tsee local)) @(tsee
 defattach) form below.</p>

 @({
  (in-package \"ACL2\")

  (defun body-1 (name formals body)
    (declare (ignore name))
    `(if (consp ,(car formals))
         ,body
       nil))

  (defun body-2 (name formals body)
    (declare (ignore name))
    `(if (acl2-numberp ,(car formals))
         ,body
       t))

  (defmacro defun+ (name formals body)
    `(make-event
      (if (foo) ; attachable stub
          '(defun ,name ,formals ,(body-1 name formals body))
        '(defun ,name ,formals ,(body-2 name formals body)))))

  ;;; (defun+ f1 (x y) (cons x y)) ; fails because foo has no attachment

  (defstub foo () t)
  (defn foo-true () t)
  (defn foo-false () nil)

  (defattach foo foo-true)

  (defun+ f1 (x y) (cons x y))

  (local (defattach foo foo-false))

  (defun+ f2 (x y) (cons x y))

  (assert-event (equal (f1 3 t) nil))

  (assert-event (equal (f2 3 t) (cons 3 t)))
 })")

(defxdoc illegal
  :parents (errors acl2-built-ins)
  :short "Print an error message and stop execution"
  :long "<p>@('(Illegal ctx str alist)') causes evaluation to halt with a short
 message using the ``context'' @('ctx').  An error message is first printed
 using the string @('str') and alist @('alist') that are of the same kind as
 expected by @(tsee fmt).  See @(see fmt), and see @(see prog2$) for an example
 of how to use a related function, @(tsee hard-error)
 (see @(see hard-error)).  Also see @(see er) for a macro that provides a
 unified way of signaling errors.</p>

 <p>The difference between @('illegal') and @(tsee hard-error) is that the
 former has a guard of @('nil') while the latter has a @(tsee guard) of @('t').
 Thus, you may want to use @('illegal') rather than @('hard-error') when you
 intend to do @(tsee guard) verification at some point, and you expect the
 guard to guarantee that the @('illegal') call is never executed.  See @(see
 prog2$) for an example.</p>

 <p>Technical note for raw Lisp programmers only: It is possible to cause hard
 errors to signal actual raw Lisp errors.  See @(see hard-error).</p>

 @(def illegal)")

(defxdoc imagpart
  :parents (numbers acl2-built-ins)
  :short "Imaginary part of a complex number"
  :long "<p>Completion Axiom (@('completion-of-imagpart')):</p>

 @({
  (equal (imagpart x)
         (if (acl2-numberp x)
             (imagpart x)
           0))
 })

 <p>@(see Guard) for @('(imagpart x)'):</p>

 @({
  (acl2-numberp x)
 })")

(defxdoc immediate-force-modep
  :parents (force)
  :short "When the @(see executable-counterpart) is @(see enable)d,
 @(see force)d hypotheses are attacked immediately"
  :long "<p>Also see @(see disable-immediate-force-modep) and see @(see
 enable-immediate-force-modep).</p>

 <p>This function symbol is defined simply to provide a @(see rune) which can
 be @(see enable)d and @(see disable)d.  Enabling</p>

 @({
  (:executable-counterpart immediate-force-modep)
 })

 <p>causes ACL2 to attack @(see force)d hypotheses immediately instead of
 delaying them to the next forcing round.</p>

 @({
  Example Hints
  :in-theory (disable (:executable-counterpart immediate-force-modep))
             ; delay forced hyps to forcing round
  :in-theory (enable (:executable-counterpart immediate-force-modep))
             ; split on forced hyps immediately
 })

 <p>See @(see force) for background information.  When a @(tsee force)d
 hypothesis cannot be established a record is made of that fact and the proof
 continues.  When the proof succeeds a ``forcing round'' is undertaken in which
 the system attempts to prove each of the @(see force)d hypotheses explicitly.
 However, if the @(see rune) @('(:executable-counterpart
 immediate-force-modep)') is @(see enable)d at the time the hypothesis is @(see
 force)d, then ACL2 does not delay the attempt to prove that hypothesis but
 undertakes the attempt more or less immediately.</p>")

(defxdoc implies
  :parents (basics acl2-built-ins)
  :short "Logical implication"
  :long "<p>@('Implies') is the ACL2 implication function.  @('(implies P Q)')
 means that either @('P') is false (i.e., @('nil')) or @('Q') is true (i.e.,
 not @('nil')).</p>

 @(def implies)")

(defxdoc improper-consp
  :parents (lists acl2-built-ins)
  :short "Recognizer for improper (non-null-terminated) non-empty lists"
  :long "<p>@('Improper-consp') is the function that checks whether its
 argument is a non-empty list that ends in other than @('nil').  See @(see
 proper-consp) and also see @(see true-listp).</p>

 @(def improper-consp)")

(defxdoc in-arithmetic-theory
  :parents (events)
  :short "Designate theory for some rewriting done for non-linear arithmetic"
  :long "<p>We assume familiarity with @(see theories); in particular, see
 @(see in-theory) for the normal way to set the current theory.  Here, we
 discuss an analogous event that pertains only to non-linear arithmetic
 (see @(see non-linear-arithmetic)).</p>

 @({
  Example:
  (in-arithmetic-theory '(lemma1 lemma2))

  General Form:
  (in-arithmetic-theory term)
 })

 <p>where @('term') is a term that when evaluated will produce a theory (see
 @(see theories)).  Except for the variable @(tsee world), @('term') must
 contain no free variables.  @('Term') is evaluated with the variable @(tsee
 world) bound to the current @(see world) to obtain a theory and the
 corresponding runic theory (see @(see theories)) is then used by non-linear
 arithmetic (see @(see non-linear-arithmetic)).</p>

 <p>Warning: If @('term') involves macros such as @(tsee ENABLE) and @(tsee
 DISABLE) you will probably not get what you expect!  Those macros are defined
 relative to the @(tsee CURRENT-THEORY).  But in this context you might wish
 they were defined in terms of the ``@('CURRENT-ARITHMETIC-THEORY')'' which is
 not actually a defined function.  We do not anticipate that users will
 repeatedly modify the arithmetic theory.  We expect @('term') most often to be
 a constant list of runes and so have not provided ``arithmetic theory
 manipulation functions'' analogous to @(tsee CURRENT-THEORY) and @(tsee
 ENABLE).</p>

 <p>See @(see non-linear-arithmetic).</p>")

(defxdoc in-package
  :parents (packages acl2-built-ins)
  :short "Select current package"
  :long "@({
  Example:
  (in-package \"MY-PKG\")

  General Form:
  (in-package str)
 })

 <p>where @('str') is a string that names an existing ACL2 package, i.e., one
 of the initial packages such as @('\"KEYWORD\"') or @('\"ACL2\"') or a package
 introduced with @(tsee defpkg).  For a complete list of the known packages
 created with @(tsee defpkg), evaluate</p>

 @({
  (strip-cars (known-package-alist state)).
 })

 <p>See @(see defpkg).  An ACL2 book (see @(see books)) must contain a single
 @('in-package') form, which must be the first form in that book.</p>")

(defxdoc in-tau-intervalp
  :parents (tau-system acl2-built-ins)
  :short "Boolean membership in a tau interval"
  :long "@({
  General Form:
  (in-tau-intervalp e x)
 })

 <p>Here, @('x') should be an interval (see @(tsee tau-intervalp)).  This
 function returns @('t') or @('nil') indicating whether @('e'), which is
 generally but not necessarily a number, is an element of interval @('x').  By
 that is meant that @('e') satisfies the domain predicate of the interval and
 lies between the two bounds.</p>

 <p>Suppose @('x') is an interval with the components <i>dom</i>,
 <i>lo-rel</i>, <i>lo</i>, <i>hi-rel</i> and <i>hi</i>.  Suppose @('(<?
 ')<i>rel u v</i>@(')') means @('(< ')<i>u v</i>@(')') when <i>rel</i> is true
 and @('(<= ')<i>u v</i>@(')') otherwise, with appropriate treatment of
 infinities.</p>

 <p>Then for @('e') to be in interval @('x'), it must be the case that @('e')
 satisfies the domain predicate <i>dom</i> (where where <i>dom</i>=@('nil')
 means there is no restriction on the domain) and @('(<? ')<i>lo-rel lo</i>@('
 e)') and @('(<? ')<i>hi-rel</i>@(' e ')<i>hi</i>@(')').  [Note: ``Appropriate
 treatment of infinities'' is slightly awkward if both infinities are
 represented by the same object, @('nil').  However, this is handled by
 coercing @('e') to a number <i>after</i> checking that it is in the domain.
 By this trick, ``@('<?')''  is presented with at most one ``infinity'' and it
 is always negative when in the first argument and positive when in the
 second.]</p>

 <p>Note that every element in an @('INTEGERP') interval is contained in the
 analogous @('RATIONALP') interval (i.e., the interval obtained by just
 replacing the domain @('INTEGERP') by @('RATIONALP')).  That is because every
 integer is a rational.  Similarly, every rational is an ACL2 number.</p>

 <p>Note that an interval in which the relations are weak and the bounds are
 equal rationals is the ``unit'' or ``identity'' interval containing exactly
 that rational.</p>

 <p>Note that an interval in which the relations are strong and the bounds are
 equal rationals is empty: it contains no objects.</p>

 <p>Note that the interval @('(make-tau-interval nil nil nil nil nil)') is the
 ``universal interval:'' it contains all ACL2 objects.  It contains all numbers
 because they satisfy the non-existent domain restriction and lie between
 minus infinity and plus infinity.  It contains all non-numbers because the
 interval contains @('0') and ACL2's inequalities coerce non-numbers to @('0').
 The universal interval is useful if you are defining a bounder (see @(see
 bounders)) for a function and do not wish to address a certain case: return
 the universal interval.</p>

 <p>Recall that @(tsee make-tau-interval) constructs intervals.  Using
 @('make-tau-interval') we give several self-explanatory examples of
 @('in-tau-intervalp'):</p>

 @({
  (in-tau-intervalp 3 (make-tau-interval 'INTEGERP nil 0 nil 10))           = t
  (in-tau-intervalp 3 (make-tau-interval 'RATIONALP nil 0 nil 10))          = t
  (in-tau-intervalp 3 (make-tau-interval NIL nil 0 nil 10))                 = t

  (in-tau-intervalp -3 (make-tau-interval 'INTEGERP nil 0 nil 10))          = nil
  (in-tau-intervalp 30 (make-tau-interval 'INTEGERP nil 0 nil 10))          = nil

  (in-tau-intervalp 3/5 (make-tau-interval 'INTEGERP nil 0 nil 10))         = nil
  (in-tau-intervalp 3/5 (make-tau-interval 'RATIONALP nil 0 nil 10))        = t

  (in-tau-intervalp #c(3 5) (make-tau-interval 'RATIONALP nil 0 nil 10))    = nil
  (in-tau-intervalp #c(3 5) (make-tau-interval 'ACL2-NUMBERP nil 0 nil 10)) = t

  (in-tau-intervalp 'ABC (make-tau-interval NIL nil 0 nil 10))              = t
 })")

(defxdoc in-theory
  :parents (events theories)
  :short "Designate ``current'' theory (enabling its rules)"
  :long "@({
  Example:
  (in-theory (set-difference-theories
               (universal-theory :here)
               '(flatten (:executable-counterpart flatten))))

  General Form:
  (in-theory term)
 })

 <p>where @('term') is a term that when evaluated will produce a theory (see
 @(see theories)).</p>

 <p>Except for the variable @(tsee world), @('term') must contain no free
 variables.  @('Term') is evaluated with the variable @(tsee world) bound to
 the current @(see world) to obtain a theory and the corresponding runic theory
 (see @(see theories)) is then made the current theory.  Thus, immediately
 after the @('in-theory'), a rule is @(see enable)d iff its rule name is a
 member of the runic interpretation (see @(see theories)) of some member of the
 value of @('term').  See @(see theory-functions) for a list of the commonly
 used theory manipulation functions.</p>

 <p>Note that it is often useful to surround @('in-theory') @(see events) with
 @('local'), that is, to use @('(local (in-theory ...))').  This use of @(tsee
 local) in @(tsee encapsulate) events and @(see books) will prevent the effect
 of this theory change from being exported outside the context of that
 @('encapsulate') or book.</p>

 <p>Also see @(see hints) for a discussion of the @(':in-theory') hint,
 including some explanation of the important point that an @(':in-theory') hint
 will always be evaluated relative to the current ACL2 logical @(see world),
 not relative to the theory of a previous goal.</p>

 <p>@(tsee In-theory) returns an @(see error-triple).  When the return is
 without error, the value is of the form @('(mv nil
 (:NUMBER-OF-ENABLED-RUNES k) state)') where @('k') is the length of the new
 current theory.  This value of @('k') is what is printed when an
 @('in-theory') event evaluates without error at the top level.</p>")

(defxdoc include-book
  :parents (books-reference books-tour events)
  :short "Load the @(see events) in a file"
  :long "@({
  Examples:

  ; Include using relative pathnames:
  (include-book \"my-arith\")
  (include-book \"/../../my-arith\")

  ; Include using absolute pathname:
  (include-book \"/home/smith/my-arith\")

  ; Include a community book:
  (include-book \"arithmetic/top-with-meta\" :dir :system)

  General Form:
  (include-book file :load-compiled-file action
                     :uncertified-okp t/nil/:ignore-certs  ; [default t]
                     :defaxioms-okp t/nil                  ; [default t]
                     :skip-proofs-okp t/nil                ; [default t]
                     :ttags ttags                          ; [default nil]
                     :dir directory)
 })

 <p>where @('file') is a book name.  See @(see books) for general information,
 see @(see book-name) for information about book names, and see @(see pathname)
 for information about file names.  @('Action') is one of @('t'), @('nil'),
 @(':default'), @(':warn'), or @(':comp'); these values are explained below,
 and the default is @(':default').  The three @('-okp') keyword arguments,
 which default to @('t'), determine whether errors or warnings are generated
 under certain conditions explained below; when the argument is @('t'),
 warnings are generated.  The @('dir') argument, if supplied, is a keyword that
 represents an absolute pathname for a directory (see @(see pathname)), to be
 used instead of the current book directory (see @(see cbd)) for resolving the
 given @('file') argument to an absolute pathname.  In particular, by default
 @(':dir :system') resolves @('file') using the @('books/') directory of your
 ACL2 installation, unless your ACL2 executable was built somewhere other than
 where it currently resides; please see the ``Books Directory'' below.  To
 define other keywords that can be used for @('dir'), see @(see
 add-include-book-dir).  If the book has no @(see certificate), if its
 certificate is invalid (say, because its @(see book-hash) shows that books
 have changed after their certification), or if the certificate was produced by
 a different @(see version) of ACL2, a warning is printed and the book is
 included anyway; see @(see certificate).  This can lead to serious errors,
 perhaps mitigated by the presence of a @('.port') file from an earlier
 certification; see @(see uncertified-books).  If the portcullis of the @(see
 certificate) (see @(see portcullis)) cannot be raised in the host logical
 @(see world), an error is caused and no change occurs to the logic.
 Otherwise, the non-@(tsee local) @(see events) in file are assumed.  Then the
 @(see keep) of the @(see certificate) is checked to ensure that the correct
 files were read; see @(see keep).  A warning is printed if uncertified @(see
 books) were included.  Even if no warning is printed, @('include-book') places
 a burden on you; see @(see certificate).</p>

 <p>If you use @(see guard)s, please note @('include-book') is executed as
 though @('(set-guard-checking nil)') has been evaluated; see @(see
 set-guard-checking).  If you want guards checked, please see @(see ld) and/or
 see @(see rebuild).</p>

 <p>The value of @(':load-compiled-file') controls whether a compiled file for
 the given @('file') is loaded by @('include-book').  Note that this keyword
 applies only to the given @('file'), not to any included sub-books.  In order
 to skip loading all compiled files, for the given @('file') as well as all
 included sub-books &mdash; for example, to avoid Lisp errors such as ``Wrong
 FASL version'' &mdash; use @('(set-compiler-enabled nil state)'); see @(see
 compilation).  Otherwise, if keyword argument @(':load-compiled-file') is
 missing or its value is the keyword @(':default'), then it is treated as
 @(':warn').  If its value is @('nil'), no attempt is made to load the compiled
 file for the book provided.  In order to load the compiled file, it must be
 more recent than the book's @(see certificate) (except in raw mode, where it
 must be more recent than the book itself; see @(see set-raw-mode)).  For
 non-@('nil') values of @(':load-compiled-file') that do not result in a loaded
 compiled file, ACL2 proceeds as follows.  Note that a load of a compiled file
 or expansion file aborts partway through whenever an @(tsee include-book) form
 is encountered for which no suitable compiled or expansion file can be loaded.
 For much more detail, see @(see book-compiled-file).</p>

 <blockquote>

 <p>@('t'): Cause an error if the compiled file is not loaded.  This same
 requirement is imposed on every @(tsee include-book) form evaluated during the
 course of evaluation of the present @('include-book') form, except that for
 those subsidiary @('include-book')s that do not themselves specify
 @(':load-compiled-file t'), it suffices to load the expansion file (see @(see
 book-compiled-file)).</p>

 <p>@(':warn'): An attempt is made to load the compiled file, and a warning is
 printed if that load fails to run to completion.</p>

 <p>@(':comp'): A compiled file is loaded as with value @('t'), except that if
 a suitable ``expansion file'' exists but the compiled file does not, then the
 compiled file is first created.  See @(see
 book-compiled-file).</p></blockquote>

 <p>The three @('-okp') arguments, @(':uncertified-okp'), @('defaxioms-okp'),
 and @('skip-proofs-okp'), determine the system's behavior when the book or any
 sub-book is found to be uncertified, when the book or any sub-book is found to
 contain @(tsee defaxiom) events, and when the book or any sub-book is found to
 contain @(tsee skip-proofs) events, respectively.  All three default to
 @('t'), which means it is ``ok'' for the condition to arise.  In this case, a
 warning is printed but the processing to load the book is allowed to proceed.
 When one of these arguments is @('nil') and the corresponding condition
 arises, an error is signaled and processing is aborted.  <b>Exceptions</b>:
 @(':uncertified-okp t') is ignored if the @('include-book') is being performed
 on behalf of a @(tsee certify-book), and @(':uncertified-okp :ignore-certs')
 is an advanced option explained later in this topic.</p>

 <p>The keyword argument @(':ttags') may normally be omitted.  A few
 constructs, used for example if you are building your own system based on
 ACL2, may require it.  See @(see defttag) for an explanation of this
 argument.</p>

 <p>@('Include-book') is similar in spirit to @(tsee encapsulate) in that it is
 a single event that ``contains'' other @(see events), in this case the @(see
 events) listed in the file named.  @('Include-book') processes the non-@(tsee
 local) event forms in the file, assuming that each is admissible.  @(tsee
 Local) @(see events) in the file are ignored.  You may use @('include-book')
 to load several @(see books), creating the logical @(see world) that contains
 the definitions and theorems of all of them.</p>

 <p>If any non-@(tsee local) event of the book attempts to define a @(see name)
 that has already been defined &mdash; and the book's definition is not
 syntactically identical to the existing definition &mdash; the attempt to
 include the book fails, an error message is printed, and no change to the
 logical @(see world) occurs.  See @(see redundant-events) for the details.</p>

 <p>When a book is included, the default @(see defun-mode) (see @(see
 default-defun-mode)) for the first event is always @(':')@(tsee logic).  That
 is, the default @(see defun-mode) ``outside'' the book &mdash; in the
 environment in which @('include-book') was called &mdash; is irrelevant to the
 book.  @(see Events) that change the @(see defun-mode) are permitted within a
 book (provided they are not in @(tsee local) forms).  However, such changes
 within a book are not exported, i.e., at the conclusion of an
 @('include-book'), the ``outside'' default @(see defun-mode) is always the
 same as it was before the @('include-book').</p>

 <p>Unlike every other event in ACL2, @('include-book') puts a burden on you.
 Used improperly, @('include-book') can be unsound in the sense that it can
 create an inconsistent extension of a consistent logical @(see world).  A
 certification mechanism is available to help you carry this burden &mdash; but
 it must be understood up front that even certification is no guarantee against
 inconsistency here.  The fundamental problem is one of file system security.
 See @(see certificate) for a discussion of the security issues.</p>

 <p>At the beginning of execution of an @('include-book') form, even before
 executing @(see portcullis) @(see command)s, the value of @(tsee
 acl2-defaults-table) is restored to the value it had at startup.  After
 execution of an @('include-book') form, the value of @(tsee
 acl2-defaults-table) is restored to what it was immediately before that
 @('include-book') form was executed.  See @(see acl2-defaults-table).</p>

 <p>An advanced option is @(':uncertified-okp :ignore-certs').  This tells ACL2
 to ignore all @(see certificate) files while including the book and its
 sub-books, thus treating all these books as uncertified.  This option may be
 useful when writing a @('.acl2x') file for the first ``run'' of a ``two-runs
 approach'' to certification; see @(see set-write-acl2x).  Note however that
 ordinary certification (the second ``run'') will then fail unless care is
 taken to avoid @(':uncertified-okp :ignore-certs') during that second
 certification run.  Finally (and speaking in general, not particularly about a
 @(tsee certify-book) context), we emphasize that the option
 @(':uncertified-okp :ignore-certs') applies when including all sub-books, not
 only for the current book.  In particular, a subsidiary @('include-book') call
 specifying @(':uncertified-okp nil') will fail, because the superior
 @(':ignore-certs') value causes the subsidiary book to be treated as
 uncertified, which conflicts with the requirement of @(':uncertified-okp
 nil').</p>

 <p><b>Books Directory.</b> We refer to the ``books directory'' of an
 executable image as the full pathname string of the directory associated with
 @('include-book') keyword option @(':dir :system') for that image.  By
 default, it is the @('books/') subdirectory of the directory where the sources
 reside and the executable image is thus built (except for ACL2(r) &mdash; see
 @(see real) &mdash;, where it is @('books/nonstd/')).  If those books reside
 elsewhere, the environment variable @('ACL2_SYSTEM_BOOKS') can be set to the
 @('books/') directory under which they reside (a Unix-style pathname,
 typically ending in @('books/') or @('books'), is permissible).  In most
 cases, your ACL2 executable is a small script in which you can set this
 environment variable just above the line on which the actual ACL2 image is
 invoked, for example:</p>

 @({
  export ACL2_SYSTEM_BOOKS
  ACL2_SYSTEM_BOOKS=/home/acl2/4-0/acl2-sources/books
 })

 <p>If you follow suggestions in the installation instructions, these books
 will be the ACL2 community books; see @(see community-books).</p>

 <p>This concludes the guided tour through @(see books).  See @(see
 set-compile-fns) for a subtle point about the interaction between
 @('include-book') and on-the-fly @(see compilation).  See @(see certify-book)
 for a discussion of how to certify a book.</p>")

(defxdoc incompatible
  :parents (theories)
  :short "Declaring that two rules should not both be @(see enable)d"
  :long "@({
  Example:
  (theory-invariant (incompatible (:rewrite left-to-right)
                                  (:rewrite right-to-left)))

  General Form:
  (incompatible rune1 rune2)
 })

 <p>where @('rune1') and @('rune2') are two specific @(see rune)s.  The
 arguments are not evaluated.  @('Invariant') is just a macro that expands into
 a term that checks that not both @(see rune)s are enabled.  See @(see
 theory-invariant).  Also see @(see incompatible!) for a variant that insists
 the the arguments are indeed runes, not merely having the shapes of
 runes.</p>")

(defxdoc incompatible!
  :parents (theories)
  :short "Declaring that two rules must exist and should not both be @(see enable)d"
  :long "<p>This variant of @('incompatible') causes an error if either of its
 arguments is not a @(see rune), by calling @(tsee active-or-non-runep) instead
 of @(tsee active-runep).  See @(see incompatible) and see @(see
 theory-invariant).</p>")

(defxdoc induction
  :parents (rule-classes)
  :short "Make a rule that suggests a certain induction"
  :long "@({
  Example:
  (defthm recursion-by-sub2-induction-rule
    t
    :rule-classes ((:induction :pattern (* 1/2 i)
                               :condition (and (integerp i) (>= i 0))
                               :scheme (recursion-by-sub2 i))))
 })

 <p>In ACL2, as in Nqthm, the functions in a conjecture ``suggest'' the
 inductions considered by the system.  Because every recursive function must be
 admitted with a justification in terms of a measure that decreases in a
 well-founded way on a given set of ``controlling'' arguments, every recursive
 function suggests a dual induction scheme that ``unwinds'' the function from a
 given application.</p>

 <p>For example, since @(tsee append) (actually @(tsee binary-append), but
 we'll ignore the distinction here) decomposes its first argument by successive
 @(tsee cdr)s as long as it is a non-@('nil') true list, the induction scheme
 suggested by @('(append x y)') has a base case supposing @('x') to be either
 not a true list or to be @('nil') and then has an induction step in which the
 induction hypothesis is obtained by replacing @('x') by @('(cdr x)').  This
 substitution decreases the same measure used to justify the definition of
 @(tsee append).  Observe that an induction scheme is suggested by a recursive
 function application only if the controlling actuals are distinct variables, a
 condition that is sufficient to ensure that the ``substitution'' used to
 create the induction hypothesis is indeed a substitution and that it drives
 down a certain measure.  In particular, @('(append (foo x) y)') does not
 suggest an induction unwinding @(tsee append) because the induction scheme
 suggested by @('(append x y)') requires that we substitute @('(cdr x)') for
 @('x') and we cannot do that if @('x') is not a variable symbol.</p>

 <p>Once ACL2 has collected together all the suggested induction schemes it
 massages them in various ways, combining some to simultaneously unwind certain
 cliques of functions and vetoing others because they ``flaw'' others.  We do
 not further discuss the induction heuristics here; the interested reader
 should see Chapter XIV of A Computational Logic (Boyer and Moore, Academic
 Press, 1979) which represents a fairly complete description of the induction
 heuristics of ACL2.</p>

 <p>However, unlike Nqthm, ACL2 provides a means by which the user can
 elaborate the rules under which function applications suggest induction
 schemes.  Such rules are called @(':induction') rules.  The definitional
 principle automatically creates an @(':induction') rule, named @('(:induction
 fn)'), for each admitted recursive function, @('fn').  It is this rule that
 links applications of @('fn') to the induction scheme it suggests.  Disabling
 @('(:induction fn)') will prevent @('fn') from suggesting the induction scheme
 derived from its recursive definition.  It is possible for the user to create
 additional @(':induction') rules by using the @(':induction') rule class in
 @(tsee defthm).</p>

 <p>Technically we are ``overloading'' @(tsee defthm) by using it in the
 creation of @(':induction') rules because no theorem need be proved to set up
 the heuristic link represented by an @(':induction') rule.  However, since
 @(tsee defthm) is generally used to create rules and rule-class objects are
 generally used to specify the exact form of each rule, we maintain that
 convention and introduce the notion of an @(':induction') rule.  An
 @(':induction') rule can be created from any lemma whatsoever.</p>

 @({
  General Form of an :induction Lemma or Corollary:
  T

  General Form of an :induction rule-class:
  (:induction :pattern pat-term
              :condition cond-term
              :scheme scheme-term)
 })

 <p>where @('pat-term'), @('cond-term'), and @('scheme-term') are all terms,
 @('pat-term') is the application of a function symbol, @('fn'),
 @('scheme-term') is the application of a function symbol, @('rec-fn'), that
 suggests an induction, and, finally, every free variable of @('cond-term') and
 @('scheme-term') is a free variable of @('pat-term').  We actually check that
 @('rec-fn') is either recursively defined &mdash; so that it suggests the
 induction that is intrinsic to its recursion &mdash; or else that another
 @(':induction') rule has been proved linking a call of @('rec-fn') as the
 @(':pattern') to some scheme.</p>

 <p>The induction rule created is used as follows.  When an instance of the
 @(':pattern') term occurs in a conjecture to be proved by induction and the
 corresponding instance of the @(':condition') term is known to be non-@('nil')
 (by type reasoning alone), the corresponding instance of the @(':scheme') term
 is created and the rule ``suggests'' the induction, if any, suggested by that
 term.  (Analysis of that term may further involve induction rules, though the
 applied rule is removed from consideration during that further analysis, in
 order to avoid looping.)  If @('rec-fn') is recursive, then the suggestion is
 the one that unwinds that recursion.</p>

 <p>Consider, for example, the example given above,</p>

 @({
  (:induction :pattern (* 1/2 i)
              :condition (and (integerp i) (>= i 0))
              :scheme (recursion-by-sub2 i)).
 })

 <p>In this example, we imagine that @('recursion-by-sub2') is the
 function:</p>

 @({
  (defun recursion-by-sub2 (i)
    (if (and (integerp i)
             (< 1 i))
        (recursion-by-sub2 (- i 2))
        t))
 })

 <p>Observe that this function recursively decomposes its integer argument by
 subtracting @('2') from it repeatedly and stops when the argument is @('1') or
 less.  The value of the function is irrelevant; it is its induction scheme
 that concerns us.  The induction scheme suggested by @('(recursion-by-sub2
 i)') is</p>

 @({
  (and (implies (not (and (integerp i) (< 1 i)))   ; base case
                (:p i))
       (implies (and (and (integerp i) (< 1 i))    ; induction step
                     (:p (- i 2)))
                (:p i)))
 })

 <p>We can think of the base case as covering two situations.  The first is
 when @('i') is not an integer.  The second is when the integer @('i') is
 @('0') or @('1').  In the base case we must prove @('(:p i)') without further
 help.  The induction step deals with those integer @('i') greater than @('1'),
 and inductively assumes the conjecture for @('i-2') while proving it for
 @('i').  Let us call this scheme ``induction on @('i') by twos.''</p>

 <p>Suppose the above @(':induction') rule has been added.  Then an occurrence
 of, say, @('(* 1/2 k)') in a conjecture to be proved by induction would
 suggest, via this rule, an induction on @('k') by twos, provided @('k') was
 known to be a nonnegative integer.  This is because the induction rule's
 @(':pattern') is matched in the conjecture, its @(':condition') is satisfied,
 and the @(':scheme') suggested by the rule is that derived from
 @('(recursion-by-sub2 k)'), which is induction on @('k') by twos.  Similarly,
 the term @('(* 1/2 (length l))') would suggest no induction via this rule,
 even though the rule ``fires'' because it creates the @(':scheme')
 @('(recursion-by-sub2 (length l))') which suggests no inductions unwinding
 @('recursion-by-sub2') (since the controlling argument of
 @('recursion-by-sub2') in this @(':scheme') is not a variable symbol).</p>

 <p>Continuing this example one step further illustrates the utility of
 @(':induction') rules.  We could define the function @('recursion-by-cddr')
 that suggests the induction scheme decomposing its @(tsee consp) argument two
 @(tsee cdr)s at a time.  We could then add the @(':induction') rule linking
 @('(* 1/2 (length x))') to @('(recursion-by-cddr x)') and arrange for @('(*
 1/2 (length l))') to suggest induction on @('l') by @(tsee cddr).</p>

 <p>Observe that @(':induction') rules require no proofs to be done.  Such a
 rule is merely a heuristic link between the @(':pattern') term, which may
 occur in conjectures to be proved by induction, and the @(':scheme') term,
 from which an induction scheme may be derived.  Hence, when an @(':induction')
 rule-class is specified in a @(tsee defthm) event, the theorem proved is
 irrelevant.  The easiest theorem to prove is, of course, @('t').  Thus, we
 suggest that when an @(':induction') rule is to be created, the following form
 be used:</p>

 @({
  (defthm name T
    :rule-classes ((:induction :pattern pat-term
                               :condition cond-term
                               :scheme scheme-term)))
 })

 <p>The name of the rule created is @('(:induction name)').  When that rune is
 disabled the heuristic link between @('pat-term') and @('scheme-term') is
 broken.</p>")

(defxdoc infected-constraints
  :parents (encapsulate)
  :short "@(tsee Defun)s affecting @(see constraint)s of @(tsee encapsulate)s"
  :long "<p>Here we explain briefly the two kinds of @('\"Infected\"') @(see
 warnings) that are sometimes printed near the end of the output from @(tsee
 encapsulate) @(see events).  Also see @(see constraint) for a more complete
 discussion of constraints produced by @('encapsulate') events, and see @(see
 subversive-recursions) for a more complete discussion of the second kind of
 @('\"Infected\"') warning mentioned below, in the last example.</p>

 <p>An @('\"Infected\"') warning indicates that a @(tsee defun) event inside an
 @('encapsulate') event affects the constraint exported for the function
 introduced in the @(see signature) of that @('encapsulate').  Let's compare
 the following three examples.</p>

 <p><b>EXAMPLE 1</b>.</p>

 @({
  (encapsulate
   (((sig-fn *) => *))

   (local (defun sig-fn (x) (cons x x)))

   (defun foo (x)
     (sig-fn x))

   (defthm foo-prop
     (consp (foo x))))
 })

 <p>In Example 1 above, ACL2 warns us that the @('defun') event is having an
 effect on the constraint of another function (more on that below).</p>

 @({
 ACL2 Warning [Infected] in ( ENCAPSULATE (((SIG-FN * ...) ...) ...)
 ...):  Note that the definitional equation for FOO infects the constraint
 of this encapsulation....
 })

 <p>Indeed, just above that warning we see that the definitional equation for
 @('foo') is part of the constraint not only on @('foo') but also on
 @('sig-fn').</p>

 @({
 The following constraint is associated with both of the functions FOO
 and SIG-FN:

 (AND (EQUAL (FOO X) (SIG-FN X)) (CONSP (FOO X)))
 })

 <p>The warning message suggests the desirability of moving the definition out
 of the @('encapsulate'), if possible.  That is not possible above: the
 definition of @('foo') cannot be moved before the @('encapsulate') because it
 depends syntactically on @('sig-fn'), and it cannot be moved after the
 @('encapsulate') because it depends syntactically on @('foo-prop').</p>

 <p>By contrast, in the next two examples the @('defun') of @('foo') can be
 moved before, respectively after, the @('encapsulate').  In these simple
 cases, ACL2 in effect does that for us automatically, and the constraint for
 @('sig-fn') doesn't mention @('foo') or vice-versa.  In other cases, you might
 want to think about how to move the relevant @('defun') (for @('foo'), in this
 case) manually.</p>

 <p><b>EXAMPLE 2</b> (moving the definition of @('foo') before the
 @('encapsulate')).</p>

 @({
  (encapsulate
   (((sig-fn *) => *))

   (local (defun sig-fn (x) (cons x x)))

   (defun foo (x)
     x)

   (defthm foo-prop
     (equal (foo x) (car (sig-fn x)))))
 })

 <p><b>EXAMPLE 3</b> (moving the definition of @('foo') after the
 @('encapsulate')).</p>

 @({
  (encapsulate
   (((sig-fn *) => *))

   (local (defun sig-fn (x) (cons x x)))

   (defun foo (x)
     (sig-fn x))

   (defthm foo-prop
     (consp (sig-fn x)))
   )
 })

 <p>We now turn to a second kind of @('\"Infected\"') warning for a @('defun')
 form inside an @('encapsulate') form.  This type of warning indicates that in
 addition to the effect on constraints discussed above, ACL2 refuses to store
 an induction scheme or a built-in @(see type-prescription) rule for the
 @('defun').  Consider the following example.</p>

 <p><b>EXAMPLE 4</b>.</p>

 @({
  (encapsulate
    (((f *) => *))

    (local (defun f (x) (cdr x)))

    (defthm f-prop
      (equal (f nil) nil))

    (defun g (x)
      (if (consp x)
          (g (f x))
        x)))
 })

 <p>As in Example 1 above, the exported constraint is on both function symbols
 that have been introduced, reported as follows by ACL2.</p>

 @({
 The following constraint is associated with both of the functions G
 and F:

 (AND (EQUAL (F NIL) NIL)
      (EQUAL (G X) (IF (CONSP X) (G (F X)) X)))
 })

 <p>But this time, in addition, no induction scheme is stored for @('g'), nor
 is any built-in @(see type-prescription) rule stored for @('g'), as indicated
 by a warning that begins as follows.</p>

 @({
 ACL2 Warning [Infected] in ( ENCAPSULATE (((F * ...) ...) ...) ...):
 Note that G is ``subversive.''  See :DOC infected-constraints....
 })

 <p>Note that if @('f') and @('g') had been similarly defined at the top level
 instead of within an @('encapsulate'), a type-prescription rule would be added
 asserting that ``the type of G is described by the theorem @('(NOT (CONSP (G
 X)))').''  But there is no such rule introduced in this ``subversive'' case.
 Indeed, this ``theorem'' is not actually a theorem after evaluating the
 @('encapsulate'), as it does not even follow from the stronger
 axiom (stronger, that is, than the constraint displayed above) that both
 @('f') and @('g') are the identity function.</p>

 <p>See @(see subversive-recursions) for more details, including criteria for
 when this ``subversive'' situation arises and what might be done to address
 it.  Also see @(see constraint) for a general discussion of constraints
 introduced by an @(tsee encapsulate) event.</p>")

(defxdoc initialize-event-user
  :parents (prover-output)
  :short "User-supplied code to initiate @(see events)"
  :long "<p>This utility is intended for system hackers, not standard ACL2
 users.</p>

 <p>See @(see finalize-event-user) to see how to supply code to be run at the
 end of @(see events).  We assume familiarity with @('finalize-event-user');
 here we focus on how to supply code for the beginning as well as the end of
 events.</p>

 <p>As with @(see finalize-event-user), you attach your own function of
 argument list @('(ctx qbody state)') to @('initialize-event-user').  (See
 @(see finalize-event-user) for discussion of @('ctx') and @('body').)  The
 attachment should return @('state') and have a trivial guard, requiring
 (implicitly) only that @('state') satisfies @('state-p') unless you use trust
 tags to avoid that requirement.  For example:</p>

 @({
  (defattach initialize-event-user initialize-event-user-test)
 })

 <p>Why would you want to do this?  Presumably you are building a system on top
 of ACL2 and you want to track your own data.  For example, suppose you want to
 save the time in some @(see state) global variable, @('my-time').  You could
 do the following.</p>

 @({
  (defun my-init (ctx body state)
    (declare (xargs :stobjs state
                    :guard-hints
                    ((\"Goal\" :in-theory (enable read-run-time))))
             (ignore ctx body))
    (mv-let (seconds state)
            (read-run-time state)
            (f-put-global 'start-time seconds state)))

  (defun my-final (ctx body state)
    (declare (xargs :stobjs state
                    :guard-hints
                    ((\"Goal\" :in-theory (enable read-run-time))))
             (ignore ctx body))
    (mv-let (seconds state)
            (read-run-time state)
            (prog2$ (if (boundp-global 'start-time state)
                        (cw \"Time: ~x0 seconds~%\"
                            (- seconds (fix (@ start-time))))
                      (cw \"BIG SURPRISE!~%\"))
                    (f-put-global 'end-time seconds state))))

  (defattach initialize-event-user my-init)
  (defattach finalize-event-user my-final)
 })

 <p>Here is an abbreviated log, showing the time being printed at the end.</p>

 @({
  ACL2 !>(thm (equal (append (append x y) x y x y x y x y)
                     (append x y x y x y x y x y)))

  *1 (the initial Goal, a key checkpoint) is pushed for proof by induction.
  ....
  ACL2 Error in ( THM ...):  See :DOC failure.

  ******** FAILED ********
  Time: 869/100 seconds
  ACL2 !>
 })")

(defxdoc instructions
  :parents (proof-builder)
  :short "Instructions to the interactive proof-builder"
  :long "<p>See @(see proof-builder) for an introduction to the interactive
 ``proof-builder'' goal manager, which supports much more direct control of the
 proof process than is available by direct calls to the prover (as are normally
 made using @(tsee defthm) or @(tsee thm)).  In brief, typical use is to
 evaluate the form @('(verify SOME-GOAL)'), where @('SOME-GOAL') is a
 formula (i.e., term) that you would like to prove.  Various
 commands (instructions) are available at the resulting prompt; see @(see
 proof-builder-commands).  When the proof is completed, suitable invocation of
 the @('exit') command will print out a form containing an @(':instructions')
 field that provides the instructions that you gave interactively, so that this
 form can be evaluated non-interactively.</p>

 <p>Thus, also see @(see defthm) for the role of @(':instructions') in place of
 @(':')@(tsee hints).  As illustrated by the following example, the value
 associated with @(':instructions') is a list of interactive @(see
 proof-builder) commands.</p>

 @({
  Example:
  (defthm associativity-of-append
          (equal (append (append x y) z)
                 (append x (append y z)))
          :instructions
          (:induct (:dv 1) (:dv 1) :x :up :x (:dv 2) := (:drop 2)
           :top (:dv 2) :x :top :s :bash))
 })

 <p>See @(see proof-builder-commands) for a list of supported interactive
 proof-builder instructions and links to their documentation.</p>

 <p>Below, we describe a capability for supplying @(':instructions') as
 @(':')@(tsee hints).</p>

 <p>The most basic utilities for directing the discharge of a proof obligation
 are @(':')@(tsee hints) and (less commonly) @(':instructions').  Individual
 instructions may call the prover with @(':hints'); in that sense, prover hints
 may occur inside instructions.  We now describe how, on the other hand,
 instructions may occur inside hints.</p>

 <p>ACL2 supports @(':instructions') as a hints keyword.  The following example
 forms the basis for our running example.  This example does not actually need
 hints, but imagine that the inductive step &mdash; which is \"Subgoal *1/2\"
 &mdash; was difficult.  You could submit that goal to @(tsee verify), do an
 interactive proof, submit @('(exit t)') to obtain the list of
 @(':instructions'), and then paste in those instructions.  When you submit the
 resulting event, you might see the following.  Below we'll explain the hint
 processing.</p>

 @({
  ACL2 !>(thm (equal (append (append x y) z)
                     (append x (append y z)))
              :hints ((\"Subgoal *1/2\"
                       :instructions
                       (:promote (:dv 1) (:dv 1) :x :up :x (:dv 2) :=
                        (:drop 2) :top (:dv 2) :x :top :s))))

  Name the formula above *1.

  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.

  We will induct according to a scheme suggested by (BINARY-APPEND X Y).
  This suggestion was produced using the :induction rule BINARY-APPEND.
  If we let (:P X Y Z) denote *1 above then the induction scheme we'll
  use is
  (AND (IMPLIES (AND (NOT (ENDP X)) (:P (CDR X) Y Z))
                (:P X Y Z))
       (IMPLIES (ENDP X) (:P X Y Z))).
  This induction is justified by the same argument used to admit BINARY-APPEND.
  When applied to the goal at hand the above induction scheme produces
  two nontautological subgoals.

  [Note:  A hint was supplied for our processing of the goal below.
  Thanks!]

  Subgoal *1/2
  (IMPLIES (AND (NOT (ENDP X))
                (EQUAL (APPEND (APPEND (CDR X) Y) Z)
                       (APPEND (CDR X) Y Z)))
           (EQUAL (APPEND (APPEND X Y) Z)
                  (APPEND X Y Z))).

  But the trusted :CLAUSE-PROCESSOR function PROOF-BUILDER-CL-PROC replaces
  this goal by T.

  Subgoal *1/1
  (IMPLIES (ENDP X)
           (EQUAL (APPEND (APPEND X Y) Z)
                  (APPEND X Y Z))).

  By the simple :definition ENDP we reduce the conjecture to

  Subgoal *1/1'
  (IMPLIES (NOT (CONSP X))
           (EQUAL (APPEND (APPEND X Y) Z)
                  (APPEND X Y Z))).

  But simplification reduces this to T, using the :definition BINARY-APPEND
  and primitive type reasoning.

  That completes the proof of *1.

  Q.E.D.

  Summary
  Form:  ( THM ...)
  Rules: ((:DEFINITION BINARY-APPEND)
          (:DEFINITION ENDP)
          (:DEFINITION NOT)
          (:FAKE-RUNE-FOR-TYPE-SET NIL)
          (:INDUCTION BINARY-APPEND))
  Time:  0.02 seconds (prove: 0.01, print: 0.01, other: 0.00)

  Proof succeeded.
  ACL2 !>
 })

 <p>To understand how the @(':instructions') supplied above were processed,
 view the interactive proof-builder instruction interpreter as a
 ``clause-processor'': a function that takes an input goal and returns a list
 of goals (which can be the empty list).  Such a function has the property that
 if all goals in that returned list are theorems, then so is the input goal.
 This view of the interactive proof-builder instruction interpreter as a
 clause-processor leads to the following crucial observation.</p>

 <p><b>IMPORTANT!</b>.  Each call of the interactive proof-builder instruction
 interpreter is treated as a standalone clause-processor that is insensitive to
 the surrounding prover environment.  In particular:</p>

 <ul>

 <li>The interactive proof-builder's theory is not sensitive to @(':in-theory')
 @(see hints) already processed in the surrounding proof.  Indeed, the current
 theory for which proof-builder commands are processed is just the current
 theory of the ACL2 logical @(see world), i.e., the value of
 @('(current-theory :here)').  Moreover, references to
 @('(current-theory :here)') in a proof-builder @('in-theory') command, even
 implicit references such as provided by @(tsee enable) and @(tsee disable)
 expressions, are also references to the current theory of the ACL2 logical
 @(see world).</li>

 <li>The @(see rune)s used during an @(':instructions') hint are not tracked
 beyond that hint, hence may not show up in the summary of the overall proof.
 Again, think of the @(':instructions') hint as a @(see clause-processor) call,
 which has some effect not tracked by the surrounding proof other than for the
 child goals that it returns.</li>

 </ul>

 <p>We continue now with our discussion of the interactive proof-builder
 instruction interpreter as a clause-processor.</p>

 <p>In the example above, the input goal (@('\"Subgoal *1/2\"')) was processed
 by the proof-builder instruction interpreter.  The result was the empty goal
 stack, therefore proving the goal, as reported in the output, which we repeat
 here.</p>

 @({
  [Note:  A hint was supplied for our processing of the goal below.
  Thanks!]

  Subgoal *1/2
  (IMPLIES (AND (NOT (ENDP X))
                (EQUAL (APPEND (APPEND (CDR X) Y) Z)
                       (APPEND (CDR X) Y Z)))
           (EQUAL (APPEND (APPEND X Y) Z)
                  (APPEND X Y Z))).

  But the trusted :CLAUSE-PROCESSOR function PROOF-BUILDER-CL-PROC replaces
  this goal by T.
 })

 <p><b>Remark.</b> This brief remark can probably be ignored, but we include it
 for completeness.  The @(':CLAUSE-PROCESSOR') message above may be surprising,
 since the hint attached to @('\"Subgoal *1/2\"') is an @(':instructions')
 hint, not a @(':clause-processor') hint.  But @(':instructions') is actually a
 custom keyword hint (see @(see custom-keyword-hints)), and may be thought of
 as a macro that expands to a @(':')@(tsee clause-processor) hint, one that
 specifies @('proof-builder-cl-proc') as the clause-processor function.  The
 keen observer may notice that the clause-processor is referred to as
 ``trusted'' in the above output.  Normally one needs a trust tag (see @(see
 defttag)) to install a trusted clause-processor, but that is not the case for
 the built-in clause-processor, @('proof-builder-cl-proc').  Finally, we note
 that @(':instructions') @(see hints) are ``spliced'' into the hints as
 follows: the appropriate @(':')@(tsee clause-processor) hint replaces the
 @(':instructions') hint, and the other hints remain intact.  It may seems
 surprising that one can thus, for example, use @(':instructions') and
 @(':in-theory') together; but although the @(':in-theory') hint will have no
 effect on execution of the @(':instructions') (see first bullet above), the
 @(':in-theory') hint will apply in the usual manner to any child goals (see
 @(see hints-and-the-waterfall)).  End of Remark.</p>

 <p>Now consider the case that the supplied instructions do not prove the goal.
 That is, suppose that the execution of those instructions results in a
 non-empty goal stack.  In that case, the resulting goals become children of
 the input goals.  The following edited log provides an illustration using a
 modification of the above example, this time with a single instruction that
 splits into two cases.</p>

 @({
  ACL2 !>(thm (equal (append (append x y) z)
                     (append x (append y z)))
              :hints ((\"Subgoal *1/2\"
                       :instructions
                       ((:casesplit (equal x y))))))

  [[ ... output omitted ... ]]

  Subgoal *1/2
  (IMPLIES (AND (NOT (ENDP X))
                (EQUAL (APPEND (APPEND (CDR X) Y) Z)
                       (APPEND (CDR X) Y Z)))
           (EQUAL (APPEND (APPEND X Y) Z)
                  (APPEND X Y Z))).

  We now apply the trusted :CLAUSE-PROCESSOR function PROOF-BUILDER-CL-PROC
  to produce two new subgoals.

  Subgoal *1/2.2

  [[ ... output omitted ... ]]

  Subgoal *1/2.1

  [[ ... output omitted ... ]]
 })

 <p>We have seen that an @(':instructions') hint may produce zero or more
 subgoals.  There may be times where you wish to insist that it produce zero
 subgoals, i.e., that it prove the desired goal.  The interactive
 proof-builder's `@('finish')' command works nicely for this purpose.  For
 example, the following form is successfully admitted, but if you delete some
 of the commands (for example, the @(':s') command at the end), you will see an
 informative error message.</p>

 @({
  (thm (equal (append (append x y) z)
              (append x (append y z)))
       :hints ((\"Subgoal *1/2\"
                :instructions
                ((finish :promote (:dv 1) (:dv 1) :x :up :x (:dv 2) :=
                         (:drop 2) :top (:dv 2) :x :top :s)))))
 })

 <p>If an :instructions hint of the form @('((finish ...))') fails to prove the
 goal, the clause-processor is deemed to have caused an error.  Indeed, any
 ``failure'' of a supplied proof-builder instruction will be deemed to cause an
 error.  In this case, you should see an error message such as the
 following:</p>

 @({
  Saving proof-builder error state; see :DOC instructions.  To retrieve:

  (RETRIEVE :ERROR1)
 })

 <p>In this case, you can evaluate the indicated @(tsee retrieve) command in
 the ACL2 read-eval-print loop, to get to the point of failure.</p>

 <p>You may have noticed that there is no output from the interactive
 proof-builder in the examples above.  This default behavior prevents confusion
 that could arise from use of proof-builder commands that call the theorem
 prover such as @('prove'), @('bash'), @('split'), and @('induct').  These
 commands produce output for what amounts to a fresh proof attempt, which could
 confuse attempts to understand the surrounding proof log.  You can override
 the default behavior by providing a command of the form</p>

 <code> @('(comment inhibit-output-lst VAL)') </code>

 <p>where @('VAL') is either the keyword @(':SAME') (indicating that no change
 should be made to which output is inhibited) or else is a legal value for
 inhibited output; see @(see set-inhibit-output-lst).  The following two
 variants of the immediately preceding @('THM') form will each produce output
 from the interactive proof-builder commands, assuming in the first variant
 that output hasn't already been inhibited.</p>

 @({
  (thm (equal (append (append x y) z)
                     (append x (append y z)))
              :hints ((\"Subgoal *1/2\"
                       :instructions
                       ((comment inhibit-output-lst :same)
                        (:casesplit (equal x y))))))

  (thm (equal (append (append x y) z)
                     (append x (append y z)))
              :hints ((\"Subgoal *1/2\"
                       :instructions
                       ((comment inhibit-output-lst (proof-tree))
                        (:casesplit (equal x y))))))
 })

 <p>Note that such a @('comment') instruction must be provided explicitly
 (i.e., not by way of a proof-builder @(see macro-command)) as the first
 instruction, in order to have the effect on inhibited output that is described
 above.</p>

 <p>The following contrived example gives a sense of how one might want to use
 @(':instructions') within @(':')@(tsee hints).  If you submit the following
 theorem</p>

 @({
  (thm (implies (true-listp x)
                (equal (reverse (reverse x)) x)))
 })

 <p>then you will see the following checkpoint printed with the summary.</p>

 @({
  Subgoal *1/3''
  (IMPLIES (AND (CONSP X)
                (EQUAL (REVAPPEND (REVAPPEND (CDR X) NIL) NIL)
                       (CDR X))
                (TRUE-LISTP (CDR X)))
           (EQUAL (REVAPPEND (REVAPPEND (CDR X) (LIST (CAR X)))
                             NIL)
                  X))
 })

 <p>This suggests proving the following theorem.  Here we state it using @(tsee
 defthmd), so that it is immediately disabled.  Normally disabling would be
 unnecessary, but for our contrived example it is useful to imagine disabling
 it, say because we are following a methodology that tends to keep @(see
 rewrite) rules disabled.</p>

 @({
  (defthmd revappend-revappend
    (equal (revappend (revappend x y) z)
           (revappend y (append x z))))
 })

 <p>We might then enter the interactive @(see proof-builder) to prove the
 original theorem interactively, as follows.</p>

 @({
  ACL2 !>(verify (implies (true-listp x)
                          (equal (reverse (reverse x)) x)))
  ->: bash
  ***** Now entering the theorem prover *****
  Goal'

  ([ A key checkpoint:

  Goal'
  (IMPLIES (TRUE-LISTP X)
           (EQUAL (REVAPPEND (REVAPPEND X NIL) NIL)
                  X))

  Goal' is subsumed by a goal yet to be proved.

  ])

  Q.E.D.

  Creating one new goal:  (MAIN . 1).

  The proof of the current goal, MAIN, has been completed.  However,
  the following subgoals remain to be proved:
    (MAIN . 1).
  Now proving (MAIN . 1).
  ->: th ; show current goal (\"th\" for \"theorem\")
  *** Top-level hypotheses:
  1. (TRUE-LISTP X)

  The current subterm is:
  (EQUAL (REVAPPEND (REVAPPEND X NIL) NIL)
         X)
  ->: p ; show current subterm only
  (EQUAL (REVAPPEND (REVAPPEND X NIL) NIL)
         X)
  ->: 1 ; dive to first argument
  ->: p
  (REVAPPEND (REVAPPEND X NIL) NIL)
  ->: sr ; show-rewrites

  1. REVAPPEND-REVAPPEND (disabled)
    New term: (REVAPPEND NIL (APPEND X NIL))
    Hypotheses: <none>
    Equiv: EQUAL

  2. REVAPPEND
    New term: (AND (CONSP (REVAPPEND X NIL))
                   (REVAPPEND (CDR (REVAPPEND X NIL))
                              (LIST (CAR (REVAPPEND X NIL)))))
    Hypotheses: <none>
    Equiv: EQUAL
  ->: (r 1) ; rewrite with rule #1 above
  Rewriting with REVAPPEND-REVAPPEND.
  ->: p
  (REVAPPEND NIL (APPEND X NIL))
  ->: top ; move to the top of the conclusion, making it the current subterm
  ->: p
  (EQUAL (REVAPPEND NIL (APPEND X NIL)) X)
  ->: prove ; finish the proof
  ***** Now entering the theorem prover *****

  Q.E.D.

  *!*!*!*!*!*!* All goals have been proved! *!*!*!*!*!*!*
  You may wish to exit.
  ->: (exit t) ; the argument, t, causes :instructions to be printed
  (DEFTHM T
          (IMPLIES (TRUE-LISTP X)
                   (EQUAL (REVERSE (REVERSE X)) X))
          :INSTRUCTIONS (:BASH (:DV 1)
                               (:REWRITE REVAPPEND-REVAPPEND)
                               :TOP :PROVE))
   NIL
  ACL2 !>(thm
          (IMPLIES (TRUE-LISTP X)
                   (EQUAL (REVERSE (REVERSE X)) X))
          :hints ((\"Goal\"
                   :INSTRUCTIONS ; copy what was printed above:
                   (:BASH (:DV 1)
                          (:REWRITE REVAPPEND-REVAPPEND)
                          :TOP :PROVE))))
  Goal'

  Q.E.D.

  Q.E.D.

  Q.E.D.

  Summary
  Form:  ( THM ...)
  Rules: NIL
  Hint-events: ((:CLAUSE-PROCESSOR PROOF-BUILDER-CL-PROC))
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

  Proof succeeded.
  ACL2 !>
 })

 <p>Finally we present an even more contrived example, based on the one above.
 This example illustrates that there is actually no limit imposed on the
 nesting of @(':instructions') within @(':')@(tsee hints) within
 @(':instructions'), and so on.  Notice the indication of nesting levels:
 ``@('1>')'' to ``@('<1')'' for output from nesting level 1, and ``@('2>')'' to
 ``@('<2')'' for output from nesting level 2.</p>

 @({
  (thm (implies (true-listp x)
                (equal (reverse (reverse x)) x))
       :hints ((\"Goal\"
                :instructions
                ((comment inhibit-output-lst :same)
                 (:prove
                  :hints ((\"Goal\" :in-theory (disable append))
                          (\"Subgoal *1/3''\"
                           :instructions
                           ((comment inhibit-output-lst :same)
                            :bash
                            (:dv 1)
                            (:rewrite revappend-revappend)))))))))
 })

 <p>Here is an edited version of the resulting log.</p>

 @({
  [Note:  A hint was supplied for our processing of the goal above.
  Thanks!]

  [[1> Executing proof-builder instructions]]

  ->: (COMMENT INHIBIT-OUTPUT-LST :SAME)
  ->: (:PROVE
           :HINTS
           ((\"Goal\" :IN-THEORY (DISABLE APPEND))
            (\"Subgoal *1/3''\" :INSTRUCTIONS ((COMMENT INHIBIT-OUTPUT-LST :SAME)
                                             :BASH (:DV 1)
                                             (:REWRITE REVAPPEND-REVAPPEND)))))
  ***** Now entering the theorem prover *****

  [[ ... output omitted ... ]]

  [Note:  A hint was supplied for our processing of the goal below.
  Thanks!]

  Subgoal *1/3''
  (IMPLIES (AND (CONSP X)
                (EQUAL (REVAPPEND (REVAPPEND (CDR X) NIL) NIL)
                       (CDR X))
                (TRUE-LISTP (CDR X)))
           (EQUAL (REVAPPEND (REVAPPEND (CDR X) (LIST (CAR X)))
                             NIL)
                  X)).

  [[2> Executing proof-builder instructions]]

  ->: (COMMENT INHIBIT-OUTPUT-LST :SAME)
  ->: :BASH
  ***** Now entering the theorem prover *****

  [Note:  A hint was supplied for our processing of the goal above.
  Thanks!]

  But we have been asked to pretend that this goal is subsumed by the
  yet-to-be-proved |PROOF-BUILDER Goal|.

  Q.E.D.

  Creating one new goal:  (MAIN . 1).

  The proof of the current goal, MAIN, has been completed.  However,
  the following subgoals remain to be proved:
    (MAIN . 1).
  Now proving (MAIN . 1).
  ->: (:DV 1)
  ->: (:REWRITE REVAPPEND-REVAPPEND)
  Rewriting with REVAPPEND-REVAPPEND.

  [[<2 Completed proof-builder instructions]]

  We now apply the trusted :CLAUSE-PROCESSOR function PROOF-BUILDER-CL-PROC
  to produce one new subgoal.

  Subgoal *1/3'''

  [[ ... output omitted ... ]]

  [[<1 Completed proof-builder instructions]]
 })

 <p>The nesting levels are independent of whether or not output is enabled; for
 example, if the first @('(comment ...)') form below is omitted, then we will
 see only the output bracketed by ``@('2>')'' to ``@('<2')''.  Note also that
 these levels are part of the error states saved for access by @(tsee retrieve)
 (as indicated above); for example, a failure at level 1 would be associated
 with symbol @(':ERROR1') as indicated above, while a failure at level 2 would
 be associated with symbol @(':ERROR2').</p>")

(defxdoc int=
  :parents (numbers acl2-built-ins)
  :short "Test equality of two integers"
  :long "<p>@('(int= x y)') is logically equivalent to @('(equal x y)').</p>

 <p>Unlike @(tsee equal), @('int=') requires its arguments to be numbers (or
 else causes a @(see guard) violation; see @(see guard)).  Generally, @('int=')
 is executed more efficiently than @(tsee equal) or @(tsee =) on
 integers.</p>

 @(def int=)")

(defxdoc integer-length
  :parents (numbers acl2-built-ins)
  :short "Number of bits in two's complement integer representation"
  :long "<p>For non-negative integers, @('(integer-length i)') is the minimum
 number of bits needed to represent the integer.  Any integer can be
 represented as a signed two's complement field with a minimum of
 @('(+ (integer-length i) 1)') bits.</p>

 <p>The @(see guard) for @('integer-length') requires its argument to be an
 integer.  @('Integer-length') is defined in Common Lisp.  See any Common Lisp
 documentation for more information.</p>

 @(def integer-length)")

(defxdoc integer-listp
  :parents (numbers lists acl2-built-ins)
  :short "Recognizer for a true list of integers"
  :long "<p>The predicate @('integer-listp') tests whether its argument is a
 true list of integers.</p>

 @(def integer-listp)")

(defxdoc integer-range-p
  :parents (numbers acl2-built-ins)
  :short "Recognizer for integers between two bounds."
  :long "<p>The predicate @('(integer-range-p lower upper x)') tests whether
  @('x') is an integer greater than or equal to @('lower') and less than
  @('upper').</p>

  @(def integer-range-p)")

(defxdoc integerp
  :parents (numbers acl2-built-ins)
  :short "Recognizer for whole numbers"
  :long "<p>@('(integerp x)') is true if and only if @('x') is an integer.</p>")

(defxdoc interesting-applications
  :parents (acl2-tutorial)
  :short "Some industrial examples of ACL2 use"
  :long "<p>ACL2 is an interactive system in which you can model digital
 artifacts and guide the system to mathematical proofs about the behavior of
 those models.  It has been used at such places as AMD, Centaur, IBM, and
 Rockwell Collins to verify interesting properties of commercial designs.  It
 has been used to verify properties of models of microprocessors, microcode,
 the Sun Java Virtual Machine, operating system kernels, other verifiers, and
 interesting algorithms.</p>

 <p>Here we list just a few of the industrially-relevant results obtained with
 ACL2.  Reading the list may help you decide you want to learn how to use ACL2.
 If you do decide you want to learn more, we recommend that you take <see
 topic='@(url |The Tours|)'>The Tours</see> after you leave this page.</p>

 <p>ACL2 was used at <b>Motorola Government Systems</b> to certify several
 microcode programs for the <b>Motorola CAP digital signal processor</b>,
 including a comparator sort program that is particularly subtle. In the same
 project, ACL2 was used to model the CAP at both the pipelined architectural
 level and the instruction set level.  The architectural model was bit- and
 cycle-accurate: it could be used to predict every bit of memory on every
 cycle.  The models were proved equivalent under certain hypotheses, the most
 important being a predicate that analyzed the microcode for certain pipeline
 hazards. This predicate defined what the hazards were, syntactically, and the
 equivalence of the two models established the correctness of this syntactic
 characterization of hazards.  Because ACL2 is a functional programming
 language, the ACL2 models and the hazard predicate could be executed.  ACL2
 executed a microcode interpreter several times faster than the hardware
 simulator could execute it &mdash; with assurance that the answers were
 equivalent.  In addition, the ACL2 hazard predicate was executed on over fifty
 microcode programs written by Motorola engineers and extracted from the ROM
 mechanically. Hazards were found in some of these.  (See, for example, Bishop
 Brock and Warren. A. Hunt, Jr. ``Formal analysis of the Motorola CAP DSP.'' In
 <i>Industrial-Strength Formal Methods</i>. Springer-Verlag, 1999.)</p>

 <p>ACL2 was used at <b>Advanced Micro Devices</b> (AMD) to verify the
 compliance of the <b>AMD Athlon</b>'s (TM) elementary floating point operations
 with their IEEE 754 specifications. This followed ground-breaking work in 1995
 when ACL2 was used to prove the correctness of the microcode for
 floating-point division on the <b>AMD K5</b>. The AMD Athlon work proved
 addition, subtraction, multiplication, division, and square root compliant
 with the IEEE standard. Bugs were found in RTL designs. These bugs had
 survived undetected in hundreds of millions of tests but were uncovered by
 ACL2 proof attempts. The RTL in the fabricated Athlon FPU has been
 mechanically verified by ACL2.  Similar ACL2 proofs have been carried out for
 every major AMD FPU design fabricated since the Athlon.  (See for example,
 David Russinoff. ``A mechanically checked proof of correctness of the AMD5K86
 floating-point square root microcode''.  <i>Formal Methods in System
 Design</i> Special Issue on Arithmetic Circuits, 1997.)</p>

 <p>ACL2 was used at <b>IBM</b> to verify the floating point divide and square
 root on the <b>IBM Power 4</b>.  (See Jun Sawada. ``Formal verification of
 divide and square root algorithms using series calculation''. In
 <i>Proceedings of the ACL2 Workshop 2002</i>, Grenoble, April 2002.)</p>

 <p>ACL2 was used to verify floating-point addition/subtraction instructions
 for the <b>media unit</b> from <b>Centaur Technology</b>'s 64-bit,
 X86-compatible microprocessor. This unit implements over one hundred
 instructions, with the most complex being floating-point
 addition/subtraction. The media unit can add/subtract four pairs of
 floating-point numbers every clock cycle with an industry-leading two-cycle
 latency. The media unit was modeled by translating its Verilog design into an
 HDL deeply embedded in the ACL2 logic. The proofs used a combination of AIG-
 and BDD-based symbolic simulation, case splitting, and theorem proving.  (See
 Warren A. Hunt, Jr. and Sol Swords. ``Centaur Technology Media Unit
 Verification''. In <i>CAV '09: Proceedings of the 21st International</i>
 <b>Conference on Computer Aided Verification</b>, pages 353&ndash;367, Berlin,
 Heidelberg, 2009. Springer-Verlag.)</p>

 <p><b>Rockwell Collins</b> used ACL2 to prove information flow properties
 about its <b>Advanced Architecture MicroProcessor 7 Government Version
 (AAMP7G)</b>, a Multiple Independent Levels of Security (MILS) device for use
 in cryptographic applications. The AAMP7G provides MILS capability via a
 verified secure hardware-based separation kernel. The AAMP7G's design was
 proved to achieve MILS using ACL2, in accordance with the standards set by
 EAL-7 of the Common Criteria and Rockwell Collins has received National
 Security Agency (NSA) certification for the device based on this work.  (See
 Matthew M. Wilding, David A. Greve, Raymond J. Richards, and David S. Hardin.
 ``Formal Verification of Partition Management for the AAMP7G
 Microprocessor''. In <i>Design and Verification of Microprocessor Systems for
 High-Assurance Applications</i>, David S. Hardin, ed., pages 175&ndash;191,
 Springer US, 2010.)</p>

 <p>Key properties of the <b>Sun Java Virtual Machine</b> and its <b>bytecode
 verifier</b> were verified in ACL2. Among the properties proved were that
 certain invariants are maintained by <b>class loading</b> and that the
 bytecode verifier insures that execution is safe. In addition, various <b>JVM
 bytecode programs</b> have been verified using this model of the JVM.  (See
 Hanbing Liu. <i>Formal Specification and</i> <i>Verification of a JVM and its
 Bytecode Verifier</i>. PhD thesis, University of Texas at Austin, 2006.)</p>

 <p>The <b>Boyer-Moore fast string searching algorithm</b> was verified with
 ACL2, including a model of the JVM bytecode for the search algorithm itself
 (but not the preprocessing).  (See J S. Moore and Matt Martinez. ``A
 mechanically checked proof of the correctness of the Boyer-Moore fast string
 searching algorithm.'' In <i>Engineering Methods and Tools for Software Safety
 and Security</i> pages 267&ndash;284. IOS Press, 2009.)</p>

 <p>ACL2 was used to verify the fidelity between an <b>ACL2-like theorem
 prover</b> and a simple (``trusted by inspection'') <b>proof checker</b>,
 thereby establishing (up to the soundness of ACL2) the soundness of the
 ACL2-like theorem prover.  This project was only part of a much larger project
 in which the resulting ACL2 proof script was then hand-massaged into a script
 suitable for the ACL2-like theorem prover to process, generating a formal
 proof of its fidelity that has been checked by the trusted proof checker.
 (See Jared Davis.  <i>Milawa: A Self-Verifying Theorem Prover</i>.
 Ph.D. Thesis, University of Texas at Austin, December, 2009.)</p>

 <p>These are but a few of the interesting projects carried out with ACL2.
 Many of the authors mentioned above have versions of the papers on their web
 pages.  In addition, see <a
 href='http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html'>Books
 and Papers about ACL2 and its Applications</a>.  Also, see the presentations
 in each of the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/workshops.html'>ACL2
 Workshops</a>.</p>")

(defxdoc interfacing-tools
  :parents (top

; Including acl2 as a parent so that all ACL2 system topics can be found under
; the graph rooted at the acl2 node.

            acl2)
  :short "Libraries and tools for doing basic <see topic='@(url std/io)'>file
 i/o</see>, using raw <see topic='@(url quicklisp)'>Common Lisp
 libraries</see>, working with the <see topic='@(url oslib)'>operating
 system</see>, and interfacing with <see topic='@(url bridge)'>other
 programs</see>.")

(defxdoc intern
  :parents (symbolp packages acl2-built-ins)
  :short "Create a new symbol in a given package"
  :long "<p>@('(intern symbol-name symbol-package-name)') returns a symbol with
 the given @(tsee symbol-name) and the given @(tsee symbol-package-name).  We
 restrict Common Lisp's @('intern') so that the second argument is either the
 symbol *main-lisp-package-name*, the value of that constant, or is one of
 \"ACL2\", \"ACL2-INPUT-CHANNEL\", \"ACL2-OUTPUT-CHANNEL\", or \"KEYWORD\".  To
 avoid that restriction, see @(see intern$).</p>

 <p>In ACL2 @('intern') is actually implemented as a macro that expands to a
 call of a similar function whose second argument is a symbol.  Invoke @(':pe
 intern') to see the definition, or see @(see intern-in-package-of-symbol).</p>

 <p>To see why is @('intern') so restricted consider @('(intern \"X\" \"P\")').
 In particular, is it a symbol and if so, what is its @(tsee
 symbol-package-name)?  One is tempted to say ``yes, it is a symbol in the
 package @('\"P\"').''  But if package @('\"P\"') has not yet been defined,
 that would be premature because the imports to the package are unknown.  For
 example, if @('\"P\"') were introduced with</p>

 @({
  (defpkg \"P\" '(LISP::X))
 })

 <p>then in Common Lisp @('(symbol-package-name (intern \"X\" \"P\"))') returns
 @('\"LISP\"').</p>

 <p>The obvious restriction on @('intern') is that its second argument be the
 name of a package known to ACL2.  We cannot express such a restriction
 (except, for example, by limiting it to those packages known at some fixed
 time, as we do).  Instead, we provide @(tsee intern-in-package-of-symbol)
 which requires a ``witness symbol'' for the package instead of the package.
 The witness symbol is any symbol (expressible in ACL2) and uniquely specifies
 a package necessarily known to ACL2.</p>")

(defxdoc intern$
  :parents (symbolp packages acl2-built-ins)
  :short "Create a new symbol in a given package"
  :long "<p>@('Intern$') is a macro that behaves the same as the macro @(tsee
 intern), except for weakening the restriction to a fixed set of package names
 so that any package name other than @('\"\"') is legal.  See @(see intern).
 Note that if you evaluate a call @('(intern$ x y)') for which there is no
 package with name @('y') that is known to ACL2, you will get an error.</p>

 <p>@('(Intern$ x y)') expands to:</p>

 @({
  (intern-in-package-of-symbol x (pkg-witness y))
 })

 <p>See @(see intern-in-package-of-symbol) and see @(see pkg-witness).</p>")

(defxdoc intern-in-package-of-symbol
  :parents (symbolp packages acl2-built-ins)
  :short "Create a symbol with a given name"
  :long "<p>Completion
  Axiom (@('completion-of-intern-in-package-of-symbol')):</p>

 @({
  (equal (intern-in-package-of-symbol x y)
         (if (and (stringp x)
                  (symbolp y))
             (intern-in-package-of-symbol x y)
           nil))
 })

 <p>@(see Guard) for @('(intern-in-package-of-symbol x y)'):</p>

 @({
  (and (stringp x) (symbolp y))
 })

 <p>Intuitively, @('(intern-in-package-of-symbol x y)') creates a symbol with
 @(tsee symbol-name) @('x') @(see intern)ed in the package containing @('y').
 More precisely, suppose @('x') is a string, @('y') is a symbol with @(tsee
 symbol-package-name) pkg and that the @(tsee defpkg) event creating pkg had
 the list of symbols imports as the value of its second argument.  Then
 @('(intern-in-package-of-symbol x y)') returns a symbol, ans, the @(tsee
 symbol-name) of ans is @('x'), and the @(tsee symbol-package-name) of ans is
 pkg, unless @('x') is the @(tsee symbol-name) of some member of imports with
 @(tsee symbol-package-name) ipkg, in which case the @(tsee
 symbol-package-name) of ans is ipkg.  Because @(tsee defpkg) requires that
 there be no duplications among the @(tsee symbol-name)s of the imports,
 @('intern-in-package-of-symbol') is uniquely defined.</p>

 <p>For example, suppose @('\"MY-PKG\"') was created by</p>

 @({
  (defpkg \"MY-PKG\" '(ACL2::ABC LISP::CAR)).
 })

 <p>Let @('w') be @(''my-pkg::witness').  Observe that</p>

 @({
  (symbolp w) is t                     ; w is a symbol
  (symbol-name w) is \"WITNESS\"         ; w's name is \"WITNESS\"
  (symbol-package-name w) is \"MY-PKG\"  ; w is in the package \"MY-PKG\"
 })

 <p>The construction of @('w') illustrates one way to obtain a symbol in a
 given package: write it down as a constant using the double-colon
 notation.</p>

 <p>But another way to obtain a symbol in a given package is to create it with
 @('intern-in-package-of-symbol').</p>

 @({
  (intern-in-package-of-symbol \"XYZ\" w) is MY-PKG::XYZ

  (intern-in-package-of-symbol \"ABC\" w) is ACL2::ABC

  (intern-in-package-of-symbol \"CAR\" w) is LISP::CAR

  (intern-in-package-of-symbol \"car\" w) is MY-PKG::|car|
 })")

(defxdoc intersection$
  :parents (lists acl2-built-ins)
  :short "Elements of one list that are not elements of another"
  :long "@({
  General Forms:
  (intersection$ l1 l2 ... lk)
  (intersection$ l1 l2 ... lk :test 'eql) ; same as above
  (intersection$ l1 l2 ... lk :test 'eq)    ; same, but eq is equality test
  (intersection$ l1 l2 ... lk :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Intersection$ x y)') equals a list that contains the @('member')s of
 @('x') that are also @('member')s of @('y').  More precisely, the resulting
 list is the result of deleting from @('x') those members that that are not
 members of @('y').  The optional keyword, @(':TEST'), has no effect logically,
 but provides the test (default @(tsee eql)) used for comparing members of the
 two lists.</p>

 <p>@('Intersection$') need not take exactly two arguments, though it must take
 at least one argument: @('(intersection$ x)') is @('x'), @('(intersection$ x y
 z ... :test test)') is @('(intersection$ x (intersection$ y z ... :test test)
 :test test)'), and if @(':TEST') is not supplied, then @('(intersection$ x y z
 ...)')  is @('(intersection$ x (intersection$ y z ...))').  For the discussion
 below we restrict ourselves, then, to the cases @('(intersection$ x y)') and
 @('(intersection$ x y :test test)').</p>

 <p>The @(see guard) for a call of @('intersection$') (in the two cases just
 above) depends on the test.  In all cases, both arguments must satisfy @(tsee
 true-listp).  If the test is @(tsee eql), then one of the arguments must
 satisfy @(tsee eqlable-listp).  If the test is @(tsee eq), then one of the
 arguments must satisfy @(tsee symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('intersection$') and its variants:</p>

 <blockquote><p>@('(intersection-eq x lst)') is equivalent to @('(intersection$
 x lst :test 'eq)');</p>

 <p>@('(intersection-equal x lst)') is equivalent to @('(intersection$ x lst
 :test 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('intersection-equal').</p>

 <p>Note that @('intersection-eq') can take any positive number of arguments,
 in analogy to @('intersection$'); indeed, @('(intersection-eq ...)') expands
 to @('(intersection$ ... :test 'eq)').  However, @('intersection-equal') is a
 function, not a macro, and takes exactly two arguments.</p>

 <p>@('Intersection$') is similar to the Common Lisp primitive
 @('intersection').  However, Common Lisp does not specify the order of
 elements in the result of a call of @('intersection').</p>

 @(def intersection-equal)")

(defxdoc intersection-theories
  :parents (theories theory-functions)
  :short "Intersect two @(see theories)"
  :long "@({
  Example:
  (intersection-theories (current-theory :here)
                         (theory 'arith-patch))

  General Form:
  (intersection-theories th1 th2)
 })

 <p>where @('th1') and @('th2') are theories (see @(see theories)).  To each of
 the arguments there corresponds a runic theory.  This function returns the
 intersection of those two runic @(see theories), represented as a list and
 ordered chronologically.</p>

 <p>This ``function'' is actually a macro that expands to a term mentioning the
 single free variable @(tsee world).  When theory expressions are evaluated by
 @(tsee in-theory) or the @(':')@(tsee in-theory) hint, @(tsee world) is bound
 to the current ACL2 @(see world).</p>")

(defxdoc intersectp
  :parents (lists acl2-built-ins)
  :short "Test whether two lists intersect"
  :long "@({
  General Forms:
  (intersectp l1 l2)
  (intersectp l1 l2 :test 'eql)   ; same as above (eql as equality test)
  (intersectp l1 l2 :test 'eq)    ; same, but eq is equality test
  (intersectp l1 l2 :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Intersectp l1 l2)') returns @('t') if @('l1') and @('l2') have a @(tsee
 member) in common, else it returns @('nil').  The optional keyword,
 @(':TEST'), has no effect logically, but provides the test (default @(tsee
 eql)) used for comparing members of the two lists.</p>

 <p>The @(see guard) for a call of @('intersectp') depends on the test.  In all
 cases, both arguments must satisfy @(tsee true-listp).  If the test is @(tsee
 eql), then one of the arguments must satisfy @(tsee eqlable-listp).  If the
 test is @(tsee eq), then one of the arguments must satisfy @(tsee
 symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('intersectp') and its variants:</p>

 <blockquote><p>@('(intersectp-eq x lst)') is equivalent to @('(intersectp x
 lst :test 'eq)');</p>

 <p>@('(intersectp-equal x lst)') is equivalent to @('(intersectp x lst :test
 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('intersectp-equal').</p>

 @(def intersectp-equal)")

(defxdoc introduction-to-a-few-system-considerations
  :parents (introduction-to-the-theorem-prover)
  :short "The mechanics of interaction with the theorem prover"
  :long "<p>ACL2 is implemented in Common Lisp.  There are many different
 Common Lisps and they differ in details relating to interacting with the
 system.  We sometimes refer to the host Common Lisp as ``raw Lisp.''  The new
 user is advised not to operate in raw Lisp as it is possible to, say, redefine
 ACL2 system facilities like @('defthm').</p>

 <p>Most people use Emacs (see @(see Emacs) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>) or
 the ACL2 Sedan (Eclipse) interface (see @(see ACL2-Sedan) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>).
 They provide protection against certain common mistakes, e.g., trying to edit
 a block of input text after the operating system has buffered it up and sent
 it to the Lisp reader which is parsing it as you type.  More on this below.
 In addition, the Sedan provides helpful syntax checking and a disciplined
 approach to the stack of lemmas generated by The Method.  But the variety of
 interfaces to the variety of Lisps mean that there is great variation in what
 one must type to interact with ACL2.</p>

 <p>The best example is perhaps trying to interrupt a running proof.  For most
 host Common Lisp implementations, if you are typing directly to the Common
 Lisp process, then you can interrupt a computation by typing ``ctrl-c'' (hold
 down the Control key and hit the ``c'' key once).  If you are typing to an
 Emacs process which is running ACL2 in a shell buffer, you should type ctrl-c
 ctrl-c.  If you are running the ACL2 Sedan, you can use the <i>Interrupt
 Session</i> button on the tool bar.  The environment you enter when you
 interrupt depends on various factors and normally, you will be put back into
 the top level ACL2 command loop.  If not, then you may be in a Lisp break, and
 you can probably get back into the ACL2 command loop by using an ``abort''
 command that depends on the host Common Lisp (e.g., @(':q') for GCL and CCL).
 You can usually determine what environment you're in by paying attention to
 the prompt, which we discuss below.</p>

 <p>The ACL2 ``interactive loop'' is called @(tsee LP) (<see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 and is generally invoked automatically from your Common Lisp when you start up
 the ACL2 process.  @('LP') is just a special case of an ACL2 function called
 @(tsee LD) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>, which the user can call from within the ACL2
 interactive loop to enter the loop recursively.  New users don't have to know
 this except that it helps explain why some commands have the string
 ``@('-ld-')'' in their names!</p>

 <p>ACL2 presents itself as a ``read-eval-print'' loop: you're repeatedly
 prompted for some type-in, which is read, evaluated, and may cause some
 printing.  The prompt tells you something about ACL2's state.  In the standard
 environment, the prompt is</p>

 @({
  ACL2 !>
 })

 <p>The ``@('ACL2')'' tells you that the symbols you use in your command are
 those defined in the standard ACL2 namespace (or, in the jargon of Lisp, the
 ``current package,'' see @(see current-package) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>).
 You could create a new namespace (see @(see defpkg) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 and set the current package to it (see @(see in-package) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>).
 The next part of the prompt above
 (``@('!')''), the exclamation mark) tells you that before ACL2 evaluates your
 type-in it will check to see whether @(tsee guard)s (<see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 are respected, i.e., whether the functions used in your command are being
 supplied arguments in their ``expected domains.''  If evaluation is allowed by
 the guards, it proceeds exactly according to the ACL2 axioms; if evaluation is
 not allowed, an error is signaled.  ACL2 event commands check their arguments
 thoroughly at run-time, regardless of Lisp's notion of ``expected
 domains.''</p>

 <p>If the exclamation mark is missing from the prompt,</p>

 @({
  ACL2 >
 })

 <p>then evaluation occurs strictly according to the ACL2 axioms, without
 regard for any declared guards.</p>

 <p>You can switch between these two prompts by typing</p>

 @({
  ACL2 !>:set-guard-checking nil
 })

 <p>to turn guard checking off and</p>

 @({
  ACL2 >:set-guard-checking t
 })

 <p>to turn it on.  Try typing @('(car 7)') to each prompt.</p>

 <p>If there is a ``@('p')'' in the prompt,</p>

 @({
  ACL2 p!>
 })

 <p>with or without the exclamation mark:</p>

 @({
  ACL2 p>
 })

 <p>it means you are in @(':')@(tsee program) (<see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 mode rather than @(':')@(tsee logic) (<see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 mode.  In @(':program') mode, @('defun') just defines Common Lisp programs
 that you can evaluation but it adds no axioms and you cannot use such defined
 functions in theorems or invoke @('defthm').  @(':Program') mode is often used
 to prototype a model.</p>

 <p>Most commands are just typical parenthesized Lisp expressions, like</p>

 @({
  ACL2 !>(defthm rev-rev
           (implies (true-listp x)
                    (equal (rev (rev x)) x)))
 })

 <p>but some are typed as keywords followed by a certain number of
 arguments.</p>

 <p>For example, to undo the last event you may type</p>

 @({
  ACL2 !>:u
 })

 <p>or to undo back through the introduction of @('rev') you may type</p>

 @({
  ACL2 !>:ubt rev
 })

 <p>The first is equivalent to evaluating @('(u)') and the second is equivalent
 to evaluating @('(ubt 'rev)').  See @(see keyword-commands) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>.
 So if you see a sentence like ``to turn on the break rewrite facility, execute
 @(':brr t'),'' we mean type</p>

 @({
  ACL2 !>:brr t
 })

 <p>or equivalently</p>

 @({
  ACL2 !>(brr t)
 })

 <p>If you see a prompt that doesn't look like those above you are probably not
 typing commands to the standard ACL2 read-eval-print loop!  If you've somehow
 called @('LD') recursively, the prompt ``gets deeper,'' e.g.,</p>

 @({
  ACL2 !>>
 })

 <p>and you can pop out one level with @(':')@(tsee q) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 (for ``quit'') or pop to the outermost ACL2 loop with @(':')@('abort!') <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>.
 If you are in the outermost call of the ACL2 interactive loop and you type
 @(':q'), you pop out into raw lisp.  The prompt there is generally different
 from the ACL2 prompt but that is outside our our control and varies from Lisp
 to Lisp.  We have arranged for many (but not all) Lisps to use a raw lisp
 prompt involving the string @('\"[RAW LISP]\"').  To get back into the ACL2
 interactive loop from raw lisp, evaluate @('(LP)').</p>

 <p>If you see a prompt that looks like an ACL2 prompt but has a number in
 front of it, e.g.,</p>

 @({
  1 ACL2 >
 })

 <p>then you're talking to the break rewrite facility (and you are 1 level deep
 in the example above).  Presumably at earlier time in this session you enabled
 that facility, with @(':brr t'), installed a monitor on some rule, invoked the
 prover, entered the break, and forgot.  Everything you have done (e.g., lemmas
 you might have proved with @('defthm')) inside that break will be lost when
 you exit the break.</p>

 <p>Since the break rewrite facility is ``ours'' we can tell you how to exit
 it!  To exit our breaks and return to the top-level ACL2 loop, execute
 @(':')@(tsee abort!).</p>

 <p>If you discover you've been working in a @('brr') break, exit, turn off the
 break facility with @(':brr nil'), and redo whatever @('defun')s and
 @('defthm')s you did while in that break.</p>

 <p>Users of the Emacs interface may occasionally type commands directly in the
 @('*shell*') buffer running ACL2.  This can be ``dangerous'' for two reasons.
 One is that if you type an event, like a @('defun') or @('defthm'), directly
 to the shell, it will not be recorded in your ``script'' buffer and you may
 forget it in your final script.  The other is that if you attempt to edit a
 multi-line command on any but the most recent line, e.g., to correct the
 spelling of @('defthm') below after you've typed the ``@('(implies (true-listp
 x)')'' you will confuse the Lisp parser because it has already read
 ``@('(defthm rev-rev')''.</p>

 @({
  ACL2 !>(defthm rev-rev
           (implies (true-listp x)
 })

 <p>This usually provokes the raw Lisp to enter a low level error break from
 which you must abort, possibly reenter the ACL2 loop, and re-type the
 corrected command from scratch.</p>

 <p>Another common mistake when using interfaces other than the ACL2 Sedan is
 to type an ill-formed ACL2 expression containing dots or commas, which also
 often provokes a break into the raw Lisp's error handler.</p>

 <p>The fundamental lesson is that you should pay attention to the prompt and
 learn what the different prompts mean &mdash; or use the ACL2 Sedan.</p>

 <p>If you have been working your way through the tutorial introduction to the
 theorem prover, use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-the-theorem-prover).</p>")

(defxdoc introduction-to-hints
  :parents (introduction-to-the-theorem-prover)
  :short "How to provide hints to the theorem prover"
  :long "<p>We assume you've read @(see introduction-to-rewrite-rules-part-1),
 @(see introduction-to-key-checkpoints), and @(see
 introduction-to-the-database).</p>

 <p>You may give the theorem prover a hint that is specific to a particular
 subgoal generated during a proof attempt.  Of course, you learn the name of
 the subgoal by inspecting the key checkpoints or other proof output.  You are
 not expected to anticipate the need for hints at specific subgoals; instead,
 you usually deduce that a hint is required because the subgoals is not proved
 but you see that existing rules and context make it provable.</p>

 <p>The most common hint is to enable and/or disable a particular rule on some
 particular subgoal.</p>

 <code>
 (defthm <i>name</i>
         <i>formula</i>
         :hints ((\"Subgoal *1/3.2''\" :in-theory (disable nth-nthcdr))))
 </code>

 <p>The hint above tells the rewriter that just before it begins to work on
 @('Subgoal *1/3.2''') it should switch to a local theory in which all of the
 rules generated from the event @('nth-nthcdr') are disabled.  That local
 theory remains the one in use for all descendant subgoals generated from the
 one named, until and unless one of those descendant subgoals has an
 @(':in-theory') hint associated with it.  There are many kinds of hints
 besides @(':in-theory') and in general, after each subgoal name, you can give
 various forms of advice and list various adjustments you wish to make to the
 context in which the prover is operating when it begins addressing the subgoal
 named.</p>

 <p>The top-level goal is always named @('Goal').  Thus</p>

 <code>
 (defthm <i>name</i>
         <i>formula</i>
         :hints ((\"Goal\" ...<i>hints1</i>...)
                 (\"Subgoal *1/3.2''\" ...<i>hints2</i>...)))
 </code>

 <p>has the effect of using <i>hints1</i> for the top-level goal and all of its
 children throughout the entire proof, except for @('Subgoal *1/3.2''') and its
 children, where <i>hints2</i> is used instead.</p>

 <p>There are a few hints which ``take effect'' exactly on the subgoal to which
 they are attached and are not inherited by their descendents.</p>

 <p>Here is an incomplete list of some of the more common hints; we note the
 ones that do not pass on their effects to their descendants.  We recommend
 that you not follow the advanced links (marked ``<see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>'')
 below until you have read the entire tutorial.</p>

 <p>See @(see in-theory) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for how to enable and/or disable rules.  The new
 theory is computed by a ``theory expression'' (see @(see theories) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 such as @('(disable nth-nthcdr)') and typically makes adjustments such as
 additions or deletions to the global current theory.  All the relevant new
 theories are computed before the proof begins.  Thus, in</p>

 <code>
 (defthm <i>name</i>
         <i>formula</i>
         :hints ((\"Goal\" :in-theory (disable rule1))
                 (\"Subgoal *1/3.2''\" (disable rule2))))
 </code>

 <p>the theory mentioned for @('Goal') is the global current theory minus
 @('rule1'), while the theory mentioned for its descendant, @('Subgoal
 *1/3.2'''), is the global current theory minus @('rule2').  In particular, if
 both @('rule1') and @('rule2') are enabled in the global current theory, then
 @('rule1') is enabled during the processing of @('Subgoal *1/3.2''') because
 it was not removed explicitly there.</p>

 <p>See @(see use) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for how to force the theorem prover to
 take note of particular instances of particular theorems; in particular, the
 instances are created and added as hypotheses to the subgoal in question.  The
 hint is not inherited by the descendants of the subgoal (since the formula
 being proved has been modified by the hint).  If the rule you are using (with
 a @(':use') hint) is an enabled rewrite rule, it might interfere with the
 added hypothesis &mdash; by rewriting itself to @('T') &mdash; and thus often
 you will both @(':use ...')  and @(':in-theory (disable ...)').</p>

 <p>See @(see expand) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for how to tell the theorem prover to expand one or
 more function calls whenever encountered.</p>

 <p>See @(see cases) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for how to force the theorem prover to do a case
 split to prove the subgoal under each of an exhaustive list of cases given in
 the hint.  This hint takes action specifically at the named subgoal and is not
 passed down to its children.</p>

 <p>See @(see induct) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for how to tell the theorem prover to go
 immediately into induction for the subgoal in question, and to use the
 induction scheme suggested by the hint rather than the one suggested by the
 terms in the subgoal itself.  This hint is not inherited by its
 descendents.</p>

 <p>See @(see hints) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for a complete list of all hints, and see @(see
 hints-and-the-waterfall) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for a more thorough description of how the effects
 of hints at a subgoal are inherited by the descendents.</p>

 <p>If you are reading this as part of the tutorial introduction to the theorem
 prover, use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-the-theorem-prover).</p>")

(defxdoc introduction-to-key-checkpoints
  :parents (introduction-to-the-theorem-prover)
  :short "What questions to ask at key checkpoints"
  :long "<p>We assume you've read about rewrite rules; see @(see
 introduction-to-rewrite-rules-part-1).</p>

 <p>When a proof attempt fails, ACL2 prints some <i>key checkpoints</i>.  These
 are formulas that we think you should look at.  There are two kinds printed:
 key checkpoints <i>before an induction</i>, and key checkpoints <i>under a
 top-level induction</i>.  (Key checkpoints under deeper inductions and
 checkpoints that aren't considered ``key'' may exist in the proof attempt, but
 ACL2 doesn't print them at the end of failed proofs because you shouldn't be
 distracted by them.)</p>

 <p>Below is a list of questions to ask yourself about the key checkpoints.
 Initially, we recommend just picking one key checkpoint <i>before</i> an
 induction (perhaps the simplest looking one) and asking these questions.
 These questions may lead you to look at other key checkpoints.  As you gain
 more experience you'll elaborate and generalize this advice.</p>

 <p><b>(1) Do you believe this formula is a theorem?</b> If you don't think it
 is, it's pointless to try to prove it!  You should reconsider your top-level
 formula in light of the special case suggested by this key checkpoint.</p>

 <p><b>(2) Can it be simplified?</b> Is there some combination of function
 symbols in it that could be eliminated or simplified by exploiting some
 simpler fact?  By a ``simpler fact'' we mean a theorem about a few of the
 symbols in this formula.  For an example of this see @(see
 dealing-with-key-combinations-of-function-symbols).  Don't think about the
 deep question ``how can I prove the checkpoint?'' until you've got it into its
 simplest form.</p>

 <p><b>(3) Is the simpler fact already in the database?</b> If there is some
 simpler fact that would help clean up the checkpoint but you believe the
 simpler fact is already in the database, you can use @(':')@(tsee pl) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>,
 @(':')@(tsee pc) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>, @(':')@(tsee pbt) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>,
 and other <i>history</i> commands to inspect the database; (see @(see history)
 <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>).  But if you find the allegedly relevant simpler
 fact in the database, you must ask: <b>why wasn't it used?</b> There are four
 principal reasons:</p>

 <p>(3a) it is disabled &mdash; so enable it; you'll learn how when you read
 the coming sections on @(see introduction-to-the-database) and @(see
 introduction-to-hints).</p>

 <p>(3b) its left-hand side doesn't match the target &mdash; so improve the
 rule by generalizing its left-hand side or prove a new rule for this
 situation; if you decide to remove the old rule from the database, see
 <i>undo</i> commands in @(see history) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p>(3c) it is an @('IFF') rule but the target doesn't occur propositionally
 &mdash; so see if you you can strengthen the rule to an @('EQUAL') rule or
 weaken the context of the target by changing the conjecture to use the target
 propositionally; if you decide to remove the old rule from the database, see
 <i>undo</i> commands in @(see history) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p>(3d) the hypotheses of the rule cannot be relieved for this occurrence of
 the target; this can be caused by the rule's hypotheses being too strong
 (requiring more than they should), or by the hypotheses of the current
 conjecture being too weak (you forgot some key hypothesis), or by ACL2 not
 having the rules it needs to prove that the conjecture's hypotheses really do
 imply the rule's.  Tools are available (@(':')see @(see brr) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 help you figure out why the rule failed, so use them and improve the rule, or
 the current conjecture, or the database as appropriate.</p>

 <p><b>(4) If the simpler fact is not already known, prove it.</b> This means
 you must create a new @('defthm') event with appropriate <i>rule-classes</i>
 to store your new theorem so that it will be used.  See @(see
 dealing-with-key-combinations-of-function-symbols).  Then you must start using
 The Method recursively to prove your new lemma.</p>

 <p><b>(5) Otherwise, is this formula something you'd prove by induction?</b>
 If you can't simplify it, it may be because you ``need this fact to prove this
 fact,'' in which case, induction is the right thing to do.  But first,
 remember that in order for a formulas to be provable by induction, it must be
 very general.  Why must it be general?  Because in an inductive proof, the
 main thing you have to work with is the induction hypothesis, which is an
 instance of the theorem you're proving.  If the theorem is not general enough,
 you won't be able to assume an instance that will help you.  ACL2 may try
 induction even on formulas that are not general enough.  Don't assume that the
 formula is ripe for induction just because ACL2 found an induction to do!
 Before you ``approve'' a formula for induction, ask whether it is perhaps a
 special case of some more general theorem.  See @(see
 generalizing-key-checkpoints) now and then come back here.  If you found a
 generalization, you should probably be proving that formula instead of this
 one.  So formulate the appropriate @('defthm') and use The Method recursively
 to prove it.</p>

 <p><b>(6) If the formula is right for induction, did ACL2 do an induction for
 it?</b> You can answer that without looking at the proof.  Just see if there
 are any key checkpoints after induction.  If not, why didn't ACL2 induct?
 Perhaps you told ACL2 not to induct!  Perhaps no term in the conjecture
 suggests an appropriate induction?  You could remedy this by extending ACL2's
 induction analysis by adding to the database.  Or you could just tell ACL2
 what induction to do for this formula.  You'll learn about both later (when
 you read coming sections of the tutorial).</p>

 <p><b>(7) If ACL2 did do an induction, was it the right one?</b> You can find
 the induction scheme used by reading the first induction message in the output
 log after you submitted the conjecture to ACL2.  But most often you will
 realize the ``wrong'' induction was done just by looking at the post-induction
 key checkpoints, keeping in mind that each is supposed to be a natural special
 case of the theorem you're proving.  Is the case analysis inappropriate?  Are
 induction hypotheses missing?  If so, you should look at the induction scheme.
 If you determine the wrong induction was done, extend ACL2's induction
 analysis or tell it which induction to do, which you'll learn about in the
 coming sections of the tutorial.  For more advice about looking at
 post-induction key checkpoints, see @(see post-induction-key-checkpoints) now
 and then come back here.</p>

 <p><b>(8) If the post-induction key checkpoints seems plausible,</b> <b>then
 repeat the questions above for each one of them,</b> <b>perhaps starting with
 the simplest.</b></p>

 <p>In any case, after successfully taking whatever action you've decided on,
 e.g., proving some new lemma and adding it as a rule:</p>

 <p><b>Start over trying to prove your main conjecture.</b> This is important!
 Do not just scroll back to the key checkpoints generated the last time you
 tried to prove it.  Instead, re-generate them in the context of your new,
 improved database and hints.</p>

 <p>You will be following this general outline almost all of the time that
 you're interacting with ACL2.  You will not often be asking ``Why is ACL2
 making me think about this subgoal?  What did ACL2 do to get here?  How does
 ACL2 work?''</p>

 <p>Two other ideas are helpful to keep in mind.</p>

 <p><b>Is a key checkpoint unexpectedly complicated?</b> Pay special attention
 to the case where the complication seems to be the introduction of low-level
 details you thought you'd dealt with or by the introduction of symbols you
 didn't expect to see in this proof.  These can be signs that you ought to
 disable some rules in the database (e.g., a definition of a complicated
 function about which you've proved all the necessary lemmas or some lemma that
 transforms the problem as was appropriate for some other proof).</p>

 <p><b>Does the theorem prover just hang up, printing nothing?</b> If this
 happens, you must interrupt it.  How you interrupt the prover is dependent on
 which Common Lisp and which interface you're using.  But most Common Lisps
 treat control-c as a console interrupt.  If you're in Emacs running ACL2 as a
 shell process, you must type control-c control-c.  If you're in ACL2s, hit the
 <i>Interrupt Session</i> button.  Interrupting ACL2 can leave you in an
 interactive loop similar in appearance but different from ACL2's top-level!
 So pay careful attention to the prompt and see @(see breaks) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p>Once you've regained control from the ``runaway'' theorem prover, there are
 several tools you can use to find out what it is doing in real-time.
 Generally speaking, when the theorem prover goes silent for a very long time
 it is either in some kind of rewrite loop caused by rules that cause it to
 flip back and forth between various supposedly normal forms, or else it has
 split the problem into a huge number of cases and suffering a combinatoric
 explosion.  See @(see DMR) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 and, perhaps, see @(see accumulated-persistence) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p>If you are reading this as part of the tutorial introduction to the theorem
 prover, use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-the-theorem-prover).</p>")

(defxdoc introduction-to-rewrite-rules-part-1
  :parents (introduction-to-the-theorem-prover)
  :short "Introduction to ACL2's notion of rewrite rules"
  :long "<p>Rewrite rules make ACL2 replace one term by another.  This is done
 by the rewriter, which is part of ACL2's simplifier.  The rewriter sweeps
 through the goal formula trying all the rewrite rules it knows.  Here's an
 example.  Just pretend that you have made a rewrite rule from the formula
 below.</p>

 @({
  (implies (and (natp i)
                (< i (len a)))
           (equal (put i v (append a b))
                  (append (put i v a) b)))
 })

 <p>Then every time the rewriter sees a target term that <i>matches</i></p>

 @({
  (put i v (append a b))
 })

 <p>it considers the rule, with the variables @('i'), @('v'), @('a'), and
 @('b') of the rule <i>bound</i> to whatever terms matched them in the target,
 say the terms <i>i</i>, <i>v</i>, <i>a</i>, and <i>b</i>.  To consider the
 rule, the rewriter first tries to establish (``relieve'') the hypotheses.  In
 particular, it rewrites:</p>

 <code>
 (natp <i>i</i>)           ; <i>hyp 1</i>
 </code>

 <p>and</p>

 <code>
 (&lt; <i>i</i> (len <i>a</i>)). ; <i>hyp 2</i>
 </code>

 <p>If both hypotheses rewrite to true, then the rule <i>fires</i> and replaces
 the target by:</p>

 <code>
 (append (put <i>i</i> <i>v</i> <i>a</i>) <i>b</i>).
 </code>

 <p>In short, rewrite rules direct ACL2 to rearrange the terms in the goal
 formulas.</p>

 <p>We are more precise later, but for now we turn to the question of how do
 you make a rewrite rule from a formula?  The answer is, you prove the formula
 with the @('defthm') command.  Recall that</p>

 <code>
 (defthm <i>name</i>
         <i>formula</i>
         ...)
 </code>

 <p>commands ACL2 to try to prove <i>formula</i> and, if successful, build it
 into the database as a rule according to your specification in the
 <i>rule-classes</i> argument of the ... part of the command.</p>

 <p>To make it easy for you to generate rewrite rules, @('defthm') has a simple
 heuristic: if you don't tell it what kind of rule to generate from
 <i>formula</i>, it generates a rewrite rule!  Thus, if this command</p>

 <code>
 (defthm <i>name</i>
         <i>formula</i>)
 </code>

 <p>is successful, ACL2 will have a new rewrite rule in the database, even
 though you did not <i>explicitly</i> tell it to add a rule.</p>

 <p>A common mistake for new users is to forget that the above command adds a
 rewrite rule.  This often results in a tangle of rules that lead nowhere or to
 infinite rewriting that you will have to interrupt.  It is also good to
 remember that the command <i>only</i> adds a rule.  It does not magically make
 ACL2 aware of all the mathematical consequences of the formula: it just makes
 a rewrite rule.</p>

 <p>When you prove a theorem with @('defthm') you are <i>programming</i> ACL2.
 Being careless in your statement of lemmas is tantamount to being careless in
 your programming.</p>

 <p>ACL2 can generate rewrite rules from formulas that look like this:</p>

 <code>
 (IMPLIES (AND <i>hyp1</i> ... <i>hypk</i>)
          (<i>eqv</i> <i>lhs</i> <i>rhs</i>))
 </code>

 <p>where <i>eqv</i> is either @('EQUAL') or @('IFF'), and <i>lhs</i> is not a
 variable symbol, not a constant, and not a call of the function @('IF'), and
 not a call of an abbreviation (``macro'') that expands to any of these.  So
 illegal <i>lhs</i> include @('X'), @('0'), @('(IF X Y Y)'), and @('(OR p q)').
 The last is illegal because @('OR') is just an abbreviation for a certain
 @('IF')-expression.</p>

 <p>Technical Note: This tutorial introduction to the theorem prover takes
 liberties with the truth!  We are trying to give you a useful predictive model
 of the system without burdening you with all the details, which are discussed
 in the ACL2 User's Manual.  For example, using directives in the rule-classes
 you can rearrange the proved formula into the form you want your rule to take,
 and you can make ACL2 take advantage of equivalence relations <i>eqv</i> other
 than just @('EQUAL') and @('IFF').  But we'll ignore these fine points for
 now.</p>

 <p>We call the <i>hyp</i> terms the <i>hypotheses</i> of the rule.  We call
 <i>lhs</i> the <i>left-hand side</i> of the rule, and we call <i>rhs</i> the
 <i>right-hand side</i> of the rule.  If the conclusion of the rule is an
 @('EQUAL') term we call it an <i>equality</i> rule.  Otherwise, it is a
 <i>propositional equivalence</i> rule.  If there are no hypotheses,
 <i>k</i>=0, we say the rule is an <i>unconditional</i> rewrite rule; otherwise
 it is <i>conditional</i>.</p>

 <p>ACL2 allows several special cases of the shapes above.  See @(see
 special-cases-for-rewrite-rules), but come back here and continue.</p>

 <p>A rewrite rule makes ACL2 seek out occurrences of terms that match the
 left-hand side of the rule and replace those occurrences using the right-hand
 side, provided all the hypotheses rewrite to true in the context of the
 application of the rule.</p>

 <p>That is, the left-hand side is treated as a <i>pattern</i> that triggers
 the rule.  The hypotheses are <i>conditions</i> that have to be proved in
 order for the rule to fire.  The right-hand side is the <i>replacement</i> and
 is put into the formula where the pattern occurred.</p>

 <p>Now for some clarifications. ACL2 only considers enabled rules.  And ACL2
 will use a propositional rule to replace a target only if the target occurs in
 a propositional place in the formula.  Generally that means it occurs in the
 argument of a propositional connective, like @('AND'), @('OR'), @('NOT'),
 @('IMPLIES'), and @('IFF'), or in the test of an @('IF').  When we say that
 the left-hand side of the rule must <i>match</i> the target we mean that we
 can instantiate the variables in the rule to make the left-hand side identical
 to the target.  To <i>relieve</i> or establish the hypotheses of the rule,
 ACL2 just applies other rewrite rules to try to prove the instantiated
 hypotheses from the assumptions governing the occurrence of the target.  When
 ACL2 replaces the target, it replaces it with the instantiated right-hand side
 of the rule and then applies rewrite rules to that.</p>

 <p>If a hypothesis has variables that do not occur in the left-hand side of
 the rule, then the pattern matching process won't find values for those
 variables.  We call those <i>free variables</i>.  They must be instantiated
 before ACL2 can relieve that hypothesis.  To instantiate them, ACL2 has to
 guess values that would make the hypothesis true in this context, i.e., true
 given the assumptions of the goal theorem.  So if you're trying to prove</p>

 @({
  (IMPLIES (AND (TRUE-LISTP A)
                (MEMBER (CAR P) A)
                (MEMBER (CDR P) A))
           ...)
 })

 <p>and the target you're rewriting is in the ``...'' part of the formula, the
 rewriter knows that @('(TRUE-LISTP A)') @('(MEMBER (CAR P) A)') and @('(MEMBER
 (CDR P) A)') are true.  So if a rewrite rule is considered and the rule has
 @('(member e x)') as a hypothesis, where @('e') is a free variable but @('x')
 was bound to @('A') in the pattern matching, then it will guess that @('e')
 must be @('(CAR P)') or @('(CDR P)'), even though there are many other
 possibilities that would make @('(MEMBER e A)') true.  Of course, whatever
 guess it makes must also satisfy all the other hypotheses that mention @('e')
 in the rule.  It simply isn't very imaginative at guessing!</p>

 <p>The most predictable rewrite rules have no free variables.  You can add
 pragmatic advice to help ACL2 with free variables, telling it to try all the
 possibilities it finds, to try just the first, or even to compute a
 ``creative'' guess.</p>

 <p>It is possible to make the rewriting process loop forever, e.g., by
 rewriting <i>alpha</i> to <i>beta</i> with one set of rules and rewriting
 <i>beta</i> to <i>alpha</i> with another.  Even a single rule can make the
 process loop; we'll show you an example of that later in the tutorial.  ACL2
 can handle commutativity rules without looping.  It uses @('(equal (+ x y) (+
 y x))') to replace @('(+ B A)') by @('(+ A B)'), but not vice versa.  (It is
 sensitive to alphabetic ordering when dealing with <i>permutative</i>
 rules.)</p>

 <p>Logically equivalent formulas can generate radically different rewrite
 rules!  Rearranging the propositional structure of the formula or swapping the
 left and right sides of an equality &mdash; while having no effect on the
 mathematical meaning of a formula &mdash; can have a drastic impact on the
 pragmatic meaning as a rule.  To see an illustration of this, see @(see
 equivalent-formulas-different-rewrite-rules).</p>

 <p>Developing an effective set of rewrite rules is key to success at using
 ACL2.  We'll look more at this later in the tutorial.</p>

 <p>If you are working your way through the tutorial for the theorem prover,
 use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-the-theorem-prover).  If you are reading just about how to
 make effective rewrite rules, go on to @(see
 introduction-to-rewrite-rules-part-2).</p>")

(defxdoc introduction-to-rewrite-rules-part-2
  :parents (introduction-to-the-theorem-prover)
  :short "How to arrange rewrite rules"
  :long "<p>You should design your rewrite rules to canonicalize the terms in
 your problem, that is, your rules should drive terms into some normal form so
 that different but equivalent terms are rewritten into the preferred shape,
 making equivalent terms identical.  You are very familiar with this idea from
 algebra, where you learned to normalize polynomials.  Thus, when you see
 <i>(2x + 6)(3x - 9)</i> you automatically normalize it, by ``multiplying out
 and collecting like terms,'' to get <i>(6x^2 - 54)</i>.  This normalization
 strategy allows you to recognize equivalent terms presented differently, such
 as <i>6(x^2 - 9)</i>.</p>

 <p>The ACL2 user is responsible for making up the rules.  (Standard ``books''
 &mdash; files of ACL2 definitions and theorems &mdash; can often provide rules
 for some sets of functions, e.g., arithmetic.)  This is a heavy burden on you
 but it means you are in charge of your own normal forms.  For example, if you
 use the function @('nthcdr'), which returns the @('n')th @('cdr') of a list,
 you might see both @('(cdr (nthcdr i x))') and @('(nthcdr i (cdr x))').  These
 two expressions are equivalent but not identical.  You will want to decide
 which you want to see and prove the rewrite rule that converts the other to
 that preferred form.</p>

 <p>Most good users develop an implicit ordering on terms and rewrite ``heavy''
 terms to ``lighter'' ones.  This insures that there are no loops in their
 rewrite rules.  But this ordering changes according to the user and the
 problem.</p>

 <p>Generally, the lightest terms are primitives such as @('IF'), @('EQUAL'),
 arithmetic, etc.  Functions defined without explicit recursion tend to be
 ignored because they are just expanded away (but see below).  Recursively
 defined functions tend to be heavier than any other recursive function used in
 their definitions, so, for example, if @('rev') is defined in terms of
 @('append'), @('rev') is heavier than @('append').  But the size and subtlety
 of recursively defined functions also affects their place in the ordering.</p>

 <p>But rewrite rules are surprisingly subtle.  Recall that a rewrite rule can
 be made from a formula of this form:</p>

 <code>
 (IMPLIES (AND <i>hyp1</i> ... <i>hypk</i>)
          (<i>eqv</i> <i>lhs</i> <i>rhs</i>))
 </code>

 <p>where <i>eqv</i> is either @('EQUAL') or @('IFF'), and <i>lhs</i> is a call
 of a function other than @('IF').  In such a rule, <i>lhs</i> is the pattern
 responsible for triggering the rule, the <i>hypi</i> are conditions which must
 be satisfied by the context of the target being rewritten, and <i>rhs</i> is
 the replacement.  The replacement only happens if the rule is enabled, the
 pattern matches, the conditions are satisfied, and (in the case of an @('IFF')
 rule) the target occurs propositionally.  There are other heuristic
 restrictions that we won't discuss here.</p>

 <p>So how should you phrase a theorem in order to make it an effective
 rule?</p>

 <p>General Principles:</p>

 <p>* <b>Strengthen the Formula</b>: The fewer hypotheses a formula has the
 better the rewrite rule formed from it.  The more general the left-hand side
 the better the rule.  The fewer free variables in the hypothesis, the better.
 The idea is to form a rule that fires predictably.  Later in this tutorial
 you'll get some practice formulating strong rules.</p>

 <p>* <b>Choosing the Conclusion</b>: If a lemma is an implication, you have to
 choose what the conclusion will be. (You'll also have to ``orient'' that
 conclusion by choosing a left-hand side and a right-hand side, but we discuss
 that below).  You can swap the conclusion and any hypothesis by negating both,
 producing a different conclusion.  There are generally two (possibly
 conflicting) heuristics for deciding which part of the formula should be the
 conclusion:</p>

 <p><i>Choosing the Conclusion Heuristic 1</i>: Can you make the conclusion be
 an @('EQUAL') or @('IFF') expression that has a ``heavy term'' on one side?
 That will make a rule that replaces the heavy term with a lighter one.  We
 discuss this situation more below.</p>

 <p><i>Choosing the Conclusion Heuristic 2</i>: Can you make the conclusion be
 a non-propositional term that contains all the variables mentioned in the
 hypotheses?  By ``non-propositional'' we mean a term that is not just the
 propositional combination (e.g., with @('AND') or @('OR')) of other terms but
 instead some call of some ``heavy'' function?  If your conclusion contains all
 the variables mentioned in the hypotheses, matching it will instantiate all
 the variables in the hypotheses.  That way ACL2 will not have to guess
 instantiations of unbound variables when it tries to relieve the hypotheses.
 It is not very good at guessing.</p>

 <p>* <b>Orienting the Conclusion</b>: If the conclusion is an @('EQUAL') or an
 @('IFF'), you have to decide which is the left-hand side and which is the
 right.  If the conclusion is @('(NOT') <i>lhs</i>@(')'), then the left-hand
 side is <i>lhs</i> and the right-hand side is @('NIL').  If the conclusion is
 not an @('EQUAL'), an @('IFF'), or a @('NOT') then the conclusion itself will
 be the left-hand side and the right-hand side will be @('T').  If your lemma
 was created by looking at Key Checkpoints while using The Method, the
 left-hand side should match some term in that checkpoint.</p>

 <p>Remember, the left-hand side is the ``trigger'' that will make the rule
 fire.  It is the pattern that ACL2 will be looking for.</p>

 <p>* <b>Pay attention to the free variables</b>: Look at the variables that
 occur in the pattern (the left-hand side) and compare them to the variables
 that occur in the hypotheses.  Does some hypothesis contain a variable, say
 <i>v</i>, that is not in the pattern?  We call <i>v</i> a <i>free variable</i>
 because it will not be assigned a value (``bound'') by the process of pattern
 matching.  ACL2 will have to guess a value for <i>v</i>.  If some hypothesis
 contains <i>v</i> as a free variable, ask whether more than one hypothesis
 contains <i>v</i>?  ACL2 uses the first hypothesis containing a free <i>v</i>
 to guide its guess for <i>v</i>.  To ``guess'' a value for <i>v</i>, ACL2 uses
 that hypothesis as a pattern and tries to match it against the assumptions in
 the checkpoint formula being proved.  This means that key hypothesis must be
 in normal form, to match the rewritten assumptions of the goal.  It also means
 that you should reorder the hypotheses to put the most unusual hypothesis
 containing a free <i>v</i> first in the list of conjuncts.  For example, if
 @('v') is free in two hypotheses, @('(natp v)') and @('(member (nthcdr v a)
 b)'), then we recommend putting the @('member') term first.  There are likely
 to be many terms in the goal satisfying the @('natp') hypothesis &mdash; or
 none if @('natp') has expanded to an integer inequality &mdash; while there
 are likely to be few terms satisfying the @('member') hypothesis, especially
 if @('a') and @('b') are bound by the left-hand side of the rule.</p>

 <p>Here are some (possibly conflicting) heuristics for choosing the left-hand
 side:</p>

 <p><i>Choose a Left-Hand Side that Occurs in a Key Checkpoint</i>: If you use
 the Method you will tend to do this anyway, because you'll see terms in the
 Key Checkpoints that you want to get rid of.  But many moderately experienced
 users ``look ahead'' to how the proof will go and formulate a few anticipatory
 rules with the idea of guiding ACL2 down the preferred path to the proof.
 When you do that, you risk choosing left-hand sides that won't actually arise
 in the problem.  So when you formulate anticipatory rules, pay special
 attention to the functions and terms you put in the left-hand sides.  The next
 few paragraphs deal with specific cases.</p>

 <p><i>Avoid Non-Recursive Functions in the Left-Hand Side</i>: If the
 left-hand side contains a call of a defined function whose definition is not
 recursive, then it will almost never match any target in the formula being
 rewritten unless the function is disabled.  Suppose for example you have
 defined @('SQ') so that @('(SQ x)') is @('(* x x)').  Suppose you considered
 choosing a left-hand side like @('(+ (SQ x) (SQ y))').  Suppose you hoped it
 would hit the target @('(+ (SQ A) (SQ B))') in some formula.  But when ACL2
 simplifies the formula, it will first rewrite that target to</p>

 @({
  (+ (* A A) (* B B))
 })

 <p>by expanding the definition of @('SQ'), since it could do so without
 introducing any recursive calls.  But now the target won't match your rule.
 By choosing a left-hand side that occurs in a Key Checkpoint (and is not one
 of a handful of abbreviations ACL2 uses in its output like @('AND'),
 @('NOT')), you'll avoid this problem since @('SQ') will have already been
 expanded before the Key Checkpoint is printed.</p>

 <p><i>Disable Non-Recursive Functions</i>: If you insist on a left-hand side
 that contains calls of non-recursive functions, remember to disable those
 non-recursive functions after you've proved all the rules you want about them.
 By disabling @('SQ') you can prevent ACL2 from expanding the definition as it
 did above.  Sometimes you will define a function non-recursively to formalize
 some concept that is common in your application and you will want to create a
 sort of algebra of rules about the function.  By all means do so, so you can
 conduct your formal reasoning in terms of the concepts you're informally
 manipulating.  But after proving the required laws, disable the non-recursive
 concept so that ACL2 just uses your laws and not the messy definition.</p>

 <p><i>Choose a Left-Hand Side Already in Simplest Form</i>: This is a
 generalization of the advice above.  If any rule will rewrite your left-hand
 side, it will prevent your rule from matching any target.  For example, if you
 write a left-hand side like @('(foo (car (cons x y)))') then it would never
 match any target!  The reason is that even if @('(FOO (CAR (CONS A B)))') did
 occur in some goal formula, before ACL2 would try your rule about @('foo') it
 will use the obvious rule about @('CAR') and @('CONS') to transform your
 imagined target to @('(FOO A)').  Thus, your rule would not match.  So you
 have to keep in mind <i>all your other rules</i> when you choose a left-hand
 side (and when you choose the hypotheses to guide free variable selection).
 If you always choose a pattern that matches a term in a Key Checkpoint, you
 avoid this problem.  Also see @(see community-books) example
 @('books/demos/knuth-bendix-problem-1.lisp').</p>

 <p><i>Make Sure the Left-Hand Side is ``Heavier'' than the Right</i>:
 Sometimes this is obvious, as when you choose @('(REV (REV x))') for the
 left-hand side and @('x') for the right.  But what do you about @('(REV
 (APPEND x y))') versus @('(APPEND (REV y) (REV x))')?  Most of the time we
 choose to drive the heaviest function (in this case @('REV')) down toward the
 variables, lifting the lighter function (@('APPEND')) up so that we can reason
 about the lighter function's interaction with the surrounding ``matrix'' of
 the formula.  So we'd rewrite @('(REV (APPEND x y))') to @('(APPEND (REV y)
 (REV x))'), not vice versa.</p>

 <p><i>Alternative Ways to Talk About the Same Thing</i>: If your problem and
 specification use two different ways to talk about the same thing, choose one
 form and rewrite the other into that form.  For example, the ACL2 built-in
 @('nth') returns the nth element of a list, and the built-in function
 @('nthcdr') returns the nth @('cdr') of a list.  They are defined
 independently.  But @('(nth n x)') is the same thing as @('(car (nthcdr n
 x))').  Since @('nth') can be expressed in terms of @('nthcdr') but not vice
 versa, it is clear we should prove @('(equal (nth n x) (car (nthcdr n x)))')
 as a rewrite rule if both @('nth') and @('nthcdr') are involved in the
 problem.</p>

 <p><i>Don't Let Computational Efficiency Dictate the Terms</i>: If you have
 two functions that are equivalent (perhaps one was defined to be
 computationally more efficient), prove their equivalence as a rewrite rule
 that eliminates the more complicated function.  An extreme example would be a
 model that uses a sophisticated data structure (like a balanced binary tree,
 red-black tree, ordered array, or hash table) to implement something simple
 like an association of keys to values.  By proving the equivalence as stated
 you can eliminate the messy function early and do the bulk of your reasoning
 in terms of its simple specification.</p>

 <p>The best ACL2 users become very good at keeping all these things in mind
 when designing their rewrite rules.  Practice makes perfect.  Don't be afraid
 during your learning of ACL2 to undo the rules you first invented and try to
 make better ones.</p>

 <p>Finally, be patient!  There will be times when you think to yourself ``Why
 should I spend my time thinking of rules that guide ACL2?  I know the proof!''
 There are two reasons.  First, you may ``know'' the proof but you may well be
 wrong and part-way through this whole exercise you may realize that you're
 missing a major hypothesis or special case that breaks your whole conception
 of the problem.  The proof is in the details.  Second, most of the time the
 library of rules you develop in this process will be used over and over again
 on variants of the main problem in the months and years ahead.  This is
 sometimes called the <i>proof maintenance</i> problem.  Theorems don't suffer
 bit rot!  But the artifacts you're modeling change and you will need to prove
 new versions of old theorems.  A good general purpose library makes this much
 easier.</p>

 <p>We now recommend that you practice inventing strong rules; see @(see
 strong-rewrite-rules).</p>

 <p>For advice on handling specific kinds of formulas and definitions, see
 @(see specific-kinds-of-formulas-as-rewrite-rules).</p>

 <p>For more information about the rewriter works and how rules are created,
 see @(see further-information-on-rewriting).</p>

 <p>If you are working your way through the tutorial introduction to the
 theorem prover, use your browser's <b>Back Button</b> to return to @(see
 introduction-to-the-theorem-prover).</p>")

(defxdoc introduction-to-the-database
  :parents (introduction-to-the-theorem-prover)
  :short "How to update the database"
  :long "<p>We assume you've read @(see introduction-to-rewrite-rules-part-1)
 and @(see introduction-to-key-checkpoints).</p>

 <p>The theorem prover's heuristics are influenced by the database of rules and
 the enabled/disabled status of the rules.  You can think of the database as a
 <i>global</i> hint, potentially affecting all parts of a proof attempt.</p>

 <p>However, in addition to the ``global hint,'' it is possible to give
 <i>local</i> hints that affect the theorem prover's behavior on specific
 subgoals.  We discuss the database here and discuss local hints later in the
 tutorial.</p>

 <p>The theorem prover's ``database'' is called the <i>ACL2 world</i>.  You
 change the world by issuing commands called <i>events</i>.  The most common
 events are @('defun') for defining new functions (and predicates) and
 @('defthm') for proving new theorems.  Both add rules to the database.  Here
 are some commonly used events.</p>

 <p>We recommend that upon the first reading of this tutorial you do not follow
 the links shown below!  The links take you into the hypertext reference
 manual, where it is easy to get lost unless you're looking for detail about
 one specific feature.</p>

 <p>See @(see defun) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> to define a new function or predicate symbol.
 Definitional axioms are just a kind of @('rewrite') rule, but @('defun') may
 also add rules affecting the determination of the type of a term and rules
 affecting the induction analysis.  When you issue a @('defun') command you
 will always supply the <i>name</i> of the function or predicate, the list of
 <i>formal parameters</i>, <i>v1,...vn</i>, and the <i>body</i>:</p>

 <code>
 (defun <i>name</i> (<i>v1 ... vn</i>)
    <i>body</i>)
 </code>

 <p>If the event is accepted, a <i>definitional axiom</i> is added to the
 world, @('(')<i>name</i> <i>v1...vn</i>@(')')=<i>body</i>, stored as a special
 kind of unconditional rewrite rule.  However, the @('defun') event may require
 theorems to be proved.  Specifically, <i>measure theorems</i> must be proved
 to establish that recursively defined functions always terminate, by proving
 that an <i>ordinal</i> measure of the formal parameters decreases in a
 <i>well-founded</i> way in every recursive call.  In addition, if
 <i>guards</i> are being used to declare the <i>expected domain</i> of the
 newly defined function, <i>guard theorems</i> might be proved to establish
 that all functions stay within their expected domains.  In any case, you may
 provide additional information to the @('defun') event, coded as part of the
 @('declaration') that Common Lisp allows:</p>

 <code>
 (defun <i>name</i> (<i>v1 ... vn</i>)
    (declare (xargs ...))
    <i>body</i>)
 </code>

 <p>The @('xargs') (``extra arguments to @('defun')'') entry may specify, among
 other things, the measure to use in the termination proof, hints for use by
 the prover during the termination proof, the guard of the new function, and
 hints for use by the prover during the guard verification step.</p>

 <p>See @(see defthm) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> to prove a theorem and to add it as a rule of one
 or more specified rule-classes.  When you issue a @('defthm') command you
 always specify a <i>name</i> for the theorem you're trying to prove and a
 <i>formula</i> stating the theorem.  You may optionally supply some local
 hints as we describe later in the tutorial.  You may also optionally supply
 some <i>rule classes</i> indicating how you want your formula stored as a
 rule, after it is proved.  We discuss the @('defthm') <i>rule classes</i>
 below.</p>

 <p>See @(see in-theory) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> to enable or disable rules.  Rules have names
 derived from the names you give to functions and theorems, e.g., @('(:REWRITE
 LEFT-IDENTITY-OF-FOO . 2)') for the second rewrite rule you created from the
 theorem named @('LEFT-IDENTITY-OF-FOO').  Rule names are called <i>runes</i>.
 A <i>theory</i> is just a set (list) of runes.  The <i>current theory</i> is
 the list of enabled runes and the @('in-theory') event can add runes to or
 delete runes from the current theory.</p>

 <p>See @(see include-book) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> to change the world by loading a
 certified file of other events.  The most common use of @('include-book') is
 to load ``community books'' &mdash; books written by other ACL2 users who have
 released them for distribution to the community.  The most common books loaded
 are probably the arithmetic books:</p>

 <code>
 ; * for the most elementary arithmetic, needed for any problem
 ;   that involves even simple addition and multiplication like
 ; @('(+ x (* 2 y) -3)'):

     (include-book \"arithmetic/top-with-meta\" :dir :system)

 ; * for more complicated arithmetic involving non-linear terms like
 ; @('(* x y)'), @('(expt x (+ i j))'), and @('floor') and @('mod')

     (include-book \"arithmetic-5/top\" :dir :system)
 </code>

 <p>But for a complete list of system books, see @(see books) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p>See @(see certify-book) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> to
 certify a file of events for reuse later.</p>

 <p>See @(see defconst) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> to define a new constant, allowing you to write a
 symbol, e.g., @('*weekdays*') in place of some object, e.g., @(''(MON TUE WED
 THU FRI)') in formulas.</p>

 <p>See @(see defmacro) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> to define a new syntactic abbreviation.  The macro
 facility in Lisp is quite powerful, allowing you to <i>compute</i> the form to
 which some type-in expands.  For example, the primitive macro @('COND') is
 defined so that @('(COND ((P X) 1)((Q X) 2)(T 3))') expands to @('(IF (P X)
 1 (IF (Q X) 2 3))').</p>

 <p>See @(see defstobj) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> to introduce a <i>single-threaded object</i> that
 your functions may modify ``destructively'' provided they follow strict
 syntactic rules.</p>

 <p>See @(see events) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for a complete list of the ACL2 events.  There are
 events to allow mutually recursive definitions, to introduce some new function
 symbols constrained to satisfy given axioms, to allow the temporary
 introduction of a ``local'' event to help prove some goal theorem and then
 disappear, to provide the power of first-order quantification and a choice
 operator, and many other features.</p>

 <p>There are also commands that allow you to inspect the world, e.g., to print
 the command that introduced a given name, to show all the commands back to a
 certain one, undo the last command or more generally roll-back to an earlier
 command.  See @(see history) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p><b>The Defthm Rule-Classes</b></p>

 <p>We've already discussed the key role that rules play in controlling the
 behavior of the system.  New rules are introduced primarily with the
 @('defthm') event, though @('defun') and other events may introduce rules.</p>

 <p>To prove <i>formula</i> and generate, say a @(':rewrite') rule and a
 @(':generalize') rule from it, you would write</p>

 <code>
 (defthm <i>name</i>
         <i>formula</i>
         :rule-classes (:rewrite :generalize))
 </code>

 <p>If you wanted to rearrange the shape of the formula before generating the
 @(':rewrite') rule you could provide a @(':corollary') modifier to the
 @(':rewrite') rule class:</p>

 <code>
 (defthm <i>name</i>
         <i>formula</i>
         :rule-classes ((:rewrite :corollary ...)
                        :generalize)).
 </code>

 <p>There are many classes of rules, affecting different parts of the system.
 Each class is denoted by a keyword, e.g., @(':REWRITE'), @(':LINEAR'), etc.
 You are responsible for specifying the class(es) of rules to be generated from
 a given formula and several different rules (possibly of different classes)
 may be derived from a single formula.  Each class admits optional modifiers
 that allow you finer control over each rule.  Each class admits the
 @(':corollary') modifier with which you can rearrange the formula before a
 rule of that class is generated.  This allows you to state a theorem in its
 most elegant form for publication purposes but store it as a rule with the
 most appropriate hypotheses and conclusion.  Other modifiers tend to be
 specific to certain rule classes, but for example, @(':rewrite') rule
 modifiers include an optional limit on the depth of backchaining and options
 for handling free variables.</p>

 <p>We give some links below to other classes of rules.  However, we recommend
 that you not follow these links upon your first reading of this tutorial!</p>

 <p>See @(see REWRITE) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for a description of how to create a rewrite
 rule.</p>

 <p>See @(see LINEAR) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for a description of how to store theorems
 concluding with arithmetic inequalities.  The trouble with storing</p>

 @({
  (<= (len (delete e x)) (len x))
 })

 <p>as a rewrite rule is that it only matches instances of that inequality and
 thus fails to match</p>

 @({
  (<= (LEN (DELETE E X)) (+ 1 (LEN X)))
 })

 <p>ACL2 contains an extensible linear arithmetic decision procedure and by
 storing inequalities as @(':linear') rules you can make that decision
 procedure aware of the basic inequalities between non-primitive numerically
 valued terms.</p>

 <p>See @(see EQUIVALENCE) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>, see @(see CONGRUENCE) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>,
 and see @(see REFINEMENT) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> to learn how to introduce a new equivalence
 relation to the rewriter.  For example, suppose you define @('set-equal') so
 that it returns t precisely if its two arguments are lists containing the same
 elements, regardless of order or number of occurrences.  Note that under this
 sense of ``equivalence'', @('(rev x)') is the identity function and
 @('append') is commutative, for example.</p>

 @({
  (set-equal (rev x) x)

  (set-equal (append x y) (append y x))
 })

 <p>You can make ACL2 use these two theorems as @(':rewrite') rules to replace
 instances of @('(REV x)') and @('(APPEND x y)') by @('set-equal') terms, even
 though the results are not actually @('EQUAL').  This is possible provided the
 target occurs in a context admitting @('set-equal') as a congruence relation.
 For example, the congruence rule:</p>

 @({
  (implies (set-equal a b)
           (iff (member e a)
                (member e b)))
 })

 <p>gives the rewriter permission to use the above @('set-equal') rules as
 rewrite rules in the second argument of any @('member') expression being used
 in a propositional way.</p>

 <p>See @(see ELIM) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for a description of how to make the system adopt a
 ``change of variable'' tactic that can trade in <i>destructor</i> functions
 for <i>constructor</i> functions.  In analogy with how ACL2 eliminates @('(CAR
 X)') and @('(CDR X)') by replacing @('X') with @('(CONS A B)'), you can make
 it eliminate other destructors.  For example, the community book
 @('\"arithmetic-5/top\"') provides an @('elim') rule that eliminates @('(floor
 x y)') and @('(mod x y)') by replacing @('x') by @('(+ r (* y q))'), so that
 the @('floor') expression becomes @('q') and the @('mod') expression becomes
 @('r').  When introducing your own @('elim') rules you will probably also need
 to introduce @('generalize') rules (see below) so that the new variables are
 appropriately constrained.</p>

 <p>See @(see GENERALIZE) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for a description of how you can make ACL2 restrict
 the new variables it introduces when generalizing.  ACL2 will sometimes
 replace a term by a new variable and with @('generalize') rules you can insure
 that the new variable symbol has certain properties of the term it
 replaces.</p>

 <p>See @(see INDUCTION) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> for a description of how to tailor the inductions
 suggested by a term.  Most of the time when ACL2 chooses the ``wrong''
 induction, the easiest fix is with a local @(':induct') hint (see below).  But
 if the same problem arises repeatedly in several theorems, you might want to
 ``educate'' ACL2's induction heuristic.</p>

 <p>For a complete list of rule-classes, See @(see rule-classes) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p>If you are reading this as part of the tutorial introduction to the theorem
 prover, use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-the-theorem-prover).</p>")

(defxdoc introduction-to-the-tau-system
  :parents (tau-system)
  :short "A decision procedure for runtime types"
  :long "<p>This doc topic is the main source of information about the tau
 system and discusses the general idea behind the procedure and how to exploit
 it.</p>

 <p><i>A ``Type-Checker'' for an Untyped Language</i></p>

 <p>Because ACL2 is an untyped language it is impossible to type check it.  All
 functions are total.  An <i>n</i>-ary function may be applied to any
 combination of <i>n</i> ACL2 objects.  The syntax of ACL2 stipulates that
 @('(')<i>fn a1...an</i>@(')') is a well-formed term if <i>fn</i> is a function
 symbol of <i>n</i> arguments and the <i>ai</i> are well-formed terms.  No
 mention is made of the ``types'' of terms.  That is what is meant by saying
 ACL2 is an untyped language.</p>

 <p>Nevertheless, the system provides a variety of monadic Boolean function
 symbols, like @(tsee natp), @(tsee integerp), @(tsee alistp), etc., that
 recognize different ``types'' of objects at runtime.  Users typically define
 many more such recognizers for domain-specific ``types.''  Because of the
 prevalence of such ``types,'' ACL2 must frequently reason about the inclusion
 of one ``type'' in another.  It must also reason about the consequences of
 functions being defined so as to produce objects of certain ``types'' when
 given arguments of certain other ``types.''</p>

 <p>Because the word ``type'' in computer science tends to imply syntactic or
 semantic restrictions on functions, we avoid using that word henceforth.
 Instead, we just reason about monadic Boolean predicates.  You may wish to
 think of ``tau'' as synonymous with ``type'' but without any suggestion of
 syntactic or semantic restrictions.</p>

 <p><i>Design Philosophy</i></p>

 <p>The following basic principles were kept in mind when developing tau
 checker and may help you exploit it.</p>

 <p>(1) The tau system is supposed to be a lightweight, fast, and helpful
 decision procedure for an elementary subset of the logic focused on monadic
 predicates and function signatures.</p>

 <p>(2) Most subgoals produced by the theorem prover are not in any decidable
 subset of the logic!  Thus, decision procedures fail to prove the vast
 majority of the formulas they see and will be net time-sinks if tried too
 often no matter how fast they are.</p>

 <p>Tau reasoning is used by the prover as part of @('preprocess-clause'), one
 of the first proof techniques the system tries.  The tau system filters out
 ``obvious'' subgoals.  The tau system is only tried when subgoals first enter
 the waterfall and when they are stable under simplification.</p>

 <p>(3) The tau system is ``benign'' in the sense that the only way it
 contributes to a proof is to eliminate (prove!) subgoals.  It does not
 rewrite, simplify, or change formulas.  Tau reasoning is not used by the
 rewriter.  The tau system either eliminates a subgoal by proving it or leaves
 it unchanged.</p>

 <p>(4) It is impossible to infer automatically the relations between arbitrary
 recursively defined predicates and functions.  Thus, the tau system's
 knowledge of tau relationships and function signatures is gleaned from
 theorems stated by the user and proved by the system.</p>

 <p>(5) Users wishing to build effective ``type-checkers'' for their models
 must learn how rules affect the tau system's behavior.  There are two main
 forms of tau rules: those that reveal inclusion/exclusion relations between
 named tau predicates, e.g., that 16-bit naturals are also 32-bit naturals,</p>

 @({
  (implies (n16p x) (n32p x)),
 })

 <p>and signatures for all relevant functions, e.g., writing a 32-bit natural
 to a legal slot in a register file produces a register file:</p>

 @({
  (implies (and (natp n)
                (< n 16)
                (n32p val)
                (register-filep regs))
           (register-filep (update-nth n val regs))).
 })

 <p>For a complete description of acceptable forms see @(':')@(tsee
 tau-system).</p>

 <p>(6) The tau system is ``greedy'' in its efforts to augment its database.
 Its database is potentially augmented when rules of <i>any</i>
 @(':rule-class') (see @(':')@(tsee rule-classes)) are proved.  For example, if
 you make a @(':')@(tsee rewrite) or @(':')@(tsee type-prescription) rule which
 expresses a relationship between one tau and another (e.g., that @('(P x)')
 implies @('(Q x)')), ACL2 will build it into the tau database.  The rule-class
 @(':')@(tsee tau-system) can be used to add a rule to the tau database without
 adding any other kind of rule.</p>

 <p>(7) Greediness is forced into the design by benignity: the tau system may
 ``know'' some fact that the rewriter does not, and because tau reasoning is
 not used in rewriting, that missing fact must be conveyed to the rewriter
 through some other class of rule, e.g., a @(':')@(tsee rewrite) or
 @(':')@(tsee type-prescription) or @(':')@(tsee forward-chaining) rule.  By
 making the tau system greedy, we allow the user to program the rewriter and
 the tau system simultaneously while keeping them separate.  However, this
 means you must keep in mind the effects of a rule on <i>both</i> the rewriter
 and the tau system and use @(':')@(tsee tau-system) rules explicitly when you
 want to ``talk'' just to the tau system.</p>

 <p>(8) Tau rules are built into the database with as much preprocessing as
 possible (e.g., the system transitively closes inclusion/exclusion
 relationships at rule-storage time) so the checker can be fast.</p>

 <p>(9) For speed, tau does not track dependencies and is not sensitive to the
 enabled/disabled status (see @(tsee enable) and @(tsee disable)) of rules,
 other than @(see executable-counterpart) rules.  Once a fact has been built
 into the tau database, the only way to prevent that fact from being used is by
 disabling the entire tau system, by disabling @('(:')@(tsee
 executable-counterpart)@(' tau-system)').  If any tau reasoning is used in a
 proof, the rune @('(:')@(tsee executable-counterpart)@(' tau-system)') is
 reported in the summary.  For a complete list of all the runes in the tau
 database, evaluate @('(global-val 'tau-runes (w state))').  Any of these
 associated theorems could have been used.</p>

 <p>These design criteria are not always achieved!  For example, the tau
 system's ``greediness'' can be turned off (see @(tsee set-tau-auto-mode)), the
 tau database can be regenerated from scratch to ignore disabled rules (see
 @(tsee regenerate-tau-database)), and disabling the @(see
 executable-counterpart) of a tau predicate symbol will prevent the tau system
 from trying to run the predicate on constants.  The tau system's benignity can
 be frustrating since it might ``know'' something the rewriter does not.  More
 problematically, the tau system is not always ``fast'' and not always
 ``benign!''  The typical way tau reasoning can slow a proof down is by
 evaluating expensive tau predicates on constants.  The typical way tau
 reasoning can hurt a previously successful proof is by proving some subgoals
 (!) and thus causing the remaining subgoals to have different @(see
 clause-identifier)s, thus making explicit hints no longer applicable.  We deal
 with such problems in @(tsee dealing-with-tau-problems).</p>

 <p><i>Technical Details</i></p>

 <p>The tau system consists of both a database and an algorithm for using the
 database.  The database contains theorems that match certain schemas allowing
 them to be stored in the tau database.  Roughly speaking the schemas encode
 ``inclusion'' and ``exclusion'' relations, e.g., that @('natp') implies
 @('integerp') and that @('integerp') implies not @('consp'), and they encode
 ``signatures'' of functions, e.g., theorems that relate the output of a
 function to the input, provided only tau predicates are involved.</p>

 <p>By ``tau predicates'' we mean the application of a monadic Boolean-valued
 function symbol, the equality of something to a quoted constant, an arithmetic
 ordering relation between something and a rational constant, or the logical
 negation of such a term.  Here are some examples of tau predicates:</p>

 @({
  (natp i)
  (not (consp x))
  (equal y 'MONDAY)
  (not (eql 23 k))
  (< 8 max)
  (<= max 24)
 })

 <p>Synonyms for @(tsee equal) include @(tsee =), @(tsee eq), and @(tsee eql).
 Note that negated equalities are also allowed.  The arithmetic ordering
 relations that may be used are @(tsee <), @(tsee <=), @(tsee >=), and @(tsee
 >).  One of the arguments to every arithmetic ordering relation must be an
 integer or rational constant for the term to be treated as a tau
 predicate.</p>

 <p>A ``tau'' is a data object representing a set of signed (positive or
 negative) tau predicates whose meaning is the conjunction of the literals in
 the set.</p>

 <p>When we say that a term ``has'' a given tau we mean the term satisfies all
 of the recognizers in that tau.</p>

 <p>The tau algorithm is a decision procedure for the logical theory described
 (only) by the rules in the database.  The algorithm takes a term and a list of
 assumptions mapping subterms (typically variable symbols) to tau, and returns
 the tau of the given term.</p>

 <p>When the system is called upon to decide whether a term satisfies a given
 monadic predicate, it computes the tau of the term and asks whether the
 predicate is in that set.  More generally, to determine if a term satisfies a
 tau, <i>s</i>, we compute a tau, <i>r</i>, for the term and ask whether
 <i>s</i> is a subset of <i>r</i>.  To determine whether a constant, <i>c</i>,
 satisfies tau <i>s</i> we apply each of the literals in <i>s</i> to <i>c</i>.
 Evaluation might, of course, be time-consuming for complex user-defined
 predicates.</p>

 <p>The tau database contains rules derived from definitions and theorems
 stated by the user.  See @(':')@(tsee tau-system) for a description of the
 acceptable forms of tau rules.</p>

 <p>To shut off the greedy augmentation of the tau database, see @(see
 set-tau-auto-mode).  This may be of use to users who wish to tightly control
 the rules in the tau database.  To add a rule to the tau database without
 adding any other kind of rule, use the rule class @(':')@(tsee
 tau-system).</p>

 <p>There are some slight complexities in the design related to how we handle
 events with both @(':tau-system') corollaries and corollaries of other
 @(':rule-classes'), see @(tsee set-tau-auto-mode).</p>

 <p>To prevent tau reasoning from being used, disable the @(':')@(tsee
 executable-counterpart) of @('tau-system'), i.e., execute</p>

 @({
  (in-theory (disable (:executable-counterpart tau-system)))
 })

 <p>or, equivalently,</p>

 @({
  (in-theory (disable (tau-system)))
 })

 <p>To prevent tau from being used in the proof of a particular subgoal,
 locally disable the @(':')@(tsee executable-counterpart) of @('tau-system')
 with a local @(':in-theory') hint (see @(see hints)).</p>

 <p>The event command @(tsee tau-status) is a macro that can be used to toggle
 both whether tau reasoning is globally enabled and whether the tau database is
 augmented greedily.  For example, the event</p>

 @({
  (tau-status :system nil :auto-mode nil)
 })

 <p>prevents the tau system from being used in proofs and prevents the
 augmentation of the tau database by rules other than those explicitly labeled
 @(':')@(tsee tau-system).</p>

 <p>To see what the tau system ``knows'' about a given function symbol see
 @(see tau-data).  To see the entire tau database, see @(see tau-database).  To
 regenerate the tau database using only the runes listed in the current enabled
 theory, see @(see regenerate-tau-database).</p>")

(defxdoc introduction-to-the-theorem-prover
  :parents (acl2-tutorial)
  :short "How the theorem prover works &mdash; level 0"
  :long "<p>Software is complex, and ACL2 is a piece of software that is used
 to analyze software &mdash; adding another layer of complexity.  Furthermore,
 instead of being limited to static analysis for certain fixed properties, ACL2
 allows you &mdash; indeed, forces you &mdash; to formalize the problem and the
 questions.  It ``knows'' nothing inherent about your problem before you start
 to interact with it.  But it can be used to help answer the most complicated
 questions you can ask about software.</p>

 <p>All this is to say that it is not the kind of tool that you just install
 and then start to use effectively.  So OK, you've installed it or confirmed
 that you can invoke it.  Good for you.  Now you have to learn how to use it!
 Your success ultimately comes down to your understanding of your problem
 domain and your appropriate exploitation of ACL2's strengths and avoidance of
 its weaknesses.  So put aside the idea of sitting down and interacting with
 it.  Instead, learn about it.</p>

 <p>We assume you know some of the <see topic='@(url
 INTERESTING-APPLICATIONS)'>industrial applications</see> of ACL2.  Realizing
 that such things can be done may sustain you during the long learning curve!
 We also assume you have taken both the <see topic='@(url
 |A Flying Tour of ACL2|)'>Flying Tour</see> and the <see topic='@(url
 |A Walking Tour of ACL2|)'>Walking Tour</see>.  The tours give you a good
 overview of the whole system where this tutorial focuses on how to use the
 prover itself.</p>

 <p>If you haven't visited these links, please do so now.</p>

 <p>This tutorial will take you several hours &mdash; maybe several days
 &mdash; to work through.  Do not breeze through it as you might a blog.
 <i>Think</i> your way through it.  <i>Remember</i> what you read.  Do not take
 short cuts.  If you start to use ACL2 before you really know how, it will only
 frustrate you.</p>

 <p>We recommend that you read this tutorial with an HTML browser so that you
 can see which links you've followed and which you have not.  To give you a
 sense of what is in store, here is a map of this document.  But don't navigate
 through it from here! Read it linearly, following the links when the text
 directs you to.</p>

 <code>
  @(see INTRODUCTION-TO-THE-THEOREM-PROVER)
      @(see INTRODUCTION-TO-REWRITE-RULES-PART-1)
          @(see SPECIAL-CASES-FOR-REWRITE-RULES)
          @(see EQUIVALENT-FORMULAS-DIFFERENT-REWRITE-RULES)
      @(see INTRODUCTION-TO-KEY-CHECKPOINTS)
          @(see DEALING-WITH-KEY-COMBINATIONS-OF-FUNCTION-SYMBOLS)
          @(see GENERALIZING-KEY-CHECKPOINTS)
          @(see POST-INDUCTION-KEY-CHECKPOINTS)
      @(see INTRODUCTION-TO-REWRITE-RULES-PART-2)
          @(see STRONG-REWRITE-RULES)
              @(see PRACTICE-FORMULATING-STRONG-RULES)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-1)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-2)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-3)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-4)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-5)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-6)
          @(see SPECIFIC-KINDS-OF-FORMULAS-AS-REWRITE-RULES)
          @(see FURTHER-INFORMATION-ON-REWRITING)
      @(see INTRODUCTION-TO-THE-DATABASE)
      @(see INTRODUCTION-TO-HINTS)
      @(see INTRODUCTION-TO-A-FEW-SYSTEM-CONSIDERATIONS)
      @(see INTRODUCTORY-CHALLENGES)
          @(see INTRODUCTORY-CHALLENGE-PROBLEM-1)
          @(see INTRODUCTORY-CHALLENGE-PROBLEM-2)
          @(see INTRODUCTORY-CHALLENGE-PROBLEM-3)
          <i>(there are others but at least do a few)</i>
      @(see FREQUENTLY-ASKED-QUESTIONS-BY-NEWCOMERS)
 </code>

 <p>If any of the links above are marked as ``visited'' by your browser, use
 your browser's tools menu to mark all links as unvisited.  As you can see, we
 really think you'll get the most out of this document if you take it
 seriously.  As you read, you will see some links to ``advanced'' topics.
 These are marked with a tiny warning sign, ``<see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>''.
 They lead out of this linear tutorial and into ACL2's hypertext reference
 manual.  We recommend that you <i>not</i> visit any of these advanced links
 until you have read the entire tutorial at least once.</p>

 <p>After you finish this tutorial material, we recommend that you look at the
 ACL2 Demos, at the ``Demos'' link of the <a
 href='http://www.cs.utexas.edu/users/moore/acl2'>ACL2 home page</a>.</p>

 <p>Most users of ACL2 have bought the book</p>

 <p><i>Computer-Aided Reasoning: An Approach</i>, Kaufmann, Manolios, and
 Moore, Kluwer Academic Publishers, June, 2000</p>

 <p>which is available <a href='http://www.lulu.com/content/1746161'>in
 paperback</a> from Lulu for approximately $20 (as of 2010).  That book
 contains hundreds of exercises in programming, proof, and using The Method
 described here to prove theorems.  Solutions to the exercises are online, as
 are <a
 href='http://link.springer.com/content/pdf/bbm%3A978-1-4615-4449-4%2F1.pdf'>appendices</a>
 that focus on some practical usage aspects.  See this <a
 href='http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html#Books'>
 web page about the book</a>, which also includes information about its
 companion (also available on Lulu) describing applications of ACL2, some of
 which are from industry.</p>

 <p>Using ACL2 is akin to having a partner in the theorem proving enterprise.
 It will do some of the work and you will do some of the work.  It can't really
 be any other way because theorem proving is undecidable.  You bring a quirky,
 error-prone, creative insight to the problem, and ACL2 brings accuracy, logic,
 and perseverance.</p>

 <p>Here we describe a ``model'' of how the system works and introduce some of
 the ideas and terminology you'll use repeatedly when interacting with it.</p>

 <p>This article is about the <i>theorem prover</i> itself, not the programming
 language and not the logic.  We assume you know enough about the ACL2
 programming language that you can define simple functions, run them, and read
 and write ACL2 constants and terms.  For some examples of what we'll take for
 granted about ACL2 programming, see @(see
 programming-knowledge-taken-for-granted).</p>

 <p>We also assume you know enough about logic to understand, for example, the
 words we use to talk about formulas and proofs.  To see some examples of what
 we'll take for granted about your knowledge of logic terminology, see @(see
 logic-knowledge-taken-for-granted).</p>

 <p>When you give the theorem prover a goal formula to prove, it tries to prove
 it by breaking it down into subgoals, each of which must be proved in order to
 prove the original goal.  This breaking apart of the goal is done by various
 <i>proof techniques</i> built into ACL2.  Different proof techniques break the
 formula apart in different ways.  For example, the <i>simplifier</i> rips
 apart the propositional structure to isolate the various cases and applies
 rewrite rules to simplify the subterms of the formula, while the
 <i>induction</i> <i>engine</i> will attempt to break the goal into some base
 cases and some induction steps.</p>

 <p>The theorem prover's behavior is affected by a <i>database</i> of
 <i>rules</i> derived from axioms, definitions, and previously proved theorems.
 The database also records the <i>enabled status</i> of each rule; only enabled
 rules are seen by the prover and you can set the status of a rule.  There are
 many other user-settable switches and parameters affecting the behavior of the
 prover; you'll learn about some of them later.</p>

 <p>You guide the theorem prover most of the time simply by identifying lemmas
 for it to prove.  (A <i>lemma</i> is just a theorem that you think is useful
 in the proofs of other theorems.)</p>

 <p>Why does this guide the theorem prover?  Because every time you get the
 system to prove a theorem, it turns the theorem into a rule (unless you tell
 it not to) and stores the rule in the database.  That changes how the prover
 behaves subsequently.  But <i>you</i> determine the kind of rule ACL2
 stores.</p>

 <p>To learn to ``drive'' the theorem prover you have to learn how various
 rules affect the system's behavior and how it turns proved formulas into
 rules.  But before we discuss this, we discuss a more mathematical activity:
 how do you figure out the lemmas ACL2 will need in order for it to prove
 interesting theorems?  ACL2 can often help you in this activity, if you use it
 in the right way.</p>

 <p>Here is the way we recommend you use ACL2.</p>

 <p><b>The Method</b>.</p>

 <p>(1) you present ACL2 with the goal conjecture to prove</p>

 <p>(2) typically, it fails to prove it (or you abort its attempt), but it
 prints some <i>Key Checkpoints</i></p>

 <p>(3) you look at the Key Checkpoints and decide that you know a fact that
 will help; this tutorial will present some helpful questions to keep in
 mind</p>

 <p>(4) you formalize your knowledge as a formula, along with directions for
 how ACL2 should turn the formula into a rule; this tutorial will tell you
 about the most commonly used rule, the <i>rewrite</i> rule</p>

 <p>(5) you recursively apply The Method to get ACL2 to prove your formula and
 to store it as the kind of rule you specified</p>

 <p>(6) go to step (1)</p>

 <p>Caveat: This approach simply won't work on some theorems!  Basically, this
 is a ``troubleshooting'' approach, where you're letting ACL2 determine the
 basic strategy and you're just helping with the subgoals.  But for some
 theorems, ACL2's approach will be misguided and no amount of troubleshooting
 will salvage its strategy.  You'll have a sense that this is happening when it
 happens because the formulas ACL2 presents to you will raise issues that feel
 irrelevant to you.  The basic truth is that if you think a formula is always
 true there are usually strong intuitive reasons behind your belief.  If you
 were asked to defend your belief, you'd start to explain your reasons and with
 training you can turn that into a proof.  So when ACL2's formulas present you
 with things you haven't thought of either (a) you'll have an ``Ah ha!''
 moment when you realize you hadn't considered that case or (b) you'll realize
 that ACL2's approach is different from your intuitive ``proof.''</p>

 <p>But, surprisingly often, the troubleshooting approach to finding proofs
 works quite well, especially as you rein in your expectations and develop a
 sense of what ACL2 can handle on its own.  Of course, if you can decompose the
 proof into a couple of main lemmas before you start, so much the better: write
 down your sequence of lemmas, thinking about the rules you want them to
 generate, and get ACL2 to prove each of them before giving it the main
 theorem.  This <i>proof planning</i> approach will gradually become an
 integral part of your use of The Method.</p>

 <p>The only mechanized help we can offer with The Method, aside from the
 theorem prover itself, are tools to help you manage the stack of subgoals it
 generates when, in step (5) you recursively apply The Method to a lemma.
 There are both Emacs and Eclipse tools available.</p>

 <p>To use The Method you have to read the Key Checkpoints printed at the very
 end of <i>failed</i> proof attempts, just after the line that reads:</p>

 @({
  The key checkpoint goals, below, may help you to debug this failure.
 })

 <p>Most users do not read the output from successful proofs and do not read
 the output <i>during</i> a proof &mdash; they just let it stream by as a sort
 of gestalt meter on the theorem prover's progress or lack thereof.  For
 example, you'll be able to tell it is in a loop and needs to be
 interrupted.</p>

 <p>You will respond to most Key Checkpoints by formulating new lemmas for the
 system to prove and store as rules designed by you to alter ACL2's behavior so
 that it proves the Key Checkpoints.  You will give each lemma a <i>name</i>
 and write some <i>formula</i> to express the mathematical idea.  You'll
 command ACL2 to prove it by typing:</p>

 <code>
 (defthm <i>name</i>
         <i>formula</i>
         ...)
 </code>

 <p>In the ``...'' you may provide two other kinds of information: <i>hints</i>
 for how to prove <i>formula</i> and directives, called <i>rule-classes</i>,
 for how to convert <i>formula</i> into a rule after it has proved
 <i>formula</i>.  Note that <i>you</i> are in charge of determining what kind
 of rule ACL2 generates!  There are over a dozen different types of rules with
 many opportunities to specialize each type.  But the most common kind of rule
 you'll want to generate is a <i>rewrite</i> rule.</p>

 <p>We recommend that you read the following topics in the following order,
 without skipping anything except links into the ACL2 User's Manual, which are
 marked by the little warning sign, ``<see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>''.</p>

 <p>(1) See @(see introduction-to-rewrite-rules-part-1) to read about the use
 and design of rewrite rules.</p>

 <p>(2) See @(see introduction-to-key-checkpoints) to see how to use The Method
 to help you design rules.</p>

 <p>(3) See @(see introduction-to-rewrite-rules-part-2) for general guidance on
 how to turn formulas into effective rules.</p>

 <p>(4) See @(see introduction-to-the-database) to see how to issue commands
 that build different kinds of rules and that affect the enabled status of
 existing rules.</p>

 <p>(5) See @(see introduction-to-hints) to see how to give the prover hints
 for how to prove specific theorems or even subgoals of specific proof
 attempts.</p>

 <p>(6) See @(see introduction-to-a-few-system-considerations) for a few words
 about system aspects of interacting with ACL2.</p>

 <p>(7) See @(see introductory-challenges) for a graduated sequence of good
 challenge problems for the new user to tackle.  <b>Do not skip this
 section!</b> It is here that you <i>really</i> learn how to use ACL2 &mdash;
 by using it.</p>

 <p>(8) See @(see frequently-asked-questions-by-newcomers) for a list of
 questions that new users frequently ask, answered mainly by providing links
 into the ACL2 User's Manual.  We recommend that you skim through these
 questions and remember that you can find the answers here later.  We are very
 interested in receiving suggestions for how to improve this FAQ and this
 tutorial.  See the ACL2 home page, specifically the link ``Mailing
 Lists''.</p>

 <p>Please read all of the material cited above (skipping only the ACL2 User's
 Manual links (``<see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>'')) before you try to use ACL2 on problems of your
 own.</p>

 <p>By this point you should have read, at least, the following topics from
 this tutorial introduction to the theorem prover:</p>

 <code>
  @(see INTRODUCTION-TO-THE-THEOREM-PROVER)
      @(see INTRODUCTION-TO-REWRITE-RULES-PART-1)
          @(see SPECIAL-CASES-FOR-REWRITE-RULES)
          @(see EQUIVALENT-FORMULAS-DIFFERENT-REWRITE-RULES)
      @(see INTRODUCTION-TO-KEY-CHECKPOINTS)
          @(see DEALING-WITH-KEY-COMBINATIONS-OF-FUNCTION-SYMBOLS)
          @(see GENERALIZING-KEY-CHECKPOINTS)
          @(see POST-INDUCTION-KEY-CHECKPOINTS)
      @(see INTRODUCTION-TO-REWRITE-RULES-PART-2)
          @(see STRONG-REWRITE-RULES)
              @(see PRACTICE-FORMULATING-STRONG-RULES)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-1)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-2)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-3)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-4)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-5)
                  @(see PRACTICE-FORMULATING-STRONG-RULES-6)
          @(see SPECIFIC-KINDS-OF-FORMULAS-AS-REWRITE-RULES)
          @(see FURTHER-INFORMATION-ON-REWRITING)
      @(see INTRODUCTION-TO-THE-DATABASE)
      @(see INTRODUCTION-TO-HINTS)
      @(see INTRODUCTION-TO-A-FEW-SYSTEM-CONSIDERATIONS)
      @(see INTRODUCTORY-CHALLENGES)
          @(see INTRODUCTORY-CHALLENGE-PROBLEM-1)
          @(see INTRODUCTORY-CHALLENGE-PROBLEM-2)
          @(see INTRODUCTORY-CHALLENGE-PROBLEM-3)
          <i>(there are others but at least do a few)</i>
      @(see FREQUENTLY-ASKED-QUESTIONS-BY-NEWCOMERS)
 </code>

 <p>We also recommend that you look at the ACL2 Demos mentioned in the @(see
 acl2-tutorial).</p>

 <p>Most users of ACL2 have bought the book</p>

 <p><i>Computer-Aided Reasoning: An Approach</i>, Kaufmann, Manolios, and
 Moore, Kluwer Academic Publishers, June, 2000</p>

 <p>which is <a href='http://www.lulu.com/content/1746161'>available in
 paperback from Lulu</a> for approximately $20 (as of 2010).  That book
 contains hundreds of exercises in programming, proof, and using The Method to
 prove theorems.  Solutions to the exercises are online.  See also this <a
 href='http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html#Books'>
 web page about the book</a>, which also includes information about its
 companion (also available on Lulu) describing applications of ACL2, some of
 which are from industry.</p>

 <p>Thank you for spending the time to get acquainted with the basics of the
 ACL2 theorem prover.  Don't hesitate to send further questions to the ACL2
 Help address on the ``Mailing Lists'' link of the ACL2 home page.</p>

 <p><b>End of Tutorial Introduction to the Theorem Prover</b></p>

 <p>Below is a list of all of the topics cited on this page.</p>")

(defxdoc introductory-challenge-problem-1
  :parents (introduction-to-the-theorem-prover)
  :short "Challenge problem 1 for the new user of ACL2"
  :long "<p>Start in a fresh ACL2, either by restarting your ACL2 image from
 scratch or executing</p>

 @({
  :ubt! 1
 })

 <p>which will undo everything since the first user event.</p>

 <p>Then define this function:</p>

 @({
  (defun rev (x)
    (if (endp x)
        nil
        (append (rev (cdr x)) (list (car x)))))
 })

 <p>Then use The Method to prove:</p>

 @({
  (defthm triple-rev
    (equal (rev (rev (rev x))) (rev x)))
 })

 <p>When you've solved this problem, compare your answer to ours; see @(see
 introductory-challenge-problem-1-answer).</p>

 <p>Then, use your browser's <b>Back Button</b> to return to @(see
 introductory-challenges).</p>")

(defxdoc introductory-challenge-problem-1-answer
  :parents (introduction-to-the-theorem-prover)
  :short "Answer to challenge problem 1 for the new user of ACL2"
  :long "<p>This answer is in the form of an ACL2 script sufficient to lead
 ACL2 to a proof.</p>

 <code>
 (defun rev (x)
   (if (endp x)
       nil
       (append (rev (cdr x)) (list (car x)))))

 ; Trying @('triple-rev') at this point produces a key checkpoint containing
 ; @('(REV (APPEND (REV (CDR X)) (LIST (CAR X))))'), which suggests:

 (defthm rev-append
   (equal (rev (append a b))
          (append (rev b) (rev a))))

 ; And now @('triple-rev') succeeds.

 (defthm triple-rev
   (equal (rev (rev (rev x))) (rev x)))

 ; An alternative, and more elegant, solution is to prove the @('rev-rev')
 ; instead of @('rev-append'):

 ; (defthm rev-rev
 ;   (implies (true-listp x)
 ;            (equal (rev (rev x)) x)))

 ; @('Rev-rev') is also discoverable by The Method because it is
 ; suggested by the statement of @('triple-rev') itself: @('rev-rev')
 ; simplifies a simpler composition of the functions in @('triple-rev').

 ; Both solutions produce lemmas likely to be of use in future proofs
 ; about @('rev').

 </code>

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 introductory-challenge-problem-1).</p>")

(defxdoc introductory-challenge-problem-2
  :parents (introduction-to-the-theorem-prover)
  :short "Challenge problem 2 for the new user of ACL2"
  :long "<p>Start in a fresh ACL2, either by restarting your ACL2 image from
 scratch or executing @(':ubt! 1').</p>

 <p>Use The Method to prove</p>

 @({
  (defthm subsetp-reflexive
    (subsetp x x))
 })

 <p>When you've solved this problem, compare your answer to ours; see @(see
 introductory-challenge-problem-2-answer).</p>

 <p>Then, use your browser's <b>Back Button</b> to return to @(see
 introductory-challenges).</p>")

(defxdoc introductory-challenge-problem-2-answer
  :parents (introduction-to-the-theorem-prover)
  :short "Answer to challenge problem 2 for the new user of ACL2"
  :long "<p>This answer is in the form of a script sufficient to lead ACL2 to a
 proof.</p>

 <code>
 ; Trying @('subsetp-reflexive') at this point produces the key checkpoint:

 ; (IMPLIES (AND (CONSP X)
 ;               (SUBSETP (CDR X) (CDR X)))
 ;          (SUBSETP (CDR X) X))

 ; which suggests the generalization:

 (defthm subsetp-cdr
   (implies (subsetp a (cdr b))
            (subsetp a b)))

 ; And now @('subsetp-reflexive') succeeds.

 (defthm subsetp-reflexive
   (subsetp x x))

 ; A weaker version of the lemma, namely the one in which we
 ; add the hypothesis that @('b') is a @('cons'), is also sufficient.

 ;    (defthm subsetp-cdr-weak
 ;      (implies (and (consp b)
 ;                    (subsetp a (cdr b)))
 ;               (subsetp a b)))

 ; But the @('(consp b)') hypothesis is not really necessary in
 ; ACL2's type-free logic because @('(cdr b)') is @('nil') if @('b') is
 ; not a @('cons').  For the reasons explained in the tutorial, we
 ; prefer the strong version.

 </code>

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 introductory-challenge-problem-2).</p>")

(defxdoc introductory-challenge-problem-3
  :parents (introduction-to-the-theorem-prover)
  :short "Challenge problem 3 for the new user of ACL2"
  :long "<p>Start in a fresh ACL2, either by restarting your ACL2 image from
 scratch or executing @(':ubt! 1').</p>

 <p>Define the following functions and use The Method to prove the theorem at
 the bottom:</p>

 @({
  (defun rev (x)
    (if (endp x)
        nil
        (append (rev (cdr x)) (list (car x)))))

  (defun dupsp (x)  ; does x contain duplicate elements?
    (if (endp x)
        nil
        (if (member (car x) (cdr x))
            t
            (dupsp (cdr x)))))

  (defthm dupsp-rev
    (equal (dupsp (rev x)) (dupsp x)))
 })

 <p>When you've solved this problem, compare your answer to ours; see @(see
 introductory-challenge-problem-3-answer).</p>

 <p>Then, use your browser's <b>Back Button</b> to return to @(see
 introductory-challenges).</p>")

(defxdoc introductory-challenge-problem-3-answer
  :parents (introduction-to-the-theorem-prover)
  :short "Answer to challenge problem 3 for the new user of ACL2"
  :long "<p>This answer is in the form of a script sufficient to lead ACL2 to a
 proof.</p>

 <code>
 ; Trying @('dupsp-rev') at this point produces the key checkpoint:

 ; (IMPLIES (AND (CONSP X)
 ;               (NOT (MEMBER (CAR X) (CDR X)))
 ;               (EQUAL (DUPSP (REV (CDR X)))
 ;                      (DUPSP (CDR X))))
 ;          (EQUAL (DUPSP (APPEND (REV (CDR X)) (LIST (CAR X))))
 ;                 (DUPSP (CDR X))))

 ; which suggests the lemma

 ; (defthm dupsp-append
 ;   (implies (not (member e x))
 ;            (equal (dupsp (append x (list e)))
 ;                   (dupsp x))))

 ; However, attempting to prove that, produces a key checkpoint
 ; containing @('(MEMBER (CAR X) (APPEND (CDR X) (LIST E)))').
 ; So we prove the lemma:

 (defthm member-append
   (iff (member e (append a b))
        (or (member e a)
            (member e b))))

 ; Note that we had to use @('iff') instead of @('equal') since
 ; @('member') is not a Boolean function.

 ; Having proved this lemma, we return to @('dupsp-append') and succeed:

 (defthm dupsp-append
   (implies (not (member e x))
            (equal (dupsp (append x (list e)))
                   (dupsp x))))

 ; So now we return to @('dups-rev'), expecting success.  But it fails
 ; with the same key checkpoint:

 ; (IMPLIES (AND (CONSP X)
 ;               (NOT (MEMBER (CAR X) (CDR X)))
 ;               (EQUAL (DUPSP (REV (CDR X)))
 ;                      (DUPSP (CDR X))))
 ;          (EQUAL (DUPSP (APPEND (REV (CDR X)) (LIST (CAR X))))
 ;                 (DUPSP (CDR X))))

 ; Why wasn't our @('dupsp-append') lemma applied?  We have two choices here:
 ; (1) Think.  (2) Use tools.

 ; Think: When an enabled rewrite rule doesn't fire even though the
 ; left-hand side matches the target, the hypothesis couldn't be
 ; relieved.  The @('dups-append') rule has the hypothesis @('(not
 ; (member e x))') and after the match with the left-hand side, @('e')
 ; is @('(CAR X)') and @('x') is @('(REV (CDR X))').  So the system
 ; couldn't rewrite @('(NOT (MEMBER (CAR X) (REV (CDR X))))') to true,
 ; even though it knows that @('(NOT (MEMBER (CAR X) (CDR X)))') from
 ; the second hypothesis of the checkpoint.  Obviously, we need to
 ; prove @('member-rev') below.

 ; Use tools:  We could enable the ``break rewrite'' facility, with

 ; ACL2 !&gt;:brr t

 ; and then install an unconditional monitor on the rewrite rule
 ; @('dupsp-append'), whose rune is (:REWRITE DUPSP-APPEND), with:

 ; :monitor (:rewrite dupsp-append) t

 ; Then we could re-try our main theorem, dupsp-rev.  At the resulting
 ; interactive break we type :eval to evaluate the attempt to relieve the
 ; hypotheses of the rule.

 ; (1 Breaking (:REWRITE DUPSP-APPEND) on
 ; (DUPSP (BINARY-APPEND (REV #) (CONS # #))):
 ; 1 ACL2 &gt;:eval

 ; 1x (:REWRITE DUPSP-APPEND) failed because :HYP 1 rewrote to
 ; (NOT (MEMBER (CAR X) (REV #))).

 ; Note that the report above shows that hypothesis 1 of the rule
 ; did not rewrite to T but instead rewrote to an expression
 ; involving @('(member ... (rev ...))').  Thus, we're led to the
 ; same conclusion that Thinking produced.  To get out of the
 ; interactive break we type:

 ; 1 ACL2 &gt;:a!
 ; Abort to ACL2 top-level

 ; and then turn off the break rewrite tool since we won't need it
 ; again right now, with:

 ; ACL2 !&gt;:brr nil

 ; In either case, by thinking or using tools, we decide to prove:

 (defthm member-rev
   (iff (member e (rev x))
        (member e x)))

 ; which succeeds.  Now when we try to prove dups-rev, it succeeds.

 (defthm dupsp-rev
   (equal (dupsp (rev x))
          (dupsp x)))

 </code>

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 introductory-challenge-problem-3).</p>")

(defxdoc introductory-challenge-problem-4
  :parents (introduction-to-the-theorem-prover)
  :short "Challenge problem 4 for the new user of ACL2"
  :long "<p>Start in a fresh ACL2, either by restarting your ACL2 image from
 scratch or executing @(':ubt! 1').</p>

 <p>This problem is much more open ended than the preceding ones.  The
 challenge is to define a function that collects exactly one copy of each
 element of a list and to prove that it returns a subset of the list with no
 duplications.</p>

 <p><b>Hint</b>: We recommend that you read this hint to align your function
 names with our solution, to make comparisons easier.  Our answer is shown in
 see @(see introductory-challenge-problem-4-answer).  In that page you'll see a
 definition of a function @('collect-once') and the proofs of two theorems:</p>

 @({
  (defthm main-theorem-1-about-collect-once
    (subsetp (collect-once x) x))

  (defthm main-theorem-2-about-collect-once
    (not (dupsp (collect-once x))))
 })

 <p>The function @('dupsp') is as defined in see @(see
 introductory-challenge-problem-3).  This is quite easy.</p>

 <p>Then, we define a tail-recursive version of the method based on the
 pseudo-code:</p>

 @({
   a = nil;
   while (x not empty) {
    a = if (member (car x) a) then a else (cons (car x) a);
    x = (cdr x);
    }
   return a;
 })

 <p>We formalize this with the function @('while-loop-version'), where
 @('(while-loop-version x nil)') is the ``semantics'' of the code above.  I.e.,
 the function @('while-loop-version') captures the while loop in the
 pseudo-code above and returns the final value of @('a'), and it should be
 invoked with the initial value of @('a') being @('nil').</p>

 <p>We prove @('(while-loop-version x nil)') returns a subset of @('x') that
 contains no duplications.  Furthermore, we do it two ways: first
 ``indirectly'' by relating @('while-loop-version') to @('collect-once'), and
 second (``directly'') without using @('collect-once').  Both of these proofs
 are much harder than the @('collect-once') approach, involving about a dozen
 lemmas each.</p>

 <p>Compare your solutions to ours at see @(see
 introductory-challenge-problem-4-answer).</p>

 <p>Then, use your browser's <b>Back Button</b> to return to @(see
 introductory-challenges).</p>")

(defxdoc introductory-challenge-problem-4-answer
  :parents (introduction-to-the-theorem-prover)
  :short "Answer to challenge problem 4 for the new user of ACL2"
  :long "<p>This topic solves a challenge problem presented elsewhere; see
 @(see introductory-challenge-problem-4).  This answer is in the form of a
 script sufficient to lead ACL2 to a proof, with a brief prologue.</p>

 <p>We wish to collect one copy of each element in x.  We'll actually define
 the method two ways, primitive recursively and tail-recursively, the latter
 method being analogous to the program:</p>

 @({
  a = nil;
  while (x not empty) {
    a = if (member (car x) a) then a else (cons (car x) a);
    x = (cdr x);
    }
  return a;
 })

 <p>We'll prove the two ``equivalent'' and we'll prove that they return a
 subset of @('x') that contains no duplications.</p>

 <p>This page is organized into four sections.  (A) We will start by proving
 that the primitive recursive version correct: it returns a subset of its
 argument that is duplication free.  This will be straightforward.  (B) Then
 we'll define the @('while')-loop version and we will prove it ``equivalent''
 to the primitive recursive version.  This will be challenging primarily
 because the two methods collect their answers in different orders; even
 stating the relationship between the two is interesting.  Proving it will
 involve a few lemmas.  But once we prove their ``equivalence'' the correctness
 of the @('while')-loop version will be straightforward from the correctness of
 the primitive recursive version.  (C) We will disable the rules we prove about
 the @('while')-loop version and prove it correct directly, without exploiting
 the primitive recursive version.  This requires leading the theorem prover
 more carefully because reasoning about tail-recursive functions that
 accumulate results is sometimes delicate.  (D) Lessons learned &mdash; a
 narrative that summarizes what we learn from these examples.</p>

 <p>We follow The Method, which, recall, involves us in recursive attempts to
 prove lemmas.  We use a notation to indicate our sequence of proof attempts.
 Here is an example (although in actual use we print things across multiple
 lines).  The number in bracket indicates our ``stack depth''.  The ``key
 term'' is some term from a Key Checkpoint in the failed proof which is
 responsible for our subsequent action.  Sometimes instead of a Key Term we
 just give an English explanation of what we're thinking.</p>

 @({
  [0] (defthm main ...)     Failed!    Key Term: ...
  [1] (defthm lemma-1 ...)  Succeeded!
  [0] (defthm main ...)     Failed!    Key Term: ...
  [1] (defthm lemma-2 ...)  Failed!    Key Term: ...
  [2] (defthm lemma-2a ...) Succeeded!
  [2] (defthm lemma-2b ...) Succeeded!
  [1] (defthm lemma-2 ...)  Succeeded!
  [0] (defthm main ...)     Succeeded!
 })

 <p>The rest of this page is just a re-playable script.</p>

 @({
  ; -----------------------------------------------------------------
  ; Section A:  The Primitive Recursive Version and Its Correctness

  ; The property of having duplications is defined as:

  (defun dupsp (x)
    (if (endp x)
        nil
        (if (member (car x) (cdr x))
            t
            (dupsp (cdr x)))))

  ; The primitive recursive method of collecting one copy of each element is:

  (defun collect-once (x)
    (if (endp x)
        nil
        (if (member (car x) (cdr x))
            (collect-once (cdr x))
            (cons (car x) (collect-once (cdr x))))))

  ; [0]
  (defthm main-theorem-1-about-collect-once
    (subsetp (collect-once x) x))
  ; Succeeded!

  ; [0]
  ; (defthm main-theorem-2-about-collect-once
  ;   (not (dupsp (collect-once x))))
  ; Failed!
  ; Key Term:  (MEMBER (CAR X) (COLLECT-ONCE (CDR X)))

  ; [1]
  (defthm member-collect-once
    (iff (member e (collect-once a))
         (member e a)))
  ; Succeeded!

  ; [0]
  (defthm main-theorem-2-about-collect-once
    (not (dupsp (collect-once x))))
  ; Succeeded!

  ; That was really easy!

  ;-----------------------------------------------------------------
  ; Section B:  The While-Loop Version and Its Correctness --
  ;  presented in two parts:  its equivalence to the primitive recursive
  ;  version and then its correctness proved via that equivalence

  ; The tail-recursive, or while-loop version, is defined as follows.  The
  ; function below is the loop itself and it ought to be called with a = nil to
  ; implement the initialization of a in the pseudo-code above.

  (defun while-loop-version (x a)
    (if (endp x)
        a
        (while-loop-version (cdr x)
                            (if (member (car x) a)
                                a
                                (cons (car x) a)))))

  ; We wish to prove that the two are equivalent.  But they are actually
  ; very different.  For example,

  ; (collect-once '(2 4 1 3 1 2 3 4))           = (1 2 3 4)
  ; (while-loop-version '(2 4 1 3 1 2 3 4) nil) = (3 1 4 2)

  ; Things get a little more complicated if a is non-nil:
  ; (while-loop-version '(2 4 1 3 1 2 3 4) '(2 2 4 4)) = (3 1 2 2 4 4)

  ; Several observations help explain what is happening.  (1) Collect-once
  ; collects the last occurrence of each element, in the order of their last
  ; occurrences.  So, for example, since the last occurrence of 2 precedes the
  ; last occurrence of 3 in '(2 4 1 3 1 2 3 4)), then the collected 2 precedes
  ; the collected 3 in the answer.  But while-loop-version collects the first
  ; occurrence of each element, in the reverse order of that occurrence.  So it
  ; adds 2 to its accumulator first and adds 3 last, making 3 precede 2 in the
  ; answer.

  ; (2) The while-loop-version does not collect anything already in a and indeed
  ; just adds stuff to the front of a, returning everything initially in a plus
  ; one occurrence of everything in x not in a.

  ; To state the relationship that holds between these two we have to define two
  ; other functions.

  ; This is our familiar list reverse function...
  (defun rev (x)
    (if (endp x)
        nil
        (append (rev (cdr x))
                (list (car x)))))

  ; And this function ``removes'' from x all the elements in y, i.e., copies x
  ; while dropping the elements of y.

  (defun list-minus (x y)
    (if (endp x)
        nil
        (if (member (car x) y)
            (list-minus (cdr x) y)
            (cons (car x) (list-minus (cdr x) y)))))

  ; The specific equivalence we're really interested in is
  ; (equal (while-loop-version x nil)
  ;        (collect-once (rev x)))

  ; But we will not be able to prove that by induction because it has the
  ; constant nil where we need a variable, a, in order to admit an appropriate
  ; inductive instance.  So we will attack the most general problem.  What is
  ; (while-loop-version x a) equal to, in terms of collect-once?

  ; The most general relationship between the two collection functions is:

  ; (equal (while-loop-version x a)
  ;        (append (collect-once (list-minus (rev x) a)) a))

  ; This formula bears thinking about!  If you're like us, you won't believe it
  ; until it is proved!

  ; [0]
  ; (defthm general-equivalence
  ;   (equal (while-loop-version x a)
  ;          (append (collect-once (list-minus (rev x) a)) a)))
  ; Failed!
  ; Key term in checkpoint:
  ; (LIST-MINUS (APPEND (REV (CDR X)) (LIST (CAR X))) A)

  ; [1]
  (defthm list-minus-append
    (equal (list-minus (append a b) c)
           (append (list-minus a c)
                   (list-minus b c))))
  ; Succeeded!

  ; [0]
  ; (defthm general-equivalence
  ;   (equal (while-loop-version x a)
  ;          (append (collect-once (list-minus (rev x) a)) a)))
  ; Failed!
  ; Key term in checkpoint:
  ; (COLLECT-ONCE (APPEND (LIST-MINUS (REV (CDR X)) A) (LIST (CAR X))))

  ; [1]
  ; (defthm collect-once-append
  ;   (equal (collect-once (append a b))
  ;          (append (list-minus (collect-once a) b)
  ;                  (collect-once b))))
  ; Failed!
  ; Key term:
  ; (MEMBER (CAR A) (APPEND (CDR A) B))

  ; [2]
  (defthm member-append
    (iff (member e (append a b))
         (or (member e a)
             (member e b))))
  ; Succeeded!

  ; [1]
  (defthm collect-once-append
    (equal (collect-once (append a b))
           (append (list-minus (collect-once a)
                               b)
                   (collect-once b))))
  ; Succeeded!

  ; [0]
  ; (defthm general-equivalence
  ;   (equal (while-loop-version x a)
  ;          (append (collect-once (list-minus (rev x) a)) a)))
  ; Failed!
  ; Key term:
  ; (APPEND (APPEND (LIST-MINUS (COLLECT-ONCE (LIST-MINUS (REV (CDR X)) A))

  ; [1]
  (defthm assoc-append
    (equal (append (append a b) c)
           (append a (append b c))))
  ; Succeeded!

  ; [0]
  ; (defthm general-equivalence
  ;   (equal (while-loop-version x a)
  ;          (append (collect-once (list-minus (rev x) a)) a)))
  ; Failed!
  ; Key term:
  ; (LIST-MINUS (COLLECT-ONCE (LIST-MINUS (REV (CDR X)) A)) ...)

  ; This key term makes us think of the lemma to move the LIST-MINUS inside the
  ; COLLECT-ONCE.  But when that's done, we will have two LIST-MINUS terms
  ; nestled together and we will want to combine them into one.  Call these two
  ; lemmas (a) and (b).

  ; [1] (a)
  ; (defthm list-minus-collect-once
  ;   (equal (list-minus (collect-once x) a)
  ;          (collect-once (list-minus x a))))
  ; Failed!
  ; Key term:
  ; (MEMBER (CAR X) (LIST-MINUS (CDR X) A))

  ; [2] (A pretty fact)
  (defthm member-list-minus
    (iff (member e (list-minus x a))
         (and (member e x)
              (not (member e a)))))
  ; Succeeded!

  ; [1] (a)
  (defthm list-minus-collect-once
    (equal (list-minus (collect-once x) a)
           (collect-once (list-minus x a))))
  ; Succeeded!

  ; [1] (b)
  (defthm list-minus-list-minus
    (equal (list-minus (list-minus x a) b)
           (list-minus x (append b a))))
  ; Succeeded!

  ; [0]
  (defthm general-equivalence
    (equal (while-loop-version x a)
           (append (collect-once (list-minus (rev x) a)) a)))
  ; Succeeded!

  ; That completes the proof of the ``equivalence'' of the two methods.

  ; Now we prove (1) that the result of while-loop-version is a subset, and (2)
  ; that it contains no duplications.  We prove the two conjuncts separately.

  ; [0]
  (defthm main-theorem-1-about-while-loop
    (subsetp (while-loop-version x nil) x))
  ; Succeeded!

  ; But the theorem prover works harder to do the proof above than one might have
  ; expected because it doesn't turn into an instance of
  ; main-theorem-1-about-collect-once because of the presence of the rev term.
  ; However, we're content that ACL2 managed to do the proof on its own.

  ; [0]
  (defthm main-theorem-2-about-while-loop
    (not (dupsp (while-loop-version x nil))))

  ; So we see that the proof of correctness of while-loop-version isn't hard,
  ; after we establish the relationship with the primitive recursive version.
  ; But finding and proving the relationship is fairly challenging.

  ; -----------------------------------------------------------------
  ; Section C:  A Direct Proof of the Correctness of the While-Loop Version

  ; Some would consider the proof in Section B ``indirect'' because we first showed
  ; how while-loop-version could be expressed as a collect-once and then proved
  ; our main theorems about while-loop-version, which means those main proofs
  ; were conducted in terms of collect-once, not while-loop-version.

  ; It is interesting to compare this proof with the ``direct'' one in which
  ; we don't use collect-once at all and reason only about while-loop-version.

  ; So to do that comparison, let's disable all the lemmas we've proved about
  ; while-loop-version and try to prove the two main theorems above about
  ; while-loop-version.

  (in-theory (disable general-equivalence
                      main-theorem-1-about-while-loop
                      main-theorem-2-about-while-loop))

  ; [0]
  ; (defthm main-theorem-1-about-while-loop-redux
  ;   (subsetp (while-loop-version x nil) x))
  ; Failed!  [Well, the truth is below...]

  ; We don't even submit this event above because we recognize that it is not
  ; general enough to permit proof by induction.  We need to deal with the nil in
  ; the second argument of while-loop-version.  Experience with induction tells
  ; us this should be a variable, so we can assume an appropriate inductive
  ; instance.  Therefore, we adopt this subgoal immediately:

  ; [1]
  ; (defthm main-lemma-1-about-while-loop-version
  ;   (subsetp (while-loop-version x a) (append x a)))
  ; Failed!
  ; Key Term:  Does the wrong induction.

  ; [1]
  ; (defthm main-lemma-1-about-while-loop-version
  ;   (subsetp (while-loop-version x a) (append x a))
  ;   :hints ((\"Goal\" :induct (while-loop-version x a))))
  ; Failed!  Two key terms are suggested
  ; Key term: (IMPLIES (AND ... (SUBSETP (WHILE-LOOP-VERSION (CDR X) A) (APPEND (CDR X) A)))
  ;                    (SUBSETP (WHILE-LOOP-VERSION (CDR X) A) (CONS ... (APPEND (CDR X) A))))
  ; Key term: (SUBSETP A A)
  ; So we'll prove both before trying again.
  ; [2]
  (defthm subsetp-cons
    (implies (subsetp a b)
             (subsetp a (cons e b))))
  ; Succeeded!

  ; [2]
  (defthm subsetp-reflexive
    (subsetp a a))
  ; Succeeded!

  ; [1]
  ; (defthm main-lemma-1-about-while-loop-version
  ;   (subsetp (while-loop-version x a) (append x a))
  ;   :hints ((\"Goal\" :induct (while-loop-version x a))))
  ; Failed!
  ; Key Term:
  ; (IMPLIES (AND ...
  ;               (SUBSETP (WHILE-LOOP-VERSION (CDR X) (CONS (CAR X) A))
  ;                        (APPEND (CDR X) (CONS (CAR X) A))))
  ;          (SUBSETP (WHILE-LOOP-VERSION (CDR X) (CONS (CAR X) A))
  ;                   (CONS (CAR X) (APPEND (CDR X) A))))

  ; We'd be done if we could rewrite the
  ; (APPEND (CDR X) (CONS (CAR X) A))
  ; to
  ; (CONS (CAR X) (APPEND (CDR X) A))
  ; These two terms are not equal!  But they are ``set-equal'' and this kind of
  ; rewriting is possible using user-defined equivalences and congruence rules.
  ; But the new user should not dive into congruences yet.  So we will do this
  ; with ordinary lemmas:

  ; The plan then is to prove the rewrite rule
  ; (iff (subsetp a (append b (cons e c)))
  ;      (subsetp a (cons e (append b c))))
  ; in order to rewrite the first call of SUBSETP shown in the key term above
  ; to the second call.

  ; Consider the first half of this bi-implication:
  ; (implies (subsetp a (append b (cons e c)))            ; hyp1
  ;          (subsetp a (cons e (append b c))))           ; concl
  ; Notice that if we knew
  ; (subsetp (append b (cons e c)) (cons e (append b c))) ; hyp2
  ; then we could use hyp1 and hyp2 together with the transitivity of
  ; subsetp to get concl.

  ; The proof in the other direction is comparable but requires the
  ; (subsetp (cons e (append b c)) (append b (cons e c)))

  ; Thus, our plan is prove
  ; (a) transitivity of subsetp
  ; (b) (subsetp (append b (cons e c)) (cons e (append b c)))
  ; (c) (subsetp (cons e (append b c)) (append b (cons e c)))

  ; in order to prove
  ; (d) (iff (subsetp a (append b (cons e c)))
  ;         (subsetp a (cons e (append b c))))

  ; [2] (a)
  (defthm trans-subsetp
    (implies (and (subsetp a b)
                  (subsetp b c))
             (subsetp a c)))
  ; Succeeded!

  ; [2] (b)
  (defthm append-cons-v-cons-append-1
    (subsetp (append b (cons e c))
             (cons e (append b c))))
  ; Succeeded!

  ; [2] (c)
  (defthm append-cons-v-cons-append-2
    (subsetp (cons e (append b c))
             (append b (cons e c))))
  ; Succeeded!

  ; [2] (d)
  (defthm subsetp-append-cons-cons-append
    (iff (subsetp a (append b (cons e c)))
         (subsetp a (cons e (append b c)))))
  ; Succeeded!

  ; [1]
  (defthm main-lemma-1-about-while-loop-version
    (subsetp (while-loop-version x a) (append x a))
    :hints ((\"Goal\" :induct (while-loop-version x a))))
  ; Succeeded!

  ; [0]
  ; (defthm main-theorem-1-about-while-loop-version
  ;   (subsetp (while-loop-version x nil) x))
  ; Failed!  [But the truth is below...]

  ; But we don't submit this because we don't expect it to be proved
  ; from the main lemma just proved:  they don't match!  But
  ; note that if we instantiated the main lemma, replacing a by nil,
  ; we get:

  ; (subsetp (while-loop-version x nil) (append x nil))

  ; and we could simplify the (append x nil) to x in this context, with
  ; another congruence rule -- if we were using them.  So let's prove
  ; first that we can simplify (append x nil) inside a subsetp:

  ; [1]
  (defthm subsetp-append-nil
    (iff (subsetp x (append y nil))
         (subsetp x y)))
  ; Succeeded!

  ; and then just tell ACL2 how to use the lemma to get the main theorem.  Note
  ; that we give a hint to instantiate main-lemma-1... but we also disable
  ; main-lemma-1... because otherwise it will rewrite itself away!  Once the
  ; instance of main-lemma-1... is sitting around as a hypothesis,
  ; subsetp-append-nil will rewrite the (append x nil) to x for us and finish the
  ; proof.

  ; [0]
  (defthm main-theorem-1-about-while-loop-version
    (subsetp (while-loop-version x nil) x)
    :hints ((\"Goal\"
             :use (:instance main-lemma-1-about-while-loop-version
                             (x x)
                             (a nil))
             :in-theory (disable main-lemma-1-about-while-loop-version))))
  ; Succeeded!

  ; Recall that the main-theorem-1... just proved is just half of what we want.
  ; We also want:

  ; [0]
  ; (defthm main-theorem-2-about-while-loop-version
  ;   (not (dupsp (while-loop-version x nil))))
  ; Failed!  [But the truth is below...]

  ; But, again, we don't submit that because the nil makes it not general enough for
  ; induction.  Instead we go immediately to:

  ; [1]
  (defthm main-lemma-2-about-while-loop-version
    (implies (not (dupsp a))
             (not (dupsp (while-loop-version x a)))))
  ; Succeeded!

  ; This time we know our main-lemma-2... will match (there's no (append x nil)
  ; in there to mess things up) and so we can complete the proof with:

  ; [0]
  (defthm main-theorem-2-about-while-loop-version
    (not (dupsp (while-loop-version x nil))))
  ; Succeeded!

  ;-----------------------------------------------------------------
  ; Section D:  Lessons Learned

  ; The most obvious lesson is that it is easier to reason about the primitive
  ; recursive collect-once than about the while-loop-version.  Thus, if your only
  ; need is for a function that collects one occurrence of each element of a list
  ; and you don't care about the order in which you collect them and you don't
  ; need it to be very sparing of stack space when it executes, then use the
  ; primitive recursive definition and don't even think about while loops!

  ; So why might you be driven to while-loop-version?  One possibility is that
  ; the list you wish to process is very long and the primitive recursive version
  ; would produce a stack overflow.  In ACL2, that would mean the list would have
  ; to be several thousand long.  Is your application really so demanding?

  ; Another possibility is that you are modeling in Lisp a while loop expressed
  ; in some other programming language.  In that case, the fidelity of your model to
  ; the artifact being modeled is important and you should use while-loop-version.

  ; Another possibility is that for some reason order matters and you really are
  ; interested in collecting the first occurrence rather than the last.  Of
  ; course this is most likely to be relevant in more interesting applications
  ; where the occurrences are somehow distinguishable.

  ; If you are forced to deal with the while-loop-version the question is do you
  ; do an indirect proof as in Section B or a direct proof as in Section C?
  ; The indirect proof involved 10 theorems and the direct proof involved 11.
  ; That is not a significant difference.

  ; But our sense is that the indirect proof is easier to find, once you figure
  ; out the basic shape of the relation between while-loop-version and
  ; collect-once.  In particular, we had to give the theorem prover two hints
  ; in the direct proof (versus no hints in the indirect proof).  One of our
  ; hints was about what induction to do and the other was about how to use a
  ; previously proved instance of a lemma involving an accumulator.
  ; Furthermore, we had to think carefully about the use of the transitivity of
  ; subsetp and we had to hack our way around rewriting (append a (cons e b))
  ; to (cons e (append a b)) in a subsetp-expression.

  ; Some of these ``set'' problems could have been handled a lot more elegantly
  ; by defining set-equal as an equivalence relation and proving the congruence
  ; rules to allow the rewriting of set-equal terms to set-equal terms inside
  ; certain expressions like subsetp and member.  However, that involves a lot
  ; of overhead in the form of congruence rules showing that set-equality is
  ; maintained by replacement of set-equals by set-equals in various argument
  ; positions of the various functions.  See :doc congruence.  In general, we
  ; find congruence-based reasoning extremely neat and powerful when the
  ; appropriate infrastructure has been built up.  But because the
  ; infrastructure is ``heavy'' we tend not to invest in it for small projects.

  ; In summary, different users might take home different lessons about whether a
  ; direct or indirect proof is better here.  This is in part due to the
  ; complexity of the functional relationship between collect-once and
  ; while-loop-version, which additionally involved append, list-minus, and rev.
  ; Had the relationship been simpler, the indirect proof would have been
  ; preferred.

  ; An undeniable lesson, however, is that it is helpful to know both styles of
  ; proof and to be able to explore both as needed in your applications.
 })

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 introductory-challenge-problem-4).</p>")

(defxdoc introductory-challenges
  :parents (introduction-to-the-theorem-prover)
  :short "Challenge problems for the new ACL2 user"
  :long "<p>Do each of the problems.  In each case, start with a fresh ACL2 (or
 undo all effects of previous events with @(':ubt! 1')).  This may require that
 you ``re-discover'' the same lemma more than once in different problems, but
 recognizing the need for something you used in some previous project is part
 of the training.</p>

 <p>We recommend that you follow The Method and consult the documentation as
 needed &mdash; but that you not look at our answers until you're well and
 truly baffled!</p>

 <p>See @(see introductory-challenge-problem-1) (Answer: @(see
 introductory-challenge-problem-1-answer))</p>

 <p>See @(see introductory-challenge-problem-2) (Answer: @(see
 introductory-challenge-problem-2-answer))</p>

 <p>See @(see introductory-challenge-problem-3) (Answer: @(see
 introductory-challenge-problem-3-answer))</p>

 <p>See @(see introductory-challenge-problem-4) (Answer: @(see
 introductory-challenge-problem-4-answer))</p>

 <p>In addition to these explicit challenge problems designed for beginners,
 the ACL2 documentation has many example solutions to problems (not always
 phrased in the question/answer format here).  If you are looking for other
 examples, you should consider</p>

 <p>@(see annotated-acl2-scripts) (Answer: the answers are given in the
 examples)</p>

 <p>When you've done the problems and compared your solutions to ours, use your
 browser's <b>Back Button</b> now to return to @(see
 introduction-to-the-theorem-prover).</p>")

(defxdoc invariant-risk
  :parents (programming advanced-features guard debugging)
  :short "Potential slowdown for @(see program)-mode updates to @(see stobj)s
 or @(see arrays)"
  :long "<p>You may see a warning like this:</p>

 @({
 ACL2 Warning [Invariant-risk] in MY-FUNCTION:  Invariant-risk has been
 detected for a call of function MY-FUNCTION (as possibly leading to
 an ill-guarded call of UPDATE-FLD); see :DOC invariant-risk.
 })

 <p>Such warnings indicate potential slowdown due to aggressive protection by
 ACL2 against either:</p>

 <ul>

 <li>writing a value of the wrong type to a @(see stobj) field; or</li>

 <li>performing an out-of-bounds write to an ACL2 @(see array).</li>

 </ul>

 <p>Whenever a @(':')@(tsee program) mode function call can perhaps lead to
 such a write, @(see guard)-checking is performed by ACL2, even though the
 normal expectation is to execute without such checks in Common Lisp; see @(see
 evaluation).  Consider the following example.</p>

 @({
 (defstobj st (fld :type integer :initially 0))

 (defun f (n st)
   (declare (xargs :stobjs st :guard (integerp n)))
   (update-fld n st))

 ; This :program-mode wrapper for f fails to require (integerp n):
 (defun g (n st)
   (declare (xargs :stobjs st :mode :program))
   (f n st))

 ; Produces an invariant-risk warning:
 (g 3 st)

 ; Produces an invariant-risk warning and a guard violation:
 (g 'a st)
 })

 <p>Each of the two calls of @('g') produces an @('\"Invariant-risk\"')
 warning, and indeed @(see guard)s are checked for the ensuing calls of @('f'),
 causing a guard violation for the second call of @('g').</p>

 <p>There are two general methods for avoiding such warnings: at runtime with
 @(tsee set-check-invariant-risk), and at definition time with @(tsee
 set-register-invariant-risk).  We describe each briefly below.  For more
 information follow the links just above to their respective documentation
 topics.  For yet more detail about invariant-risk see @(see
 invariant-risk-details).</p>

 <h3>Controlling runtime checking for invariant-risk</h3>

 <p>You can avoid seeing warnings like the one displayed above (without
 affecting the check that is actually performed) by evaluating either one of
 the following forms.</p>

 @({
 (set-check-invariant-risk t)
 (set-inhibit-warnings \"invariant-risk\")
 })

 <p>You can also replace such warnings by errors:</p>

 @({
 (set-check-invariant-risk :error)
 })

 <p>Evaluate @('(get-check-invariant-risk state)') to see the current setting
 for invariant-risk checking.  For details, including a dangerous way to remove
 invariant-risk checking completely at runtime, see @(see
 set-check-invariant-risk).</p>

 <h3>Eliminating invariant-risk checking done by specific functions</h3>

 <p>On occasion you may define functions that you know avoid invariant-risk
 danger, even though ACL2 designates those functions as having invariant-risk.
 Rather than removing invariant-risk checking for <i>all</i> functions at
 runtime with @(tsee set-check-invariant-risk), it is probably much safer to
 remove it only for the functions in a given book or @(tsee encapsulate) event.
 See @(see set-register-invariant-risk) for how to do that.</p>")

(defxdoc invariant-risk-details
  :parents (invariant-risk)
  :short "More details about @(see invariant-risk)"
  :long "<p>This topic, which may be unnecessary for most ACL2 users, expands
 on the documentation for @(see invariant-risk).  See that topic and see @(see
 evaluation) for relevant background.</p>

 <p>We refer below to the following example, which is slightly expanded from
 the one in the documentation for @(see invariant-risk).</p>

 @({
 (defstobj st (fld :type integer :initially 0))

 (defun f1 (n st)
   (declare (xargs :stobjs st :guard (integerp n)))
   (update-fld n st))

 (defun f2 (n st)
   (declare (xargs :stobjs st :guard (integerp n)))
   (f1 n st))

 ; This :program-mode wrapper for f fails to require (integerp n):
 (defun g (n st)
   (declare (xargs :stobjs st :mode :program))
   (f2 n st))

 ; Trace f1 and f2 and their *1* functions.  (This is optional.)
 (trace$ f1 f2 g)

 ; Produces an invariant-risk warning; only *1* functions are called.
 (g 3 st)

 ; Produces an invariant-risk warning and a guard violation:
 (g 'a st)

 ; Defeat invariant-risk checking (risky; uses a trust tag):
 (set-check-invariant-risk nil)

 ; No warning because *1* functions are not called.
 (g 3 st)

 ; No warning because *1* functions are not called.
 (g 'a st)

 ; Non-integer field value!
 (assert-event (equal (fld st) 'a))
 })

 <p>To understand invariant-risk, consider the case that a @(see stobj)
 updater (such as @('update-fld') above) is called on ill-guarded arguments.
 In that case the resulting ACL2 @(see state) could be ill-formed, as in the
 example above: after turning off invariant-risk checking, the stobj @('st') is
 defined to have an integer field yet winds up with a symbol in that field.
 ACL2 arranges invariant-risk checking by installing special code in the
 executable-counterpart of a @(':')@(tsee program)-mode function to prevent it
 from calling its corresponding submitted function.  It does this when the
 @(':program')-mode function has a non-nil @(''invariant-risk') property; in
 the example above, note:</p>

 @({
 ACL2 !>(getpropc 'g 'invariant-risk)
 UPDATE-FLD
 ACL2 !>
 })

 <p>When the function symbol @('g') was defined, it inherited this property
 from @('f2'), which in turn inherited it from @('f1'), which in turn inherited
 it from the stobj updater, @('update-fld').  However, the aforementioned
 special code is only installed for @(':program') mode functions, hence not for
 @('f1') or @('f2').  Consider for example the following trace, from the call
 of @('(g 3)') made above before turning off invariant-risk checking.</p>

 @({
 1> (ACL2_*1*_ACL2::G 3 |<st>|)

 ACL2 Warning [Invariant-risk] in G:  Invariant-risk has been detected
 for a call of function G (as possibly leading to an ill-guarded call
 of UPDATE-FLD); see :DOC invariant-risk.

   2> (ACL2_*1*_ACL2::F2 3 |<st>|)
     3> (F2 3 |<st>|)
       4> (F1 3 |<st>|)
       <4 (F1 |<st>|)
     <3 (F2 |<st>|)
   <2 (ACL2_*1*_ACL2::F2 |<st>|)
 <1 (ACL2_*1*_ACL2::G |<st>|)
 <st>
 ACL2 !>
 })

 <p>This trace illustrates that even though @('f2') has the
 @(''invariant-risk') property, its executable-counterpart has permission to
 call its submitted function because @('f2') is a guard-verified
 @(':logic')-mode function.</p>

 <p>As an optimization, ACL2 avoids setting the @(''invariant-risk') property
 on @(':')@(tsee logic) mode functions whose @(see guard) is @('t') or, more
 generally, a conjunction of @(see stobj) recognizer calls.  For example, the
 call of @('(bar 3 st)') below does not cause an invariant-risk warning.</p>

 @({
 (progn (defstobj st (reg :type (array (unsigned-byte 31) (8))
                          :initially 0))
        (defun foo (i st)
          (declare (xargs :guard t :stobjs st))
          (if (eql i 0) (update-regi i 3 st) st))
        (defun bar (i st)
          (declare (xargs :stobjs st :mode :program))
          (foo i st)))
 (bar 3 st)
 })

 <p>This optimization can hold even if the function is originally submitted
 without guard verification (typically, using @(see xargs) declaration
 @(':verify-guards nil')), but only if its guards are verified before defining the
 @(':program')-mode wrapper (e.g., @('bar') above).  Thus we see an
 invariant-risk warning in the call of @('bar') below.</p>

 @({
 (progn (defstobj st (reg :type (array (unsigned-byte 31) (8))
                          :initially 0))
        (defun foo (i st)
          (declare (xargs :guard t :stobjs st :VERIFY-GUARDS NIL))
          (if (eql i 0) (update-regi i 3 st) st))
        (defun bar (i st)
          (declare (xargs :stobjs st :mode :program))
          (foo i st))
        (verify-guards foo) ; avoid invariant-risk by moving before bar
        )
 (bar 3 st) ; invariant-risk
 })

 <p>Here is code that will return a list of all @(':program')-mode functions
 subject to invariant-risk checking that are user-defined (not built into
 ACL2).</p>

 @({
 :q ; go into raw Lisp
 (let (ans (wrld (w *the-live-state*)))
   (dolist (p (list-all-packages))
     (do-symbols (sym p)
       (when (and (getpropc sym 'invariant-risk)
                  (programp sym wrld)
                  (not (getpropc sym 'predefined)))
         (push sym ans))))
   ans)
 })

 <p>To see exactly the executable-counterpart code generated for a
 @(':program')-mode function with invariant-risk, evaluate
 @('(trace! (oneify-cltl-code :native t))') before submitting its
 definition.</p>")

(defxdoc invisible-fns-table
  :parents (loop-stopper)
  :short "Functions that are invisible to the @(see loop-stopper) algorithm"
  :long "@({
  Examples:
  ACL2 !>(invisible-fns-table (w state))
  ((binary-+ unary--)
   (binary-* unary-/)
   (unary-- unary--)
   (unary-/ unary-/))
 })

 <p>Among other things, the setting above has the effect of making @(tsee
 unary--) ``invisible'' for the purposes of applying permutative @(':')@(tsee
 rewrite) rules to @(tsee binary-+) trees.  Also see @(see add-invisible-fns)
 and see @(see remove-invisible-fns), which manage macro aliases (see @(see
 macro-aliases-table)), as well as see @(see set-invisible-fns-table).</p>

 <p>See @(see table) for a general discussion of tables.</p>

 <p>The ``invisible functions @(see table)'' is an alist with elements of the
 following form, where @('fn') is a function symbol and the @('ufni') are unary
 function symbols in the current ACL2 @(see world), and @('k') is at least
 1.</p>

 @({
  (fn ufn1 ufn2 ... ufnk)
 })

 <p>This @(see table) thus associates with certain function symbols, e.g.,
 @('fn') above, a set of unary functions, e.g., the @('ufni') above.  The
 @('ufni') associated with @('fn') in the invisible functions table are said to
 be ``invisible with respect to @('fn').''  If @('fn') is not the @(tsee car)
 of any pair in the @('alist'), then no function is invisible for it.  Thus for
 example, setting the invisible functions alist to @('nil') completely
 eliminates the consideration of invisibility.</p>

 <p>The notion of invisibility is involved in the use of the @(':')@(tsee
 loop-stopper) field of @(':')@(tsee rewrite) rules to prevent the indefinite
 application of permutative rewrite rules.  Roughly speaking, if rewrite rules
 are being used to permute @('arg') and (ufni arg) inside of a nest of @('fn')
 calls, and @('ufni') is invisible with respect to @('fn'), then @('arg') and
 @('(ufni arg)') are considered to have the same ``weight'' and will be
 permuted so as to end up as adjacent tips in the @('fn') nest.  See @(see
 loop-stopper).</p>")

(defxdoc io
  :parents (interfacing-tools

; We include programming and state because of pointers like open-output-channel
; and get-output-stream-string$, among others.

            state programming)
  :short "Input/output facilities in ACL2"
  :long "@({
  Example:
  (mv-let
    (channel state)
    (open-input-channel \"foo.lisp\" :object state)
    (mv-let (eofp obj state)
            (read-object channel state)
            (.
              .
               (let ((state (close-input-channel channel state)))
                     (mv final-ans state))..)))
 })

 <p>Also see @(see std/io) and @(see file-reading-example).</p>

 <p>For advanced ways to control printing, see @(see print-control).</p>

 <p>For a discussion of formatted printing, see @(see fmt).</p>

 <p>To control ACL2 abbreviation (``evisceration'') of objects before printing
 them, see @(see set-evisc-tuple), see @(see without-evisc), and see @(see
 set-iprint).</p>

 <p>To redirect output to a file, see @(see output-to-file).</p>

 <p>ACL2 supports input and output facilities equivalent to a subset of those
 found in Common Lisp.  ACL2 does not support random access to files or
 bidirectional streams.  In Common Lisp, input and output are to or from
 objects of type @('stream').  In ACL2, input and output are to or from objects
 called ``channels,'' which are actually symbols.  Although a channel is a
 symbol, one may think of it intuitively as corresponding to a Common Lisp
 stream.  Channels are in one of two ACL2 packages, @('\"ACL2-INPUT-CHANNEL\"')
 and @('\"ACL2-OUTPUT-CHANNEL\"').  When one ``opens'' a file one gets back a
 channel whose @(tsee symbol-name) is the file name passed to ``open,''
 postfixed with @('-n'), where @('n') is a counter that is incremented every
 time an open or close occurs.</p>

 <p>There are three channels which are open from the beginning and which cannot
 be closed:</p>

 @({
    acl2-input-channel::standard-character-input-0
    acl2-input-channel::standard-object-input-0
    acl2-input-channel::standard-character-output-0
 })

 <p>All three of these are really Common Lisp's @('*standard-input*') or
 @('*standard-output*'), appropriately.</p>

 <p>For convenience, three global variables are bound to these rather tedious
 channel names:</p>

 @({
    *standard-ci*
    *standard-oi*
    *standard-co*
 })

 <p>Common Lisp permits one to open a stream for several different kinds of
 @('io'), e.g. character or byte.  ACL2 permits an additional type called
 ``object''.  In ACL2 an ``io-type'' is a keyword, either @(':character'),
 @(':byte'), or @(':object').  When one opens a file, one specifies a type,
 which determines the kind of io operations that can be done on the channel
 returned.  The types @(':character') and @(':byte') are familiar.  Type
 @(':object') is an abstraction not found in Common Lisp.  An @(':object') file
 is a file of Lisp objects.  One uses @('read-object') or
 @('read-object-with-case') (see below) to read from @(':object') files and
 @('print-object$') or @('print-object$-preserving-case') (see below; also,
 @('print-object$-ser')) to print to @(':object') files.  (The reading and
 printing are really done with the Common Lisp @('read') and printing
 functions.  For those familiar with @('read'), we note that the
 @('recursive-p') argument is @('nil').)  The function
 @('read-object-suppress') is logically the same as @('read-object') except
 that @('read-object-suppress') throws away the second returned value, i.e. the
 value that would normally be read, simply returning @('(mv eof state)'); under
 the hood, @('read-object-suppress') avoids errors, for example those caused by
 encountering symbols in packages unknown to ACL2.</p>

 <p>The functions @('read-object-with-case') and
 @('print-object$-preserving-case') are logically defined simply to be
 @('read-object') and @('print-object$'), respectively, though they do I/O
 differently from those functions, except when the host Lisp is GCL.  For
 @('read-object-with-case') the value that is read is affected by an extra
 argument, namely, the second argument: the <i>mode</i>.  The mode is one of
 the keywords @(':upcase'), @(':downcase'), @(':preserve'), or @(':invert'),
 where @(':upcase') gives the same behavior as @('read-object'), and the other
 three modes are handled according to the specification for the Common Lisp
 function, @('readtable-case') (see for example <a
 href='http://www.lispworks.com/documentation/HyperSpec/Body/23_aba.htm'>the
 Common Lisp HyperSpec's documentation for ``Examples of Effect of Readtable
 Case on the Lisp Reader''</a>).  The function
 @('print-object$-preserving-case') is somewhat analogous: it is defined
 logically to be @('print-object$') and it has the same behavior, except that
 symbols are printed without adding escapes merely because of lowercase
 letters; for example, the symbol in the current package with name @('\"abc\"')
 will be printed as @('abc'), not as @('|abc|').  But note that
 @('print-object$-preserving-case') may still insert vertical bars, depending
 on the host Lisp, because different Lisp implementations choose to escape
 symbols differently.  Consider the symbol typically printed as @('|1u|').
 Using @('print-object$-preserving-case'), this prints simply as @('1u') in
 CCL and Allegro CL, but it is printed as @('|1u|') in SBCL, LispWorks, and
 CMUCL &mdash; at least in the implementations that we tested!</p>

 <p>File-names are strings.  ACL2 does not support the Common Lisp type @(tsee
 pathname).  However, for the @('file-name') argument of the output-related
 functions listed below, ACL2 supports a special value, @(':STRING').  For this
 value, the channel connects (by way of a Common Lisp output string stream) to
 a string rather than to a file: as characters are written to the channel they
 can be retrieved by using @('get-output-stream-string$').</p>

 <p>Here are the names, formals and output descriptions of the ACL2 io
 functions.</p>

 @({
  Input Functions:
    (open-input-channel (file-name io-type state) (mv channel state))
    (open-input-channel-p (channel io-type state) boolean)
    (close-input-channel (channel state) state)
    (read-char$ (channel state) (mv char/nil state)) ; nil for EOF
    (peek-char$ (channel state) char/nil)
    (read-byte$ (channel state) (mv byte/nil state)) ; nil for EOF
    (read-object (channel state) (mv eof-read-flg obj-read state))
    (read-object-with-case (channel mode state) (mv eof-read-flg obj-read state))
    (read-object-suppress (channel state) (mv eof-read-flg state))
    (read-file-into-string (file-name &key..) string/nil) ; macro (reads state)

  Output Functions:
    (open-output-channel  (file-name io-type state) (mv channel state))
    (open-output-channel! (file-name io-type state) (mv channel state))
    (open-output-channel-p (channel io-type state) boolean)
    (close-output-channel (channel state) state)
    (princ$ (obj channel state) state)
    (write-byte$ (byte channel state) state)
    (print-object$ (obj channel state) state)
    (print-object$-preserving-case (obj channel state) state)
    (print-object$-ser (obj serialize-character channel state) state)
    (fms  (string alist channel state evisc-tuple) state)
    (fms! (string alist channel state evisc-tuple) state)
    (fmt  (string alist channel state evisc-tuple) (mv col state))
    (fmt! (string alist channel state evisc-tuple) (mv col state))
    (fmt1 (string alist col channel state evisc-tuple) (mv col state))
    (fmt1! (string alist col channel state evisc-tuple) (mv col state))
    (cw (string arg0 arg1 ... argn) nil)
    (get-output-stream-string$ (channel state
                                &optional (close-p 't)
                                          (ctx ''get-output-stream-string$))
                               (mv erp string state))
 })

 <p>Note that @('open-output-channel') and @('open-output-channel!') will
 attempt to create directories as needed (but this is not the case for
 @('open-input-channel')).  For example, the following can succeed in writing
 to the indicated file by creating subdirectory @('\"dir4\"') if that directory
 does not already exist.</p>

 @({
 (mv-let
   (channel state)
   (open-output-channel \"dir4/foo4\" :object state)
   (pprogn (fms \"Here: ~x0\"
                (list (cons #\\0 (make-list 10)))
                channel state nil)
           (close-output-channel channel state)))
 })

 <p>The ``formatting'' functions are particularly useful; see @(see fmt) and
 see @(see cw).  In particular, @(tsee cw) prints to a ``comment window'' and
 does not involve the ACL2 @(tsee state), so many may find it easier to use
 than @(tsee fmt) and its variants.  The functions @(tsee fms!), @(tsee fmt!),
 and @(tsee fmt1!) are the same as their respective functions without the
 ``@('!'),'' except that the ``@('!')'' functions are guaranteed to print forms
 that can be read back in (at a slight readability cost).</p>

 <p>When one enters ACL2 with @('(lp)'), input and output are taken from @(tsee
 *standard-oi*) to @(tsee *standard-co*).  Because these are synonyms for
 @('*standard-input*') and @('*standard-output*'), one can drive ACL2 io off of
 arbitrary Common Lisp streams, bound to @('*standard-input*') and
 @('*standard-output*') before entry to ACL2.</p>

 <p>The macro @('get-output-stream-string$') returns the string accumulated
 into the given channel.  By default, a call of this macro closes the supplied
 output channel.  However, a third argument is optional (default @('t')), and
 if it evaluates to @('nil') then the channel remains open.  The fourth
 argument is an optional context, which generally evaluates to a symbol, for
 error reporting.  The following example illustrates.</p>

 @({
  ACL2 !>
  (mv-let
     (channel state)
     (open-output-channel :string :object state)
     (pprogn (print-object$-ser 17 nil channel state)
             (print-object$-ser '(a b (c d)) nil channel state)
             (er-let*
               ((str1 (get-output-stream-string$
                       channel state
                       nil))) ; keep the channel open
               (pprogn (print-object$-ser 23 nil channel state)
                       (print-object$-ser '((e f)) nil channel state)
                       (er-let* ; close the channel
                         ((str2 (get-output-stream-string$ channel state)))
                         (value (cons str1 str2)))))))
   (\"
  17
  (A B (C D))\" . \"
  23
  ((E F))\")
  ACL2 !>
 })

 <p>Also see @(see printing-to-strings) for a discussion of formatted printing
 functions such as @('fmt-to-string') that do not take a channel or @(tsee
 state) argument and return a string.</p>

 <p>By default, symbols are printed in upper case when vertical bars are not
 required, as specified by Common Lisp.  See @(see set-print-case) for how to
 get ACL2 to print symbols in lower case.</p>

 <p>By default, numbers are printed in radix 10 (base 10).  See @(see
 set-print-base-radix) for how to get ACL2 to print numbers in radix 2, 8, or
 16.</p>

 <p>To see the @(see guard) of an IO function, or indeed any function, see
 @(see args) or call the function @('guard'); but some built-in functions
 (including some IO functions) will print the result using the variable
 @('STATE-STATE').  While that is logically correct, if you want to execute the
 guard then you should replace that variable by @('STATE') and also replace
 each built-in function symbol of the form @('xxx-p1') by corresponding
 function symbol @('xxx-p').  Consider the following example.</p>

 @({
  ACL2 !>:args princ$

  Function         PRINC$
  Formals:         (X CHANNEL STATE-STATE)
  Signature:       (PRINC$ * * STATE)
                   => STATE
  Guard:           (AND (OR (ACL2-NUMBERP X)
                            (CHARACTERP X)
                            (STRINGP X)
                            (SYMBOLP X))
                        (STATE-P1 STATE-STATE)
                        (SYMBOLP CHANNEL)
                        (OPEN-OUTPUT-CHANNEL-P1 CHANNEL
                                                :CHARACTER STATE-STATE))
  Guards Verified: T
  Defun-Mode:      :logic
  Type:            (CONSP (PRINC$ X CHANNEL STATE-STATE))
  Documentation available via :DOC
   PRINC$
  ACL2 !>(untranslate (guard 'princ$ nil (w state)) t (w state))
  (AND (OR (ACL2-NUMBERP X)
           (CHARACTERP X)
           (STRINGP X)
           (SYMBOLP X))
       (STATE-P1 STATE-STATE)
       (SYMBOLP CHANNEL)
       (OPEN-OUTPUT-CHANNEL-P1 CHANNEL
                               :CHARACTER STATE-STATE))
  ACL2 !>
 })

 <p>If you want to execute the guard for @(tsee princ$), then according to the
 suggestion above, you should consider the guard for @('(princ$ x channel
 state)') to be as follows.</p>

 @({
  (AND (OR (ACL2-NUMBERP X)
           (CHARACTERP X)
           (STRINGP X)
           (SYMBOLP X))
       (STATE-P STATE)
       (SYMBOLP CHANNEL)
       (OPEN-OUTPUT-CHANNEL-P CHANNEL :CHARACTER STATE))
 })

 <p>For example, we can check the guard for a given value and channel as
 follows.</p>

 @({
  ACL2 !>(let ((x 3) (channel *standard-co*))
           (AND (OR (ACL2-NUMBERP X)
                    (CHARACTERP X)
                    (STRINGP X)
                    (SYMBOLP X))
                (STATE-P STATE)
                (SYMBOLP CHANNEL)
                (OPEN-OUTPUT-CHANNEL-P CHANNEL :CHARACTER STATE)))
  T
  ACL2 !>
 })

 <p>Comment for advanced users: Function @(tsee open-output-channel!) is
 identical as a function to @('open-output-channel'), except that the former
 may be called even during @(tsee make-event) expansion and @(tsee
 clause-processor) @(see hints), but requires that there is an active trust tag
 (see @(see defttag)).</p>

 <p>Finally, we note that the @(see std/io) library contains useful file io
 functions whose definitions illustrate some of the features described
 above.</p>")

(defxdoc irrelevant-formals
  :parents (programming)
  :short "Formals that are used but only insignificantly"
  :long "<p>Let @('fn') be a function of @('n') arguments.  Let @('x') be the
 @('i')th formal of @('fn').  We say @('x') is ``irrelevant in @('fn')'' if
 @('x') does not occur in either the @(see guard) or the measure for @('fn'),
 and the value of @('(fn a1...ai...an)') is independent of @('ai').</p>

 <p>The easiest way to define a function with an irrelevant formal is simply
 not to use the formal anywhere in its definition.  Such formals are said to be
 ``ignored'' by Common Lisp and a special declaration is provided to allow
 ignored formals.  ACL2 makes a distinction between ignored and irrelevant
 formals.  Note however that if a variable is @(tsee declare)d @('ignore')d or
 @('ignorable'), then it will not be reported as irrelevant.</p>

 <p>An example of an irrelevant formal is @('x') in the definition of @('fact')
 below.</p>

 @({
  (defun fact (i x)
    (declare (xargs :guard (and (integerp i) (<= 0 i))))
    (if (zp i) 1 (* i (fact (1- i) (cons i x))))).
 })

 <p>Observe that @('x') is only used in recursive calls of @('fact'); it never
 ``gets out'' into the result.  ACL2 can detect some irrelevant formals by a
 closure analysis on how the formals are used; let us call these the ``clearly
 irrelevant formals.''  For example, if the @('i')th formal is only used in the
 @('i')th argument position of recursive calls, then it is clearly irrelevant.
 This is how @('x') is used above.</p>

 <p>It is possible for a formal to appear only in recursive calls but not be
 clearly irrelevant, or even irrelevant at all.  For example, @('x') is
 <b>not</b> irrelevant below, even though it only appears in the recursive
 call.</p>

 @({
  (defun fn (i x y)
    (if (zp i) y (fn (1- i) y x)))
 })

 <p>The following examples show the relevance of @('x').</p>

 @({
 ACL2 !>(fn 1 3 0)
 3
 ACL2 !>(fn 1 4 0)
 4
 ACL2 !>
 })

 <p>The key observation for the definition of @('fn') is that while @('x') only
 appears in a recursive call, it appears in the argument position for a formal
 that is not clearly irrelevant, namely @('y')'s.</p>

 <p>Establishing that a formal is irrelevant, in the sense defined above, can
 be an arbitrarily hard problem because it requires theorem proving.  For
 example, is @('x') irrelevant below?</p>

 @({
  (defun test (i j k x) (if (p i j k) 0 x))
 })

 <p>Note that the value of @('(test i j k x)') is independent of @('x') &mdash;
 thus making @('x') irrelevant &mdash; precisely if @('(p i j k)') is a
 theorem.  ACL2's syntactic analysis of a definition to determine the ``clearly
 irrelevant'' formals does not guarantee to notice all irrelevant formals.</p>

 <p>We regard the presence of irrelevant formals as an indication that
 something is wrong with the definition.  By default, ACL2 causes an error on
 such definitions.  In most cases the best remedy for such an error is to
 recode the definition so as to eliminate the irrelevant formals.  Another
 option is to @(tsee declare) the irrelevant formals, for example as
 follows.</p>

 @({
  (defun fact (i x)
    (declare (irrelevant x))
    (if (zp i) 0 (* i (fact (1- i) (cons i x)))))
 })

 <p>Note that an @('irrelevant') declaration is only legal for a @(tsee
 defun) form, not in other contexts that allow declarations (@(tsee let),
 etc.).</p>

 <p>To turn off the checking of irrelevant formals globally (though we do not
 recommend avoiding those checks), see @(see set-irrelevant-formals-ok).  In
 that case ACL2 will ignore every @('irrelevant') declaration.  But otherwise,
 and by default, if you provide an @('irrelevant') declaration (see @(see
 declare)), then it must specify exactly the formals that ACL2 determines to be
 irrelevant, what we call the ``clearly irrelevant'' formals above: any formal
 declared irrelevant that is not clearly irrelevant will cause an error.</p>")

(defxdoc keep
  :parents (books-tour)
  :short "How we know if @(tsee include-book) read the correct files"
  :long "<p>The certificate (see @(see certificate) for general information) of
 a certified file contains a @(see portcullis) and a keep.  These names come
 from castle lore.  The keep is the strongest and usually tallest tower of a
 castle from which the entire courtyard can be surveyed by the defenders.  The
 keep of a book is a list of file names and @(see book-hash) values used after
 the book has been included, to determine if the files read were (up to
 book-hash) those certified.</p>

 <p>Once the @(see portcullis) is open, @(tsee include-book) can enter the book
 and read the event forms therein.  The non-@(tsee local) event forms are in
 fact executed, extending the host theory.  That may read in other @(see
 books).  When that has been finished, the keep of the @(see certificate) is
 inspected.  The keep is a list of the book names which are included
 (hereditarily through all sub-books) in the certified book (including the
 certified book itself) together with the @(see book-hash) values for those
 @(see books) at the time of certification.  We compare the book-hash values of
 the @(see books) just included to those of the @(see books) stored in the
 keep.  If differences are found then we know that the book or one of its
 sub-books has been changed since certification.</p>

 <p>See @(see include-book) to continue the guided tour through @(see
 books).</p>")

(defxdoc keyword-commands
  :parents (ld)
  :short "How keyword commands like @(':u') and @(':pbt') are processed"
  :long "@({
  Examples:
  user type-in                 form evaluated
  :pc 5                        (ACL2::PC '5)
  :pcs app rev                 (ACL2::PCS 'app 'rev)
  :length (1 2 3)              (ACL2::LENGTH '(1 2 3))
  :quit                        (ACL2::QUIT) ; Note: avoid optional argument
 })

 <p>When a keyword, @(':key'), is read as a command, ACL2 determines whether
 the symbol with the same name in the @('\"ACL2\"') package, @('acl2::key'), is
 a function or simple macro of n arguments.  If so, ACL2 reads @('n') more
 objects, @('obj1'), ..., @('objn'), and then acts as though it had read the
 following form (for a given @('key')):</p>

 @({
  (ACL2::key 'obj1 ... 'objn)
 })

 <p>Thus, by using the keyword command hack you avoid typing the parentheses,
 the @('\"ACL2\"') package name, and the quotation marks.</p>

 <p>See @(see ld-keyword-aliases) for how to customize this behavior.</p>

 <p>Note the generality of this hack.  Any function or macro in the
 @('\"ACL2\"') package can be so invoked, not just ``commands.''  Indeed, there
 is no such thing as a distinguished class of commands.  Users may take
 advantage of the keyword command hack by defining functions and macros in the
 @('\"ACL2\"') package.</p>

 <p>The one caveat is that when the keyword hack is used to invoke a macro,
 only the required arguments for that macro are read before calling that macro:
 none of the @('&optional'), @('&rest'), @('&body'), or @('&key') arguments are
 read for that call.  The macro is thus called with only its required
 arguments.  The following log illustrates this caveat.</p>

 @({
  ACL2 !>:set-iprint t

  ACL2 Query (:SET-IPRINT):  Action  (T, NIL, RESET, RESET-ENABLE, SAME,
  Q or ?):
  ACL2 Observation in SET-IPRINT:  Iprinting has been enabled.
  ACL2 !>
 })

 <p>What happened?  First, the command @(':set-iprint') was read.  Since the
 macro @(tsee set-iprint) has no required arguments, the ACL2 evaluator was
 then called on the form @('(set-iprint)'), that is, calling the macro on no
 arguments.  @('Set-iprint') is defined to query the ACL2 user when its first
 argument is omitted.  The log shows that query, which is set up to read the
 next form from the input stream.  That form was available immediately: the
 form @('t') that had been supplied by the user.  So the query returned
 immediately and the @('set-iprint') call was completed.</p>")

(defxdoc keyword-value-listp
  :parents (keywordp lists acl2-built-ins)
  :short "Recognizer for true lists whose even-position elements are keywords"
  :long "<p>@('(keyword-value-listp l)') is true if and only if @('l') is a
 list of even length of the form @('(k1 a1 k2 a2 ... kn an)'), where each
 @('ki') is a keyword.</p>

 @(def keyword-value-listp)")

(defxdoc keywordp
  :parents (symbols acl2-built-ins)
  :short "Recognizer for keywords"
  :long "<p>@('(Keywordp x)') is true if and only if @('x') is a keyword, i.e.,
 a symbol in the \"KEYWORD\" package.  Such symbols are typically printed using
 a colon
 (:) followed by the @(tsee symbol-name) of the symbol.</p>

 <p>@('Keywordp') has a @(see guard) of @('t').</p>

 <p>@('Keywordp') is a Common Lisp function.  See any Common Lisp documentation
 for more information.  The following log may be illuminating.</p>

 @({
  ACL2 !>(intern \"ABC\" \"KEYWORD\")
  :ABC
  ACL2 !>(symbol-name ':ABC)
  \"ABC\"
  ACL2 !>(symbol-package-name ':ABC)
  \"KEYWORD\"
  ACL2 !>
 })

 @(def keywordp)")

(defxdoc kwote
  :parents (term acl2-built-ins)
  :short "Quote an arbitrary object"
  :long "<p>For any object @('x'), @('(kwote x)') returns the two-element list
 whose elements are the symbol @('quote') and the given @('x'), respectively.
 The guard of @('(kwote x)') is @('t').</p>

 @(def kwote)")

(defxdoc kwote-lst
  :parents (term acl2-built-ins)
  :short "Quote an arbitrary true list of objects"
  :long "<p>The function @('kwote-lst') applies the function @('kwote') to each
 element of a given list.  The guard of @('(kwote-lst lst)') is @('(true-listp
 lst)').</p>

 @(def kwote-lst)")

(defxdoc last
  :parents (lists acl2-built-ins)
  :short "The last @(tsee cons) (not element) of a list"
  :long "<p>@('(Last l)') is the last @(tsee cons) of a list.  Here are
 examples.</p>

 @({
  ACL2 !>(last '(a b . c))
  (B . C)
  ACL2 !>(last '(a b c))
  (C)
 })

 <p>@('(Last l)') has a @(see guard) of @('(listp l)'); thus, @('l') need not
 be a @(tsee true-listp).</p>

 <p>@('Last') is a Common Lisp function.  See any Common Lisp documentation for
 more information.  Unlike Common Lisp, we do not allow an optional second
 argument for @('last').</p>

 @(def last)")

(defxdoc last-prover-steps
  :parents (set-prover-step-limit with-prover-step-limit programming-with-state
                                  acl2-built-ins)
  :short "The number of prover steps most recently taken"
  :long "<p>For discussions of prover step limits, See @(see
 set-prover-step-limit) and see @(see with-prover-step-limit).  The value of
 the form @('(last-prover-steps state)') indicates the number of prover steps
 taken, in the sense described below, for the most recent context in which an
 event summary would normally be printed.  Note that the value of
 @('(last-prover-steps state)') is updated for all @(see events), and for all
 other forms such as calls of @(tsee thm) or @(tsee certify-book), that would
 print a summary &mdash; regardless of whether or not such output is inhibited
 (see @(see set-inhibit-output-lst) and see @(see
 set-inhibited-summary-types)).  In particular, the value is updated (typically
 to @('nil')) for @(tsee table) @(see events), even when no summary is printed;
 for example, the value is updated to @('nil') for @('table') events such as
 @('(')@(tsee logic)@(')'), @('(')@(tsee program)@(')'), and even calls of
 @(tsee set-prover-step-limit).</p>

 <p>The value of @('(last-prover-steps state)') is determined as follows, based
 on the most recent summary context (as described above):</p>

 <blockquote>

 <p>@('nil'), if no prover steps were taken; else,</p>

 <p>the (positive) number of steps taken, if the number of steps did not exceed
 the starting limit; else,</p>

 <p>the negative of the starting limit.</p></blockquote>

 <p>We conclude with a remark for advanced users who wish to invoke
 @('last-prover-steps') in the development of utilities that track prover
 steps.  Suppose that you want to write a utility that takes some action based
 on the number of prover steps performed by the first @('defun') event that is
 generated, among others, for example the number of prover steps taken to admit
 @('f1') in the following example.</p>

 @({
  (progn (defun f1 ...)
         (defun f2 ...))
 })

 <p>A solution is to record the steps taken by the first @(tsee defun) before
 executing subsequent events, as follows (see @(see make-event)).</p>

 @({
  (progn (defun f1 ...)
         (make-event (pprogn (f-put-global 'my-step-count
                                           (last-prover-steps state)
                                           state)
                             (value '(value-triple nil))))
         (defun f2 ...))
 })")

(defxdoc ld
  :parents (miscellaneous)
  :short "The ACL2 read-eval-print loop, file loader, and @(see command) processor"
  :long "<code>
 Examples:
 (LD \"foo.lisp\")              ; read and evaluate each form in file
                              ; \"foo.lisp\", in order
 (LD \"foo.lisp\" :ld-pre-eval-print t)
                              ; as above, but print each form to standard
                              ; character output just before it is evaluated

 General Form:
 (LD standard-oi                  ; open obj in channel, stringp file name
                                  ; to open and close, or list of forms
                                  ; Optional keyword arguments:
     :dir                ...      ; use this add-include-book-dir directory
     :standard-co        ...      ; open char out or file to open and close
     :proofs-co          ...      ; open char out or file to open and close
     :current-package    ...      ; known package name
     :ld-skip-proofsp    ...      ; nil, 'include-book, or t
                                  ;   (see @(see ld-skip-proofsp))
     :ld-redefinition-action ...  ; nil or '(:a . :b)
     :ld-prompt          ...      ; nil, t, or some prompt printer fn
     :ld-missing-input-ok ...     ; nil, t, :warn, or warning message
     :ld-pre-eval-filter ...      ; :all, :query, or some new name
     :ld-pre-eval-print  ...      ; nil, t, or :never
     :ld-post-eval-print ...      ; nil, t, or :command-conventions
     :ld-evisc-tuple     ...      ; nil or '(alist nil nil level length)
     :ld-error-triples   ...      ; nil or t
     :ld-error-action    ...      ; :return!, :return, :continue, :error,
                                  ;   or (:exit N)
     :ld-query-control-alist ...  ; alist supplying default responses
     :ld-verbose         ...)     ; nil or t
     :ld-user-stobjs-modified-warning ...) ; nil, t, or :same

 </code>

 <p>@('Ld') is the top-level ACL2 read-eval-print loop.  (When you call @(tsee
 lp), a little initialization is done in raw Common Lisp and then @('ld') is
 called.)  @('Ld') is also a general-purpose ACL2 file loader and a @(see
 command) interpreter.  @('Ld') is actually a macro that expands to a function
 call involving @(tsee state).  @('Ld') returns an ``error triple'' @('(mv erp
 val state)') as explained below.  (For much more on error triples, see @(see
 programming-with-state).)</p>

 <p>See @(see rebuild) for a variant of @('ld') that skips proofs.  See @(see
 output-to-file) for examples showing how to redirect output to a file.</p>

 <p>The arguments to @('ld'), except for @(':dir'), all happen to be global
 variables in @(tsee state) (see @(see state) and see @(see
 programming-with-state)).  For example, @(''')@(tsee current-package) and
 @(''')@(tsee ld-verbose) are global variables, which may be accessed via @('(@
 current-package)') and @('(@ ld-verbose)').  When @('ld') is called, it
 ``binds'' these variables.  By ``binds'' we actually mean the variables are
 globally set but restored to their old values on exit.  Because @('ld')
 provides the illusion of @(see state) global variables being bound, they are
 called ``@('ld') specials'' (after the Lisp convention of calling a variable
 ``special'' if it is referenced freely after having been bound).</p>

 <p>Note that all arguments but the first are passed via keyword.  Any variable
 not explicitly given a value in a call retains its pre-call value, with the
 exception of @(':')@(tsee ld-error-action), which generally defaults to
 @(':return!') if not explicitly specified.</p>

 <p>Just as an example to drive the point home: If @(tsee current-package) is
 @('\"ACL2\"') and you typed</p>

 @({
  (ld *standard-oi* :current-package \"MY-PKG\")
 })

 <p>you would find yourself in (an inner) read-eval-print loop in which the
 @(see current-package) was @('\"MY-PKG\"').  You could operate there as long
 as you wished, changing the current package at will.  But when you typed
 @(':')@(tsee q) you would return to the outer read-eval-print loop where the
 current package would still be @('\"ACL2\"').</p>

 <p>Roughly speaking, @('ld') repeatedly reads a form from @(tsee standard-oi),
 evaluates it, and prints its result to @(tsee standard-co).  It does this
 until the form is @(':')@(tsee q) or evaluates to an error triple whose value
 component is @(':')@(tsee q), or until the input channel or list is emptied.
 However, @('ld') has many bells and whistles controlled by the @('ld')
 specials.  Each such special is documented individually.  For example, see the
 documentation for @(tsee standard-oi), @(tsee current-package), @(tsee
 ld-pre-eval-print), etc.</p>

 <p>A more precise description of @('ld') is as follows.  In the description
 below we use the @('ld') specials as variables, e.g., we say ``a form is read
 from @(tsee standard-oi).''  By this usage we refer to the current value of
 the named @(see state) global variable, e.g., we mean ``a form is read from
 the current value of @(''')@(tsee standard-oi).'' This technicality has an
 important implication: If while interacting with @('ld') you change the value
 of one of the @('ld') specials, e.g., @(''')@(tsee standard-oi), you will
 change the behavior of @('ld'), e.g., subsequent input will be taken from the
 new value.</p>

 <p>Three @('ld') specials are treated as channels: @(tsee standard-oi) is
 treated as an object input channel and is the source of forms evaluated by
 @('ld'); @(tsee standard-co) and @(tsee proofs-co) are treated as character
 output channels and various flavors of output are printed to them.  However,
 the supplied values of these specials need not actually be channels; several
 special cases are recognized.</p>

 <p>If the supplied value of one of these is in fact an open channel of the
 appropriate type, that channel is used and is not closed by @('ld').  If the
 supplied value of one of these specials is a string, the string is treated as
 a file name in (essentially) Unix syntax (see @(see pathname)) and a channel
 of the appropriate type is opened to/from that file.  Any channel opened by
 @('ld') during the binding of the @('ld') specials is automatically closed by
 @('ld') upon termination.  If @(tsee standard-co) and @(tsee proofs-co) are
 strings that represent the same file, only one channel to that file is opened
 and is used for both.</p>

 <p>As a special convenience, when @(tsee standard-oi) is a string and the
 @(':dir') argument provided and not @('nil'), we look up @(':dir') in the
 table of directories maintained by @(tsee add-include-book-dir), and prepend
 this directory to @(tsee standard-oi) to create the filename.  (In this case,
 however, we require that @('standard-oi') is a relative pathname, not an
 absolute pathname.)  For example, one can write @('(ld
 \"arithmetic/top-with-meta.lisp\" :dir :system)') to @('ld') that particular
 community books library.  (Of course, you should almost always load books like
 @('arithmetic/top-with-meta') using @(tsee include-book) instead of @('ld').)
 If @(':dir') is not specified, then a relative pathname is resolved using the
 connected book directory; see @(see cbd).</p>

 <p>Several other alternatives are allowed for @(tsee standard-oi).  If @(tsee
 standard-oi) is a true list then it is taken as the list of forms to be
 processed.  If @(tsee standard-oi) is a list ending in an open channel, then
 @('ld') processes the forms in the list and then reads and processes the forms
 from the channel.  Analogously, if @(tsee standard-oi) is a list ending a
 string, an object input channel from the named file is opened and @('ld')
 processes the forms in the list followed by the forms in the file.  That
 channel is closed upon termination of @('ld').</p>

 <p>In the cases that a string is to be converted to an object input channel
 &mdash; that is, when @(tsee standard-oi) is a string or is a list ending in a
 string &mdash; an error occurs by default if the conversion fails, presumably
 because the file named by the string does not exist.  However, if keyword
 argument @(':ld-missing-input-ok') is @('t'), then @('ld') immediately returns
 without error in this case, but without reading or executing any forms, as
 though @('standard-oi') is @('nil') and keyword arguments @(':ld-verbose') and
 @(':ld-prompt') both have value @('nil').  The other legal values for
 @(':ld-missing-input-ok') are @('nil'), which gives the default behavior, and
 @(':warn'), which behaves the same as @('t') except that a warning is printed,
 which contains the same information as would be printed for the default error
 described above.</p>

 <p>The remaining @('ld') specials are handled more simply and generally have
 to be bound to one of a finite number of tokens described in the @(':')@(tsee
 doc) entries for each @('ld') special.  Should any @('ld') special be supplied
 an inappropriate value, an error message is printed.</p>

 <p>Next, if @(tsee ld-verbose) is @('t'), @('ld') prints the message ``ACL2
 loading name'' where @('name') names the file or channel from which forms are
 being read.  At the conclusion of @('ld'), it will print ``Finished loading
 name'' if @(tsee ld-verbose) is @('t').</p>

 <p>One may generally omit @('ld-user-stobjs-modified-warning') except when
 calling @('ld') in the body of a definition.  In that case this keyword
 argument is required, and the value @('t') is recommended.  With that value, a
 warning will generally be printed if a user-defined @(see stobj) is modified
 by the call of @('ld'); value @('nil') avoids such warnings, and value
 @(':same') causes the value to be inherited from the existing value (generally
 from a superior call of @('ld')).  A discussion of these warnings is highly
 recommended reading before you give a value other than @('t'); see @(see
 user-stobjs-modified-warnings).</p>

 <p>Finally, @('ld') repeatedly executes the ACL2 read-eval-print step, which
 may be described as follows.  A @(see prompt) is printed to @(tsee
 standard-co) if @(tsee ld-prompt) is non-@('nil').  The format of the @(see
 prompt) is determined by @(tsee ld-prompt).  If it is @('t'), the default ACL2
 @(see prompt) is used.  If it is any other non-@('nil') value then it is
 treated as an ACL2 function that will print the desired @(see prompt).  See
 @(see ld-prompt).  In the exceptional case where @('ld')'s input is coming
 from the terminal @('(*standard-oi*)') but its output is going to a different
 sink (i.e., @(tsee standard-co) is not @(tsee *standard-co*)), we also print
 the @(see prompt) to the terminal.</p>

 <p>@('Ld') then reads a form from @(tsee standard-oi).  If the object read is
 a keyword, @('ld') constructs a ``keyword command form'' by possibly reading
 several more objects.  See @(see keyword-commands).  This construction process
 is sensitive to the value of @(tsee ld-keyword-aliases).  See @(see
 ld-keyword-aliases).  Otherwise, the object read is treated as the command
 form.</p>

 <p>@('Ld') next decides whether to evaluate or skip this form, depending on
 @(tsee ld-pre-eval-filter).  Initially, the filter must be either @(':all'),
 @(':query'), or a new name.  If it is @(':all'), it means all forms are
 evaluated.  If it is @(':query'), it means each form that is read is displayed
 and the user is queried.  Otherwise, the filter is a name and each form that
 is read is evaluated as long as the name remains new, but if the name is ever
 introduced then no more forms are read and @('ld') terminates.  See @(see
 ld-pre-eval-filter).</p>

 <p>If the form is to be evaluated, then @('ld') first prints the form to
 @(tsee standard-co), if @(tsee ld-pre-eval-print) is @('t').  With this
 feature, @('ld') can process an input file or form list and construct a script
 of the session that appears as though each form was typed in.  See @(see
 ld-pre-eval-print).</p>

 <p>@('Ld') then evaluates the form, with @(tsee state) bound to the current
 @(see state).  The result is some list of (multiple) values.  If a @(see
 state) is among the values, then @('ld') uses that @(see state) as the
 subsequent current @(see state).</p>

 <p>Depending on @(tsee ld-error-triples), @('ld') may interpret the result as
 an ``error.''  See @(see ld-error-triples).  We first discuss @('ld')'s
 behavior if no error signal is detected (either because none was sent or
 because @('ld') is ignoring them because @(tsee ld-error-triples) is
 @('nil')).</p>

 <p>In the case of a non-erroneous result, @('ld') does two things: First, if
 the logical @(see world) in the now current @(see state) is different than the
 @(see world) before execution of the form, @('ld') adds to the @(see world) a
 ``@(see command) landmark'' containing the form evaluated.  See @(see
 command-descriptor).  Second, @('ld') prints the result to @(tsee
 standard-co), but only if @(tsee ld-post-eval-print) is not @('nil').  The
 result is printed as a list of (multiple) values unless @(tsee
 ld-post-eval-print) is @(':command-conventions'), @(tsee ld-error-triples) is
 @('t'), and the result is an @(see error-triple), i.e., of the form @('(mv * *
 state)').  In that case, only the non-erroneous ``value'' component of the
 result is printed.  See @(see ld-post-eval-print).</p>

 <p>Whenever @('ld') prints anything (whether the input form, a query, or some
 results) it ``eviscerates'' it if @('ld-evisc-tuple') is non-@('nil').
 Essentially, evisceration is a generalization of Common Lisp's use of
 @('*print-level*') and @('*print-length*') to hide large substructures.  See
 @(see evisc-tuple) and also see @(see set-iprint).</p>

 <p>We now return to the case of a form whose evaluation signals an error.  In
 this case, @('ld') first restores the ACL2 logical @(see world) to what it was
 just before the erroneous form was evaluated.  Thus, a form that partially
 changes the @(see world) (i.e., begins to store properties) and then signals
 an error, has no effect on the @(see world).  You may see this happen on @(see
 command)s that execute several @(see events) (e.g., an @(tsee encapsulate) or
 a @(tsee progn) of several @(tsee defuns)): even though the output makes it
 appear that the initial @(see events) were executed, if an error is signaled
 by a later event the entire block of @(see events) is discarded.</p>

 <p>After rolling back, @('ld') takes an action determined by @(tsee
 ld-error-action).  If the action is @(':continue'), @('ld') merely iterates
 the read-eval-print step.  Note that nothing suggestive of the value of the
 ``erroneous'' form is printed.  If the action is @(':return'), @('ld')
 terminates normally; similarly if the action is @(':return!'), but a special
 value is returned that can cause superior @('ld') commands to terminate; see
 @(see ld-error-action) for details.  If the action is @(':error'), @('ld')
 terminates signaling an error to its caller.  If its caller is in fact
 another instance of @('ld') and that instance is watching out for error
 signals, the entire @(see world) created by the inner @('ld') will be
 discarded by the outer @('ld') if the inner @('ld') terminates with an
 error.  Note that if the action is @('(:exit N)'), then there is no rolling
 back, because ACL2 quits immediately with exit status @('N').</p>

 <p>@('Ld') returns an error triple, @('(mv erp val state)').  @('Erp') is
 @('t') or @('nil') indicating whether an error is being signaled.  If no
 error is signaled, @('val') is the ``reason'' @('ld') terminated and is one
 of @(':exit') (meaning @(':')@(tsee q) was read), @(':eof') (meaning the input
 source was exhausted), @(':error') (meaning an error occurred but has been
 suppressed), @(':filter') (meaning the @(tsee ld-pre-eval-filter) terminated
 @('ld')), or a cons pair whose first component is the symbol @(':STOP-LD'),
 which typically indicates that an error occurred while the value of variable
 @(''')@(tsee ld-error-action) was @(':RETURN!').  See @(see ld-error-action)
 for details of this last case.</p>")

(defxdoc ld-error-action
  :parents (ld)
  :short "Determines @(tsee ld)'s response to an error"
  :long "<p>@('Ld-error-action') is an @(tsee ld) special (see @(see ld)).  The
 accessor is @('(ld-error-action state)') and the updater is
 @('(set-ld-error-action val state)').  @('Ld-error-action') must be
 @(':continue'), @(':return'), @(':return!'), @(':error'), or @('(:exit N)')
 for some natural number @('N').  The initial value of @('ld-error-action') is
 @(':continue'), which means that the top-level ACL2 @(see command) loop (see
 @(tsee lp)) will not exit when an error is caused by @('user-typein').  But
 the default value for @('ld-error-action') on calls of @(tsee ld) is
 @(':return!'), with one exception: in the case that the value of @(tsee ld)
 special @('ld-error-action') is @('(:exit N)'), the default remains that
 value.</p>

 <p>The general-purpose ACL2 read-eval-print loop, @(tsee ld), reads forms from
 @(tsee standard-oi), evaluates them and prints the result to @(tsee
 standard-co).  Note that the ACL2 top-level loop (see @(tsee lp)) results from
 an invocation of @(tsee ld).</p>

 <p>However, there are various flags that control @(tsee ld)'s behavior and
 @('ld-error-action') is one of them.  Suppose that @(tsee ld-error-triples) is
 @('t') and a form evaluates to an @(see error-triple) @('(mv erp val state)').
 If the ``error component'', @('erp'), is non-@('nil'), then an error is said
 to have occurred.  If an error occurs, @(tsee ld)'s action depends on
 @('ld-error-action').  If it is @(':continue'), @(tsee ld) just continues
 processing the forms in @(tsee standard-oi).  If it is @(':return') or
 @(':return!'), @(tsee ld) stops and returns as though it had emptied the
 channel.  If it is @(':error'), @(tsee ld) stops and returns, signaling an
 error to its caller by returning an error triple with non-@('nil') error
 component, and reverting the logical @(see world) to its value just before
 that call of @(tsee ld).  If it is @('(:exit N)'), then ACL2 quits with exit
 status @('N').</p>

 <p>To see this effect of @(':ERROR') for @('ld-error-action'), consider the
 following example.</p>

 @({
  (ld '((defun f (x) x) (defun bad (x)) (defun g (x) x)))
 })

 <p>When the @(tsee defun) of @('bad') fails (because its body is missing),
 evaluation of the @('ld') call stops; thus, the @(tsee defun) of @('g') is not
 evaluated.  The definition of @('f') will be removed from the logical @(see
 world) before the call of @('ld') returns.</p>

 <p>However, by default each user call of @('ld') is made with a
 @('ld-error-action') of @(':RETURN!') (not @(':ERROR')).  In the common case
 that all nested calls of @('ld') inside the ACL2 loop are made this way, an
 error will not roll back the logical @(see world).  However, it will still
 halt evaluation of forms for the current call of @('ld') and any parent calls
 of @('ld') (other than the call made on behalf of @('lp') that entered the
 ACL2 loop in the first place), as though there were no more forms to
 evaluate.</p>

 <p>We have already discussed the behavior of @('ld') when an error occurs.
 But there is another case when @('ld') can stop processing more forms: when
 @('ld-error-action') is not @(':CONTINUE'), @(tsee ld-error-triples) is
 @('t'), and evaluation of a form returns an error triple @('(mv nil val
 state)'), where @('nil') is the error component and whose ``value component'',
 @('val') is a @(tsee cons) pair whose @(tsee car) is the symbol @(':STOP-LD').
 Let @('val') be the pair @('(:STOP-LD . x)').  Then the call of @('ld')
 returns the error triple @('(mv nil (:STOP-LD n . x) state)'), where @('n') is
 the value of @(tsee state) global variable @(''ld-level') at the time of
 termination.  The following example illustrates how this works.</p>

 @({
  (ld '((defun f1 (x) x)
        (ld '((defun f2 (x) x)
              (mv nil '(:STOP-LD my-error more-info) state)
              (defun g2 (x) x)))
        (defun g1 (x) x)))
 })

 <p>The outer call of @('ld') returns the value</p>

 @({
  (:STOP-LD 2 3 MY-ERROR MORE-INFO)
 })

 <p>and leaves us in a world the includes definitions for @('f1') and @('f2'),
 but no definition for @('g1') or @('g2') since neither of their two @('defun')
 forms was evaluated.  The value of @(tsee state) global @(''ld-level') is
 incremented from 1 to 2 when the outer @('ld') is entered and then again to 3
 when the inner @('ld') is entered.  When the inner @('ld') encounters the
 error triple @('(mv nil (:STOP-LD my-error more-info) state)'), it sees
 @(':STOP-LD') in the @('car') of the value component and pushes the current
 value of @(''ld-level'), 3, onto the @(tsee cdr) of that value, to return the
 value triple @('(mv nil (:STOP-LD my-error 3 more-info) state)').  The outer
 of @('ld') then sees this value and returns @('(mv nil (:STOP-LD my-error 2 3
 more-info) state)'), since its current value of @(''ld-level') is 2 after the
 inner @('ld') exits.</p>

 <p>That concludes our discussion of how these special @(':STOP-LD') values are
 handled; but how are they created?  While they can be created directly by
 evaluation results as suggested in the example above, that is not the standard
 way.  Rather, @('ld') returns an error triple @('(mv nil (:STOP-LD n)
 state)'), where @('n') is the value of variable @('ld-level') at the time of
 termination, when the following conditions hold: an error occurs,
 @('ld-error-action') is @('RETURN!') (which is the default), and @(tsee
 ld-error-triples) is @('t') (the default).  The following example, which is a
 bit similar to the preceding one, illustrates both creation and handling of
 the special @(':STOP-LD') values.</p>

 @({
  (ld '((defun f1 (x) x)
        (ld '((defun f2 (x) x)
              (ld '((defun f3 (x) x)
                    (defun bad (x)) ; ERROR -- missing the body
                    (defun g3 (x) x)))
              (defun g2 (x) x)))
        (defun g1 (x) x)))
 })

 <p>The result is that @('f1'), @('f2'), and @('f3') are defined, but none of
 @('g1'), @('g2'), or @('g3') is defined.  Let's see why.  The innermost call
 of @(tsee ld) has a default @(':ld-error-action') of @(':RETURN!') (as do the
 other calls).  So when the definition of @('bad') fails, then the innermost
 @('ld') returns @('(mv nil (:STOP-LD 4) state)').  The middle @('ld') sees
 this value, and since its @(':ld-error-action') is not @(':CONTINUE') (because
 it has the default value of @(':RETURN!')), it returns before considering the
 definition of @('g2'), with value @('(mv nil (:STOP-LD 3 4) state)').  The
 topmost call of @('ld') similarly sees the @(':STOP-LD'); stops evaluation of
 forms, without defining @('g1'); and returns @('(mv nil (:STOP-LD 2 3 4)
 state)').</p>")

(defxdoc ld-error-triples
  :parents (ld)
  :short "Determines whether a form caused an error during @(tsee ld)"
  :long "<p>@('Ld-error-triples') is an @(tsee ld) special (see @(see ld)).
 The accessor is @('(ld-error-triples state)') and the updater is
 @('(set-ld-error-triples val state)').  @('Ld-error-triples') must be either
 @('t') or @('nil').  The initial value of @('ld-error-triples') is @('t').</p>

 <p>The general-purpose ACL2 read-eval-print loop, @(tsee ld), reads forms from
 @(tsee standard-oi), evaluates them and prints the result to @(tsee
 standard-co).  Note that the ACL2 top-level loop (see @(tsee lp)) results from
 an invocation of @(tsee ld).</p>

 <p>However, there are various flags that control @(tsee ld)'s behavior and
 @('ld-error-triples') is one of them.  If this variable has the value @('t')
 then when a form evaluates to an @(see error-triple) @('(mv erp val state)')
 such that @('erp') is non-@('nil'), then an error is deemed to have occurred.
 When an error occurs in evaluating a form, @(tsee ld) rolls back the ACL2
 @(see world) to the configuration it had at the conclusion of the last
 error-free form.  Then @(tsee ld) takes the action determined by @(tsee
 ld-error-action).</p>")

(defxdoc ld-evisc-tuple
  :parents (ld)
  :short "Determines whether @(tsee ld) suppresses details when printing"
  :long "<p>@('Ld-evisc-tuple') is an @(tsee ld) special (see @(see ld)).  The
 accessor is @('(ld-evisc-tuple state)') and an updater is
 @('(set-ld-evisc-tuple val state)'), although the use of @(tsee
 set-evisc-tuple) is preferred for updating.  @('Ld-evisc-tuple') must be
 either @('nil'), which is its initial value, or a legal evisc-tuple: see @(see
 set-evisc-tuple).</p>

 <p>The general-purpose ACL2 read-eval-print loop, @(tsee ld), reads forms from
 @(tsee standard-oi), evaluates them and prints the result to @(tsee
 standard-co).  Note that the ACL2 top-level loop (see @(tsee lp)) results from
 an invocation of @(tsee ld).</p>

 <p>However, there are various flags that control @(tsee ld)'s behavior and
 @('ld-evisc-tuple') is one of them.  @(tsee Ld) may print the forms it is
 evaluating and/or the results of evaluation.  Depending on the value of
 @('ld-evisc-tuple') @(tsee ld) may ``eviscerate'' objects before printing
 them.  See @(see set-evisc-tuple) for a discussion of evisceration and of how
 other evisc-tuples affect the printing of error messages and warnings, as well
 as other output not from @('ld').</p>")

(defxdoc ld-keyword-aliases
  :parents (ld)
  :short "Abbreviation of some keyword commands"
  :long "@({
  Examples:
  (set-ld-keyword-aliases '((:q 0 q-fn)
                            (:e 0 exit-acl2-macro))
                          state)
  (ld-keyword-aliases state) ; current value of the ld-keyword-aliases table
 })

 <p>@('Ld-keyword-aliases') is the name of a ACL2 table (see @(see table)) and
 also the name of a function of @('state') that returns the value of this
 table.  That value must be an alist, each element of which is of the form
 @('(:keyword n fn)'), where @(':keyword') is a keyword, @('n') is a
 nonnegative integer, and @('fn') is a function symbol of arity @('n'), a macro
 symbol, or a @('lambda') expression of arity @('n').  When @('keyword') is
 typed as an @(tsee ld) command, @('n') more forms are read, @('x1, ..., xn'),
 and the form @('(fn 'x1 ... 'xn)') is then evaluated.  The initial value of
 the @('ld-keyword-aliases') @(see table) is @('nil').</p>

 <p>ACL2 provides functions to modify the @('ld-keyword-aliases') table, as
 follows.</p>

 <blockquote>

 <p>@('(Set-ld-keyword-aliases val state)'): sets the table to @('val'), which
 must be a legal alist as described above.  This is an event that may go into a
 book (see @(see events)), but its effect will be @(see local) to that
 book.</p>

 <p>@('Set-ld-keyword-aliases!') is the same as @('set-ld-keyword-aliases'),
 except that its effect is not @(see local).  Indeed, the form
 @('(set-ld-keyword-aliases val state)') is equivalent to the form @('(local
 (set-ld-keyword-aliases! val state)').</p>

 <p>@('(Add-ld-keyword-alias key val state)'): modifies the table by binding
 the keyword @('key') to @('val'), which must be a legal value as described
 above.  This is an event that may go into a book (see @(see events)), but its
 effect will be @(see local) to that book.</p>

 <p>@('Add-ld-keyword-alias!') is the same as @('add-ld-keyword-alias'), except
 that its effect is not @(see local).  Indeed, the form
 @('(add-ld-keyword-alias key val state)') is equivalent to the form @('(local
 (add-ld-keyword-alias! key val state)').</p>

 </blockquote>

 <p>Consider the first example above:</p>

 @({
  (set-ld-keyword-aliases '((:q 0 q-fn)
                            (:e 0 exit-acl2-macro))
                          state)
 })

 <p>With this event, @(':')@(tsee q) is redefined to have the effect of
 executing @('(q-fn)'), so for example if you have defined @('q-fn') with</p>

 @({
  (defmacro q-fn ()
    '(er soft 'q \"You un-bound :q and now we have a soft error.\"))
 })

 <p>then @(':')@(tsee q) will cause an error, and if you have defined</p>

 @({
  (defmacro exit-acl2-macro () '(exit-ld state))
 })

 <p>then @(':e') will cause the effect (it so happens) that @(':')@(tsee q)
 normally has.  If you prefer @(':e') to @(':')@(tsee q) for exiting the ACL2
 loop, you might even want to put such definitions of @('q-fn') and
 @('exit-acl2-macro') together with the @('set-ld-keyword-aliases') form above
 into your @('\"acl2-customization.lsp\"') file; see @(see
 acl2-customization).</p>

 <p>The general-purpose ACL2 read-eval-print loop, @(tsee ld), reads forms from
 @(tsee standard-oi), evaluates them and prints the result to @(tsee
 standard-co).  Note that the ACL2 top-level loop (see @(tsee lp)) results from
 an invocation of @(tsee ld).</p>

 <p>However, there are various flags that control @(tsee ld)'s behavior and
 @('ld-keyword-aliases') is one of them.  @('Ld-keyword-aliases') affects how
 keyword commands are parsed.  Generally speaking, @(tsee ld)'s command
 interpreter reads ``@(':fn x1 ... xn')'' as ``@('(fn 'x1 ... 'xn)')'' when
 @(':fn') is a keyword and @('fn') is the name of an @('n')-ary function; see
 @(see keyword-commands).  But this parse is overridden, as described above,
 for the keywords bound in the @('ld-keyword-aliases') @(see table).</p>")

(defxdoc ld-missing-input-ok
  :parents (ld)
  :short "Determines which forms @(tsee ld) evaluates"
  :long "<p>@('ld-missing-input-ok') is an @(tsee ld) special (see @(see ld)).
 The accessor is @('(ld-missing-input-ok state)') and the updater is
 @('(set-ld-missing-input-ok val state)').  @('ld-missing-input-ok') must be
 either @('nil'), @('t'), or @(':warn').  The initial value of
 @('ld-missing-input-ok') is @('nil').</p>

 <p>The general-purpose ACL2 read-eval-print loop, @(tsee ld), is controlled by
 various flags that control its behavior, and @('ld-missing-input-ok') is one
 of them.  In brief, the first argument of @('ld') can indicate a file from
 which to read input.  If the file does not exist, it is an error by default,
 but @('ld') becomes essentially a no-op if @('t') or @(':warn') is supplied
 for @(':ld-missing-input-ok'), where @(':warn') prints a warning.  Also see
 @(see ld).</p>")

(defxdoc ld-post-eval-print
  :parents (ld)
  :short "Determines whether and how @(tsee ld) prints the result of evaluation"
  :long "<p>@('Ld-post-eval-print') is an @(tsee ld) special (see @(see ld)).
 The accessor is @('(ld-post-eval-print state)') and the updater is
 @('(set-ld-post-eval-print val state)').  @('Ld-post-eval-print') must be
 either @('t'), @('nil'), or @(':command-conventions').  The initial value of
 @('ld-post-eval-print') is @(':command-conventions').</p>

 <p>The general-purpose ACL2 read-eval-print loop, @(tsee ld), reads forms from
 @(tsee standard-oi), evaluates them and prints the result to @(tsee
 standard-co).  Note that the ACL2 top-level loop (see @(tsee lp)) results from
 an invocation of @(tsee ld).</p>

 <p>However, there are various flags that control @(tsee ld)'s behavior and
 @('ld-post-eval-print') is one of them.  If this global variable is @('t'),
 @(tsee ld) prints the result.  In the case of a form that produces a multiple
 value, @(tsee ld) prints the list containing all the values (which, logically
 speaking, is what the form returned).  If @('ld-post-eval-print') is @('nil'),
 @(tsee ld) does not print the values.  This is most useful when @(tsee ld) is
 used to load a previously processed file.</p>

 <p>Finally, if @('ld-post-eval-print') is @(':command-conventions') and also
 @('ld-error-triples') is @('t'), then @(tsee ld) prints the result but treats
 ``error triples'' specially.  An ``error triple'' (see @(see error-triple))
 is a result, @('(mv erp val state)'), that consists of two ordinary values and
 @(tsee state).  Many ACL2 functions use such triples to signal errors.  The
 convention is that if @('erp') (the first value) is @('nil'), then the
 function is returning @('val') (the second value) as its conventional single
 result and possibly side-effecting @(see state) (as with some output).  If
 @('erp') is not @('nil'), then an error has been caused, @('val') is
 irrelevant and the error message has been printed in the returned @(see
 state).  Example ACL2 functions that follow this convention include @(tsee
 defun) and @(tsee in-package).  If such ``error producing'' functions are
 evaluated while @('ld-post-eval-print') is set to @('t'), then you would see
 them producing lists of length 3.  This is disconcerting to users accustomed
 to Common Lisp (where these functions produce single results but sometimes
 cause errors or side-effect @(see state)).  For more information about error
 triples, see @(see programming-with-state).</p>

 <p>When @('ld-post-eval-print') is @(':command-conventions') and a form
 produces an error triple @('(mv erp val state)') as its value, @(tsee ld)
 prints nothing if @('erp') is non-@('nil') and otherwise @(tsee ld) prints
 just @('val').  Because it is a misrepresentation to suggest that just one
 result was returned, @(tsee ld) prints the value of the global variable
 @(''triple-print-prefix') before printing @('val').  @(''triple-print-prefix')
 is initially @('\" \"'), which means that when non-erroneous error triples are
 being abbreviated to @('val'), @('val') appears one space off the left margin
 instead of on the margin.</p>

 <p>In addition, when @('ld-post-eval-print') is @(':command-conventions') and
 the value component of an error triple is the keyword @(':invisible') then
 @(tsee ld) prints nothing.  This is the way certain commands (e.g.,
 @(':')@(tsee pc)) appear to return no value.</p>

 <p>By printing nothing when an error has been signalled, @(tsee ld) makes it
 appear that the error (whose message has already appeared in @(see state)) has
 ``thrown'' the computation back to load without returning a value.  By
 printing just @('val') otherwise, we suppress the fact that @(see state) has
 possibly been changed.</p>")

(defxdoc ld-pre-eval-filter
  :parents (ld)
  :short "Determines which forms @(tsee ld) evaluates"
  :long "<p>@('Ld-pre-eval-filter') is an @(tsee ld) special (see @(see ld)).
 The accessor is @('(ld-pre-eval-filter state)') and the updater is
 @('(set-ld-pre-eval-filter val state)').  @('Ld-pre-eval-filter') must be
 either @(':all'), @(':query'), or a new name that could be defined (e.g., by
 @(tsee defun) or @(tsee defconst)).  The initial value of
 @('ld-pre-eval-filter') is @(':all').</p>

 <p>The general-purpose ACL2 read-eval-print loop, @(tsee ld), reads forms from
 @(tsee standard-oi), evaluates them and prints the result to @(tsee
 standard-co).  Note that the ACL2 top-level loop (see @(tsee lp)) results from
 an invocation of @(tsee ld).</p>

 <p>However, there are various flags that control @(tsee ld)'s behavior and
 @('ld-pre-eval-filter') is one of them.  If the filter is @(':all'), then
 every form read is evaluated.  If the filter is @(':query'), then after a form
 is read it is printed to @(tsee standard-co) and the user is asked if the form
 is to be evaluated or skipped.  If the filter is a new name, then all forms
 are evaluated until that name is introduced, at which time @(tsee ld)
 terminates normally.</p>

 <p>The @(':all') filter is, of course, the normal one.  @(':Query') is useful
 if you want to replay selected the @(see command)s in some file.  The new name
 filter is used if you wish to replay all the @(see command)s in a file up
 through the introduction of the given one.</p>")

(defxdoc ld-pre-eval-print
  :parents (ld)
  :short "Determines whether @(tsee ld) prints the forms to be @('eval')'d"
  :long "<p>@('Ld-pre-eval-print') is an @(tsee ld) special (see @(see ld)).
 The accessor is @('(ld-pre-eval-print state)') and the updater is
 @('(set-ld-pre-eval-print val state)').  @('Ld-pre-eval-print') must be either
 @('t'), @('nil'), or @(':never').  The initial value of @('ld-pre-eval-print')
 is @('nil').</p>

 <p>The general-purpose ACL2 read-eval-print loop, @(tsee ld), reads forms from
 @(tsee standard-oi), evaluates them and prints the result to @(tsee
 standard-co).  Note that the ACL2 top-level loop (see @(tsee lp)) results from
 an invocation of @(tsee ld).</p>

 <p>However, there are various flags that control @(tsee ld)'s behavior and
 @('ld-pre-eval-print') is one of them.  If this global variable is @('t'),
 then before evaluating the form just read from @(tsee standard-oi), @(tsee ld)
 prints the form to @(tsee standard-co).  If the variable is @('nil'), no such
 printing occurs.  The @('t') option is useful if you are reading from a file
 of @(see command)s and wish to assemble a complete script of the session in
 @(tsee standard-co).</p>

 <p>The value @(':never') of @('ld-pre-eval-print') is rarely used.  During the
 evaluation of @(tsee encapsulate) and of @(tsee certify-book) forms,
 subsidiary events are normally printed, even if @('ld-pre-eval-print') is
 @('nil').  Thus for example, when the user submits an @(tsee encapsulate)
 form, all subsidiary events are generally printed even in the default
 situation where @('ld-pre-eval-print') is @('nil').  But occasionally one may
 want to suppress such printing.  In that case, @('ld-pre-eval-print') should
 be set to @(':never').  As described elsewhere (see @(see
 set-inhibit-output-lst)), another way to suppress such printing is to execute
 @('(set-inhibit-output-lst lst)') where @('lst') evaluates to a list including
 @(''prove') and @(''event').</p>")

(defxdoc ld-prompt
  :parents (ld)
  :short "Determines the @(see prompt) printed by @(tsee ld)"
  :long "<p>@('Ld-prompt') is an @(tsee ld) special (see @(see ld)).  The
 accessor is @('(ld-prompt state)') and the updater is @('(set-ld-prompt val
 state)').  @('Ld-prompt') must be either @('nil'), @('t'), or a function
 symbol that, when given an open output character channel and @(see state),
 prints the desired @(see prompt) to the channel and returns two values: the
 number of @(see characters) printed and the @(see state).  The initial value
 of @('ld-prompt') is @('t').</p>

 <p>The general-purpose ACL2 read-eval-print loop, @(tsee ld), reads forms from
 @(tsee standard-oi), evaluates them and prints the result to @(tsee
 standard-co).  Note that the ACL2 top-level loop (see @(tsee lp)) results from
 an invocation of @(tsee ld).</p>

 <p>However, there are various flags that control @(tsee ld)'s behavior and
 @('ld-prompt') is one of them.  @('Ld-prompt') determines whether @(tsee ld)
 prints a @(see prompt) before reading the next form from @(tsee standard-oi).
 If @('ld-prompt') is @('nil'), @(tsee ld) prints no @(see prompt).  If
 @('ld-prompt') is @('t'), the default @(see prompt) printer is used, which
 displays information that includes the current package, default @(see
 defun-mode), @(see guard) checking status (on or off), and @(tsee
 ld-skip-proofsp); see @(see default-print-prompt).</p>

 <p>If @('ld-prompt') is neither @('nil') nor @('t'), then it should be a
 function name, @('fn'), such that @('(fn channel state)') will print the
 desired @(see prompt) to @('channel') in @(tsee state) and return @('(mv col
 state)'), where @('col') is the number of @(see characters) output (on the
 last line output).  You may define your own @(see prompt) printing
 function.</p>

 <p>If you supply an inappropriate @(see prompt) function, i.e., one that
 causes an error or does not return the correct number and type of results, the
 following odd @(see prompt) will be printed instead:</p>

 @({
  Bad Prompt
  See :DOC ld-prompt>
 })

 <p>which will lead you to this message.  You should either call @(tsee ld)
 appropriately next time or assign an appropriate value to
 @('ld-prompt').</p>")

(defxdoc ld-query-control-alist
  :parents (ld)
  :short "How to default answers to queries"
  :long "<p>@('Ld-query-control-alist') is an @(tsee ld) special (see @(see
 ld)).  The accessor is @('(ld-query-control-alist state)') and the updater is
 @('(set-ld-query-control-alist val state)').  Roughly speaking,
 @('ld-query-control-alist') is either @('nil') (meaning all queries should be
 interactive), @('t') (meaning all should default to the first accepted
 response), or an alist that pairs query ids to keyword responses.  The alist
 may end in either @('t') or @('nil'), indicating the default value for all ids
 not listed explicitly.  Formally, the @('ld-query-control-alist') must satisfy
 @('ld-query-control-alistp').  The initial @('ld-query-control-alist') is
 @('nil'), which means all queries are handled interactively.</p>

 <p>When an ACL2 query is raised, a unique identifying symbol is printed in
 parentheses after the word ``Query''.  This symbol, called the ``query id,''
 can be used in conjunction with @('ld-query-control-alist') to prevent the
 query from being handled interactively.  By ``handled interactively'' we mean
 that the query is printed to @(tsee *standard-co*) and a response is read from
 @(tsee *standard-oi*).  The alist can be used to obtain a ``default value''
 for each query id.  If this value is @('nil'), then the query is handled
 interactively.  In all other cases, the system handles the query without
 interaction (although text may be printed to @(tsee standard-co) to make it
 appear that an interaction has occurred; see below).  If the default value is
 @('t'), the system acts as though the user responded to the query by typing
 the first response listed among the acceptable responses.  If the default
 value is neither @('nil') nor @('t'), then it must be a keyword and one of the
 acceptable responses.  In that case, the system acts as though the user
 responded with the given keyword.</p>

 <p>Next, we discuss how the @('ld-query-control-alist') assigns a default
 value to each query id.  It assigns each id the first value paired with the id
 in the alist, or, if no such pair appears in the alist, it assigns the final
 @(tsee cdr) of the alist as the value.  Thus, @('nil') assigns all ids
 @('nil').  @('T') assigns all ids @('t').  @(''((:filter . nil) (:sysdef . :n)
 . t)') assigns @('nil') to the @(':filter') query, @(':n') to the @(':sysdef')
 query, and @('t') to all others.</p>

 <p>It remains only to discuss how the system prints text when the default
 value is not @('nil'), i.e., when the query is handled without interaction.
 In fact, it is allowed to pair a query id with a singleton list containing a
 keyword, rather than a keyword, and this indicates that no printing is to be
 done.  Thus for the example above, @(':sysdef') queries would be handled
 noninteractively, with printing done to simulate the interaction.  But if we
 change the example so that @(':sysdef') is paired with @('(:n)'), i.e., if
 @('ld-query-control-alist') is @(''((:filter . nil) (:sysdef :n) . t)'), then
 no such printing would take place for @('sysdef') queries.  Instead, the
 default value of @(':n') would be assigned ``quietly''.</p>")

(defxdoc ld-redefinition-action
  :parents (ld)
  :short "To allow redefinition without @(see undoing)"
  :long "<p>The present topic discusses redefining functions, macros, and
 constants, using a mechanism that may be convenient but also may be unsafe or
 unsound.  See @(see undo) for what is often a better way to carry out
 redefinition.</p>

 <p>@('Ld-redefinition-action') is an @(tsee ld) special (see @(see ld)).  The
 accessor is @('(ld-redefinition-action state)') and the updater is
 @('(set-ld-redefinition-action val state)').</p>

 <p><b>WARNING!</b> If @('ld-redefinition-action') is non-@('nil') then ACL2 is
 liable to be made unsafe or unsound, or behave in unexpected ways.  For
 example, redefining a macro or inlined function called in the body of a
 function, @('g'), may not cause the new definition to be called by @('g').
 Redefinition should be viewed as a way to facilitate unsafe, but potentially
 useful, hacking.</p>

 <p>The keyword command @(':')@(tsee redef) will set
 @('ld-redefinition-action') to a convenient setting allowing unsound
 redefinition.  See below.</p>

 <p>When @('ld-redefinition-action') is @('nil'), redefinition is prohibited.
 In that case, an error message is printed upon any attempt to introduce a name
 that is already in use.  There is one exception to this rule.  It is permitted
 to redefine a function symbol in @(':')@(tsee program) mode to be a function
 symbol in @(':')@(tsee logic) mode provided the formals and body remain the
 same.  This is the standard way a function ``comes into'' logical
 existence.</p>

 <p>Throughout the rest of this discussion we exclude from our meaning of
 ``redefinition'' the case in which a function in @(':')@(tsee program) mode is
 identically redefined in @(':')@(tsee logic) mode.  At one time, ACL2 freely
 permitted the @(see signature)-preserving redefinition of @(':')@(tsee
 program) mode functions but it no longer does.  See @(see
 redefining-programs).</p>

 <p>When @('ld-redefinition-action') is non-@('nil'), you are allowed to
 redefine a name that is already in use.  <b>The system may be rendered
 unsound</b> by such an act.  It is important to understand how dangerous
 redefinition is.  Suppose @('fn') is a function symbol that is called from
 within some other function, say @('g').  Suppose @('fn') is redefined so that
 its arity changes.  Then the definition of @('g') is rendered syntactically
 ill-formed by the redefinition.  This can be devastating since the entire ACL2
 system assumes that terms in its database are well-formed.  For example, if
 ACL2 executes @('g') by running the corresponding function in raw Common Lisp
 the redefinition of @('fn') may cause raw lisp to break in irreparable ways.
 As Lisp programmers we live with this all the time by following the simple
 rule: after changing the syntax of a function don't run any function that
 calls it via its old syntax.  This rule also works in the context of the
 evaluation of ACL2 functions, but it is harder to follow in the context of
 ACL2 deductions, since it is hard to know whether the database contains a path
 leading the theorem prover from facts about one function to facts about
 another.  Finally, of course, even if the database is still syntactically
 well-formed there is no assurance that all the rules stored in it are valid.
 For example, theorems proved about @('g') survive the redefinition of @('fn')
 but may have crucially depended on the properties of the old @('fn').  In
 summary, we repeat the warning: <b>all bets are off if you set</b>
 @('ld-redefinition-action') to <b>non</b>-@('nil').</p>

 <p>ACL2 provides some enforcement of the concern above, by disabling @(tsee
 certify-book) if any @(see world)-changing @(see events) exist in the
 certification @(see world) that were executed with a non-@('nil') value of
 @(''ld-redefinition-action').  (This value is checked at the end of each
 top-level command, but the value does not change during evaluation of embedded
 event forms; see @(see embedded-event-form).)</p>

 <p>If at any point in a session you wish to see the list of all names that
 have been redefined, see @(see redefined-names).</p>

 <p>That said, we'll give you enough rope to hang yourself.  When
 @('ld-redefinition-action') is non-@('nil'), it must be a pair, @('(a .  b)').
 The value of @('a') determines how the system interacts with you when a
 redefinition is submitted.  The value of @('b') allows you to specify how the
 property list of the redefined name is to be ``renewed'' before the
 redefinition.</p>

 <p>There are several dimensions to the space of possibilities controlled by
 part a: Do you want to be queried each time you redefine a name, so you can
 confirm your intention?  (We sometimes make typing mistakes or simply forget
 we have used that name already.)  Do you want to see a warning stating that
 the name has been redefined?  Do you want ACL2 system functions given special
 protection from possible redefinition?  Below are the choices for part a:</p>

 <blockquote>

 <p>@(':query') &mdash; every attempt to redefine a name will produce a query.
 The query will allow you to abort the redefinition or proceed.  It will will
 also allow you to specify the part @('b') for this redefinition.  @(':Query')
 is the recommended setting for users who wish to dabble in redefinition.</p>

 <p>@(':warn') &mdash; any user-defined function may be redefined but a
 post-redefinition warning is printed.  The attempt to redefine a system name
 produces a query.  If you are prototyping and testing a big system in ACL2
 this is probably the desired setting for part @('a').</p>

 <p>@(':doit') &mdash; any user-defined function may be redefined silently
 (without query or warning) but when an attempt is made to redefine a system
 function, a query is made.  This setting is recommended when you start making
 massive changes to your prototyped system (and tire of even the warning
 messages issued by @(':warn')).</p>

 </blockquote>

 <p>In support of our own ACL2 systems @(see programming) there are two other
 settings.  We suggest ordinary users not use them.</p>

 <blockquote>

 <p>@(':warn!') &mdash; every attempt to redefine a name produces a warning but
 no query.  Since ACL2 system functions can be redefined this way, this setting
 should be used by the only-slightly-less-than supremely confident ACL2 system
 hacker.</p>

 <p>@(':doit!') &mdash; this setting allows any name to be redefined silently
 (without query or warnings).  ACL2 system functions are fair game.  This
 setting is reserved for the supremely confident ACL2 system hacker.
 (Actually, this setting is used when we are loading massively modified
 versions of the ACL2 source files.)</p>

 </blockquote>

 <p>Part @('b') of @('ld-redefinition-action') tells the system how to
 ``renew'' the property list of the name being redefined.  There are two
 choices:</p>

 <blockquote>

 <p>@(':erase') &mdash; erase all properties stored under the name, or</p>

 <p>@(':overwrite') &mdash; preserve existing properties and let the redefining
 overwrite them.</p>

 </blockquote>

 <p>It should be stressed that neither of these @('b') settings is guaranteed
 to result in an entirely satisfactory state of affairs after the redefinition.
 Roughly speaking, @(':erase') returns the property list of the name to the
 state it was in when the name was first introduced.  Lemmas, type information,
 etc., stored under that name are lost.  Is that what you wanted?  Sometimes it
 is, as when the old definition is ``completely wrong.'' But other times the
 old definition was ``almost right'' in the sense that some of the work done
 with it is still (intended to be) valid.  In that case, @(':overwrite') might
 be the correct @('b') setting.  For example if @('fn') was a function and is
 being re-@(tsee defun)'d with the same @(see signature), then the properties
 stored by the new @(tsee defun) should overwrite those stored by the old
 @(tsee defun) but the properties stored by @(tsee defthm)s will be
 preserved.</p>

 <p>In addition, neither setting will cause ACL2 to erase properties stored
 under other symbols!  Thus, if @('FOO') names a rewrite rule which rewrites a
 term beginning with the function symbol @('BAR') and you then redefine
 @('FOO') to rewrite a term beginning with the function symbol @('BAZ'), then
 the old version of @('FOO') is still available (because the rule itself was
 added to the rewrite rules for @('BAR'), whose property list was not cleared
 by redefining @('FOO')).</p>

 <p>The @('b') setting is only used as the default action when no query is
 made.  If you choose a setting for part a that produces a query then you will
 have the opportunity, for each redefinition, to specify whether the property
 list is to be erased or overwritten.</p>

 <p>The keyword command @(':')@(tsee redef) sets @('ld-redefinition-action') to
 the pair @('(:query . :overwrite)').  Since the resulting query will give you
 the chance to specify @(':erase') instead of @(':overwrite'), this setting is
 quite convenient.  But when you are engaged in heavy-duty prototyping, you may
 wish to use a setting such as @(':warn') or even @(':doit').  For that you
 will have to invoke a form such as:</p>

 @({
  (set-ld-redefinition-action '(:doit . :overwrite) state) .
 })

 <p>@(tsee Encapsulate) causes somewhat odd interaction with the user if
 redefinition occurs within the encapsulation because the @(see encapsulate)d
 event list is processed several times.  For example, if the redefinition
 action causes a query and a non-local definition is actually a redefinition,
 then the query will be posed twice, once during each pass.  C'est la vie.</p>

 <p>Finally, it should be stressed again that redefinition is dangerous because
 not all of the rules about a name are stored on the property list of the name.
 Thus, redefinition can render ill-formed terms stored elsewhere in the
 database or can preserve now-invalid rules.  See @(see redundant-events), in
 particular the section ``Note About Unfortunate Redundancies,'' for more
 discussion of potential pitfalls of redefinition.</p>")

(defxdoc ld-skip-proofsp
  :parents (ld)
  :short "How carefully ACL2 processes your @(see command)s"
  :long "@({
  Examples:
  ACL2 !>(set-ld-skip-proofsp t state)
   T
  ACL2 !s>(set-ld-skip-proofsp nil state)
   NIL
  ACL2 !>(set-ld-skip-proofsp 'include-book state)
   INCLUDE-BOOK
  ACL2 !s>
 })

 <p>A global variable in the ACL2 @(tsee state), called @(''ld-skip-proofsp'),
 determines the thoroughness with which ACL2 processes your @(see command)s.
 This variable may take on one of three values: @('t'), @('nil') or
 @(''')@(tsee include-book).  When @('ld-skip-proofsp') is non-@('nil'), the
 system assumes that which ought to be proved and is thus unsound.  The form
 @('(set-ld-skip-proofsp flg state)') is the general-purpose way of setting
 @('ld-skip-proofsp').  This global variable is an ``@(tsee ld) special,''
 which is to say, you may call @(tsee ld) in such a way as to ``bind'' this
 variable for the dynamic extent of the @(tsee ld).</p>

 <p>When @('ld-skip-proofsp') is non-@('nil'), the default @(see prompt)
 displays the character @('s').  Thus, the @(see prompt)</p>

 @({
  ACL2 !s>
 })

 <p>means that the default @(see defun-mode) is @(':')@(tsee logic) (otherwise
 the character @('p'), for @(':')@(tsee program), would also be printed; see
 @(see default-print-prompt)) but ``proofs are being skipped.''</p>

 <p>Observe that there are two legal non-@('nil') values, @('t') and
 @(''')@(tsee include-book).  When @('ld-skip-proofsp') is @('t'), ACL2 skips
 all proof obligations but otherwise performs all other required analysis of
 input @(see events).  When @('ld-skip-proofsp') is @(''')@(tsee include-book),
 ACL2 skips not only proof obligations but all analysis except that required to
 compute the effect of successfully executed @(see events).  To explain the
 distinction, let us consider one particular event, say a @(tsee defun).  Very
 roughly speaking, a @(tsee defun) event normally involves a check of the
 syntactic well-formedness of the submitted definition, the generation and
 proof of the termination conditions, and the computation and storage of
 various rules such as a @(':')@(tsee definition) rule and some @(':')@(tsee
 type-prescription) rules.  By ``normally'' above we mean when
 @('ld-skip-proofsp') is @('nil').  How does a @(tsee defun) behave when
 @('ld-skip-proofsp') is non-@('nil')?</p>

 <p>If @('ld-skip-proofsp') is @('t'), then @(tsee defun) performs the
 syntactic well-formedness checks and computes and stores the various rules,
 but it does not actually carry out the termination proofs.  If
 @('ld-skip-proofsp') is @(''')@(tsee include-book), @(tsee defun) does not do
 the syntactic well-formedness check nor does it carry out the termination
 proof.  Instead, it merely computes and stores the rules under the assumption
 that the checks and proofs would all succeed.  Observe that a setting of
 @(''')@(tsee include-book) is ``stronger'' than a setting of @('t') in the
 sense that @(''')@(tsee include-book) causes @(tsee defun) to assume even more
 about the admissibility of the event than @('t') does.</p>

 <p>As one might infer from the choice of name, the @(tsee include-book) event
 sets @('ld-skip-proofsp') to @(''')@(tsee include-book) when processing the
 @(see events) in a book being loaded.  Thus, @(tsee include-book) does the
 minimal work necessary to carry out the effects of every event in the book.
 The syntactic checks and proof obligations were, presumably, successfully
 carried out when the book was certified.</p>

 <p>A non-@('nil') value for @('ld-skip-proofsp') also affects the system's
 output messages.  Event summaries (the paragraphs that begin ``Summary'' and
 display the event forms, rules used, etc.) are not printed when
 @('ld-skip-proofsp') is non-@('nil').  Warnings and observations are printed
 when @('ld-skip-proofsp') is @('t') but are not printed when it is
 @(''')@(tsee include-book).</p>

 <p>Intuitively, @('ld-skip-proofsp') @('t') means skip just the proofs and
 otherwise do all the work normally required for an event; while
 @('ld-skip-proofsp') @(''')@(tsee include-book) is ``stronger'' and means do
 as little as possible to process @(see events).  In accordance with this
 intuition, @(tsee local) @(see events) are processed when @('ld-skip-proofsp')
 is @('t') but are skipped when @('ld-skip-proofsp') is @(''')@(tsee
 include-book).</p>

 <p>The ACL2 system itself uses only two settings, @('nil') and @(''')@(tsee
 include-book), the latter being used only when executing the @(see events)
 inside of a book being included.  The @('ld-skip-proofsp') setting of @('t')
 is provided as a convenience to the user.  For example, suppose one has a file
 of @(see events).  By loading it with @(tsee ld) with @('ld-skip-proofsp') set
 to @('t'), the @(see events) can all be checked for syntactic correctness and
 assumed without proof.  This is a convenient way to recover a state lost by a
 system crash or to experiment with a modification of an @(see events)
 file.</p>

 <p>The foregoing discussion is actually based on a lie.  @('ld-skip-proofsp')
 is allowed two other values, @(''initialize-acl2') and
 @(''include-book-with-locals').  The first causes behavior similar to @('t')
 but skips @(tsee local) @(see events) and avoids some error checks that would
 otherwise prevent ACL2 from properly booting.  The second is identical to
 @(''')@(tsee include-book) but also executes @(tsee local) @(see events).
 These additional values are not intended for use by the user, but no barriers
 to their use have been erected.</p>

 <p>We close by reminding the user that ACL2 is potentially unsound if
 @('ld-skip-proofsp') is ever set by the user.  We provide access to it simply
 to allow experimentation and rapid reconstruction of lost or modified logical
 @(see world)s.</p>")

(defxdoc ld-verbose
  :parents (ld)
  :short "Determines whether @(tsee ld) prints ``ACL2 Loading ...''"
  :long "<p>@('Ld-verbose') is an @(tsee ld) special (see @(see ld)).  The
 accessor is @('(ld-verbose state)') and the updater is @('(set-ld-verbose val
 state)').  @('Ld-verbose') must be @('t'), @('nil') or a string or @(tsee
 consp) suitable for @(tsee fmt) printing via the @('~@') command.  The initial
 value of @('ld-verbose') is a @(tsee fmt) message that prints the ACL2 version
 number, @(tsee ld) level and connected book directory.</p>

 <p>Note: @('Ld-verbose') has no effect on proofs.  See @(see set-gag-mode) and
 see @(see set-inhibit-output-lst) for how to control the size of proof
 output.</p>

 <p>Before processing the forms in @(tsee standard-oi), @(tsee ld) may print a
 header.  The printing of this header is controlled by @('ld-verbose').  If
 @('ld-verbose') is @('nil'), no header is printed.  If it is @('t'), @(tsee
 ld) prints the message</p>

 @({
     ACL2 loading <file>
 })

 <p>where @('<file>') is the input channel supplied to @(tsee ld).  A similar
 message is printed when @(tsee ld) completes.  If @('ld-verbose') is neither
 @('t') nor @('nil') then it is presumably a header and is printed with the
 @('~@') @(tsee fmt) directive before @(tsee ld) begins to read and process
 forms.  In this case the @('~@') @(tsee fmt) directive is interpreted in an
 environment in which @('#\\v') is the ACL2 version string, @('#\\l') is the
 level of the current recursion in @(tsee ld) and/or @(tsee wormhole), and
 @('#\\c') is the connected book directory @('(cbd)').</p>")

(defxdoc lemma-instance
  :parents (hints functional-instantiation)
  :short "An object denoting an instance of a theorem"
  :long "<p>Lemma instances are the objects one provides via @(':use') and
 @(':by') @(see hints) to bring to the theorem prover's attention some
 previously proved or easily provable fact.  A typical use of the @(':use')
 hint is given below.  The value specified is a list of five lemma
 instances.</p>

 @({
  :use (reverse-reverse
        (:type-prescription app)
        (:instance assoc-of-app
                   (x a) (y b) (z c))
        (:functional-instance p-f
                              (p consp) (f flatten))
        (:instance (:theorem (equal x x))
                   (x (flatten a))))
 })

 <p>Observe that an event name can be a lemma instance.  The @(':use') hint
 allows a single lemma instance to be provided in lieu of a list, as in:</p>

 @({
  :use reverse-reverse
 })

 <p>or</p>

 @({
  :use (:instance assoc-of-app (x a) (y b) (z c))
 })

 <p>A lemma instance denotes a formula which is either known to be a theorem or
 which must be proved to be a theorem before it can be used.  To use a lemma
 instance in a particular subgoal, the theorem prover adds the formula as a
 hypothesis to the subgoal before the normal theorem proving heuristics are
 applied.</p>

 <p>A lemma instance, or @('lmi'), is of one of the following forms:</p>

 <p>(1) @('name'), where @('name') names a previously proved theorem, axiom, or
 definition and denotes the formula (theorem) of that name.</p>

 <p>(2) @('rune'), where @('rune') is a @(see rune) (see @(see rune)) denoting
 the @(':')@(tsee corollary) justifying the rule named by the @(see rune).</p>

 <p>(3) @('(:theorem term)'), where @('term') is any term alleged to be a
 theorem.  Such a lemma instance denotes the formula @('term').  But before
 using such a lemma instance the system will undertake to prove @('term').</p>

 <p>(4) @('(:instance lmi (v1 t1) ... (vn tn))'), where @('lmi') is recursively
 a lemma instance, the @('vi')'s are distinct variables, and the @('ti')'s are
 terms.  Such a lemma instance denotes the formula obtained by instantiating
 the formula @('F') denoted by @('lmi'), normally by replacing each @('vi') by
 @('ti') in @('F') and requiring that each @('vi') must be bound in @('F').
 There are two exceptions.  If the keyword @(':extra-bindings-ok') is inserted
 immediately after the lemma instance in order to remove that requirement, as
 follows, then that requirement is ignored: @('(:instance
 lmi :extra-bindings-ok (v1 t1) ... (vn tn))').  Otherwise there is the
 following exception pertaining to @(see packages): if one or more variables
 @('vi') do not occur in @('F'), but for each such @('vi') exactly one variable
 @('v') with the same @(tsee symbol-name) as @('vi') occurs in @('F') and no
 other @('vj') with the same @('symbol-name') as @('v') is bound in the
 substitution, then the pair @('(vi ti)') is replaced by the pair @('(v ti)')
 in the substitution.</p>

 <p>(5) @('(:functional-instance lmi (f1 g1) ... (fn gn))'), where @('lmi') is
 recursively a lemma instance and each @('fi') is an ``instantiable'' function
 symbol of arity @('ni') and @('gi') is a function symbol, a macro alias for a
 function symbol @('gi'') (see @(see macro-aliases-table)) in which case we
 treat @('gi') as @('gi''), or a pseudo-lambda expression of arity @('ni').  An
 instantiable function symbol is any defined or constrained function symbol
 except the primitives @(tsee not), @(tsee member), @(tsee implies), and @(tsee
 o<), and a few others, as listed by the constant
 @('*non-instantiable-primitives*').  These are built-in in such a way that we
 cannot recover the @(see constraint)s on them.  (Special case: a function
 introduced in the @(':partial-theory') of a dependent clause-processor is not
 instantiable; see @(see define-trusted-clause-processor).)  A pseudo-lambda
 expression is an expression of the form @('(lambda (v1 ... vn) body)') where
 the @('vi') are distinct variable symbols and @('body') is any term.  No <i>a
 priori</i> relation is imposed between the @('vi') and the variables of
 @('body'), i.e., @('body') may ignore some @('vi')'s and may contain ``free''
 variables.  However, we do not permit @('v') to occur freely in @('body') if
 the functional substitution is to be applied to any formula (@('lmi') or the
 @(see constraint)s to be satisfied) in a way that inserts @('v') into the
 scope of a binding of @('v') by @(tsee let) or @(tsee mv-let) (or, @(tsee
 lambda)).  If you happen to violate this restriction, an informative error
 message will be printed.  That message will list for you the potentially
 illegal choices for @('v') in the context in which the functional substitution
 is offered.  A @(':functional-instance') lemma instance denotes the formula
 obtained by functionally instantiating the formula denoted by @('lmi'),
 replacing @('fi') by @('gi').  However, before such a lemma instance can be
 used, the system will generate proof obligations arising from the replacement
 of the @('fi')'s by the @('gi')'s in constraints that ``support'' the lemma to
 be functionally instantiated; see @(see constraint).  One might expect that if
 the same instantiated constraint were generated on behalf of several events,
 then each of those instances would have to be proved.  However, for the sake
 of efficiency, ACL2 stores the fact that such an instantiated constraint has
 been proved, unless the proof was done inside an @(tsee encapsulate) event
 that either has a non-empty @(see signature) list or is ``empty'' (stores
 no events), and then avoids re-proving that constraint in future @(see
 events).</p>

 <p>See @(see functional-instantiation-example) for an example of the use of
 @(':functional-instance') (so-called ``functional instantiation'').</p>

 <p>Note that ACL2(r) (see @(see real)) imposes additional requirements for
 functional instantiation.  See @(see functional-instantiation-in-acl2r).</p>

 <p>(6) @('(:termination-theorem name)') or @('(:termination-theorem! name)'),
 where @('name') is a function symbol in @(see logic) mode.  Such a lemma
 instance denotes the termination theorem previously proved for @('name'),
 possibly modified as discussed in the next paragraph.  If no such theorem
 exists &mdash; for example, if the definition of @('name') is not recursive
 &mdash; then the lemma instance is illegal in the case of
 @(':termination-theorem'), but denotes @('T') in the case of
 @(':termination-theorem!').  If @('name') is defined as part of a
 mutually-recursive clique of definitions (see @(see mutual-recursion)), then
 the lemma instance refers to the termination theorem proved for the entire
 clique.  See @(see termination-theorem-example) and see @(see tthm).</p>

 <p>Consider the application of @(':termination-theorem f') while attempting to
 prove the termination theorem for a function, @('g').  For now suppose that
 neither @('f') nor @('g') is defined using @(tsee mutual-recursion).  Suppose
 that @('f') and @('g') have the same number of formal parameters.  Then every
 call of @('f') in the termination theorem for @('f') will be replaced by a
 call of @('g') on the same arguments (except, recursively, @('f') is also
 replaced by @('g') in those arguments).  The analogous replacement also takes
 place for mutually recursive definitions, as follows.  In the case that @('f')
 was introduced with @('(mutual-recursion (defun f1 ...) ... (defun fk ...))')
 and similarly @('g') is being introduced with @('(mutual-recursion (defun g1
 ...)  ... (defun gk ...))'), where for each @('i') from @('1') to @('k') the
 number of formal parameters is the same for @('fi') and @('gi'), then the
 functional substitution @('((f1 . g1) ... (fk . gk))') is applied to the
 termination theorem for the @('fi').  Note that unlike normal @(see
 functional-instantiation), here there is no proof obligation.  (Logical
 justification in a nutshell: the termination proof for the @('fi') took place
 before adding their definitional equations to the current theory, where the
 @('fi') were thus stubs with no axioms.)</p>

 <p>Finally, note that an optional second argument to @(':termination-theorem')
 specifies an explicit functional substitution @('((f1 g1) ... (fn gn))'),
 which is to be applied to the termination theorem for @('f').  If that
 argument is supplied, then there will be no attempt to derive a functional
 substitution automatically, as described in the preceding paragraph.</p>

 <p>(7) @('(:guard-theorem name)') or @('(:guard-theorem name flg)'), where
 @('name') is a @(see guard)-verified function symbol (hence, in particular, is
 in @(see logic) mode).  Such a lemma instance denotes the guard theorem
 previously proved for @('name'), where by default @('flg') is @('t'), and a
 non-@('nil') value of @('flg') enables simplification as documented elsewhere;
 see @(see gthm).  If @('name') is defined as part of a mutually-recursive
 clique of definitions (see @(see mutual-recursion)), then the lemma instance
 refers to the guard theorem proved for the entire clique.  See @(see
 guard-theorem-example) and see @(see gthm).</p>

 <p>Obscure case for @(see definition)s.  If the lemma instance refers to a
 @(':definition') @(see rune), then it refers to the @(tsee corollary) formula
 of that rune, which can be a normalized (simplified) form of the definition
 body; see @(see normalize).  However, if the hint is a @(':by') hint and the
 lemma instance is based on a name (i.e., a symbol), rather than a rune, then
 the formula is the original formula of the event, as shown by @(':')@(tsee
 pe), rather than the normalized version, as shown by @(':')@(tsee pf).  This
 is as one would expect: If you supply the name of an event, you expect it to
 refer to the original event.  For @(':use') hints we use the simplified (@(see
 normalize)d) form instead, which is reasonable since one would expect
 simplification during the proof that re-traces the normalization done at the
 time the rule was created.</p>

 <p>We conclude with remarks on (6) and (7).  The termination theorem actually
 used is an unsimplified version of what was originally proved for the
 indicated function; the guard theorem is partially simplified.  That is: while
 in general, the termination theorem is simplified before being given to the
 prover, nevertheless the unsimplified theorem is what is actually used for
 @(':termination-theorem') lemma instances; for @(':guard-theorem'), some
 simplification is done that is independent of the theory, by using a form of
 ``subsumption'' to eliminate redundancy and by deleting tautologies as well as
 instances of @(see built-in-clause) rules that come with ACL2.  Also see @(see
 guard-formula-utilities).  Moreover, the @(':')@(tsee measure-debug) and
 @(':')@(tsee guard-debug) keywords for @(tsee xargs) are ignored when
 generating the termination or guard theorem.  You can see the termination or
 guard theorem for an existing function symbol @('FN') by evaluating the form
 @('(termination-theorem 'FN (w state))') or @('(guard-theorem 'FN (w state)
 state)'), respectively.  In the former case, failure is indicated by a result
 of the form @('(FAILED . msg)'), where @('msg') is a message suitable for
 @(tsee fmt); see @(see msg).</p>

 <p>Also see @(see make-termination-theorem).</p>

 <p>Why do we avoid simplification for @(':termination-theorem'), as described
 in the preceding paragraph?  The reason is that it could in principle
 strengthen the theorem, which is sound when admitting the original function
 but not for lemma instances.  Future work might try to allow simplification at
 lemma-instance time, by ensuring that simplification never strengthens the
 theorem.  Alternatively, simplification might be checked for each usage to be
 equivalence-preserving by defining a suitable macro based on @(tsee
 make-event).  For now, by avoiding simplification we guarantee that the
 theorem we are using is truly a theorem.  The theorem being used might not be
 exactly the theorem originally proved, for example because of the use of @(see
 case-split-limitations), which depends on the current logical @(see world);
 but we expect the two theorems to be logically equivalent.</p>")

(defxdoc len
  :parents (lists acl2-built-ins)
  :short "Length of a list"
  :long "<p>@('Len') returns the length of a list.</p>

 <p>A Common Lisp function that is appropriate for both strings and proper
 lists is @('length'); see @(see length).  The guard for @('len') is
 @('t').</p>

 <p>(Low-level implementation note.  ACL2 provides a highly-optimized
 implementation of @('len'), which is tail-recursive and fixnum-aware, that
 differs from its simple ACL2 definition.)</p>

 @(def len)")

(defxdoc length
  :parents (lists strings acl2-built-ins)
  :short "Length of a string or proper list"
  :long "<p>@('Length') is the function for determining the length of a
 sequence.  In ACL2, the argument is required to be either a @(tsee true-listp)
 or a string.</p>

 <p>For a similar function that is logically defined to be equal to zero on any
 atom, including any string, see @(tsee len).</p>

 <p>@('Length') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def length)")

(defxdoc let
  :parents (basics acl2-built-ins)
  :short "Binding of lexically scoped (local) variables"
  :long "<h3>Introduction</h3>

 <p>Example</p>

 @({
  (let ((x (* x x))
        (y (* 2 x)))
   (list x y))
 })

 <p>If the form above is executed in an environment in which @('x') has the
 value @('-2'), then the result is @(''(4 -4)').</p>

 <p>@('Let') expressions bind variables so that their ``local'' values, the
 values they have when the ``body'' of the @('let') is evaluated, are possibly
 different than their ``global'' values, the values they have in the context in
 which the @('let') expression appears.  In the @('let') expression above, the
 local variables bound by the @('let') are @('x') and @('y').  They are locally
 bound to the values delivered by the two forms @('(* x x)') and @('(* 2 x)'),
 respectively, that appear in the ``bindings'' of the @('let').  The body of
 the @('let') is @('(list x y)').</p>

 <p>Suppose that the @('let') expression above occurs in a context in which
 @('x') has the value @('-2').  (The global value of @('y') is irrelevant to
 this example.)  For example, one might imagine that the @('let') form above
 occurs as the body of some function, @('fn'), with the formal parameter @('x')
 and we are evaluating @('(fn -2)').</p>

 <p>To evaluate the @('let') above in a context in which @('x') is @('-2'), we
 first evaluate the two forms specifying the local values of the variables.
 Thus, @('(* x x)') is evaluated and produces @('4') (because @('x') is
 @('-2')) and @('(* 2 x)') is evaluated and produces @('-4') (because @('x') is
 @('-2')).  Then @('x') and @('y') are bound to these values and the body of
 the @('let') is evaluated.  Thus, when the body, @('(list x y)') is evaluated,
 @('x') is @('4') and @('y') is @('-4').  Thus, the body produces @(''(4
 -4)').</p>

 <p>Note that the binding of @('y'), which is written after the binding of
 @('x') and which mentions @('x'), nevertheless uses the global value of
 @('x'), not the new local value.  That is, the local variables of the @('let')
 are bound ``in parallel'' rather than ``sequentially.'' In contrast, if
 the example @('let*') form:</p>

 @({
  (let* ((x (* x x))
         (y (* 2 x)))
   (list x y))
 })

 <p>is evaluated when the global value of @('x') is @('-2'), then the result is
 @(''(4 8)'), because the local value of @('y') is computed after @('x') has
 been bound to @('4').  @(tsee Let*) binds its local variables
 ``sequentially.''</p>

 <p>General @('let') forms</p>
 @({
  (let ((var1 term1) ... (varn termn)) body)
  and
  (let ((var1 term1) ... (varn termn))
   (declare ...) ... (declare ...)
   body)
 })

 <p>where the @('vari') are distinct variables, the @('termi') are terms
 involving only variables bound in the environment containing the @('let'), and
 @('body') is a term involving only the @('vari') plus the variables bound in
 the environment containing the @('let').  Each @('vari') must be used in
 @('body') or else @(see declare)d ignored.</p>

 <p>A @('let') form is evaluated by first evaluating each of the @('termi'),
 obtaining for each a @('vali').  Then, each @('vari') is bound to the
 corresponding @('vali') and @('body') is evaluated.</p>

 <p>Actually, @('let') forms are just abbreviations for certain uses of
 @('lambda') notation.  In particular</p>

 @({
  (let ((var1 term1) ... (varn termn)) (declare ...) body)
 })

 <p>is equivalent to</p>

 @({
  ((lambda (var1 ... varn)
     (declare ...)
     body)
   term1 ... termn).
 })

 <p>@(tsee Let*) forms are used when it is desired to bind the @('vari')
 sequentially, i.e., when the local values of preceding @('varj') are to be
 used in the computation of the local value for @('vari').</p>

 <p>General @('let*') forms:</p>
 @({
  (let* ((var1 term1) ... (varn termn)) body)
  and
  (let* ((var1 term1) ... (varn termn))
   (declare (ignore x1 ... xm))
   body)
 })

 <p>where the @('vari') are variables (not necessarily distinct), the
 @('termi') are terms involving only variables bound in the environment
 containing the @(tsee let*) and those @('varj') such that @('j<i'), and
 @('body') is a term involving only the @('vari') plus the variables bound in
 the environment containing the @(tsee let*).  Each @('vari') must be used
 either in some subsequent @('termj') or in @('body'), except that in the
 second form above we make an exception when @('vari') is among the @('xk'), in
 which case @('vari') must not be thus used.  Note that @(tsee let*) does not
 permit the inclusion of any @(tsee declare) forms other than one as shown
 above.  In the second general form above, every @('xk') must be among the
 @('vari'), and furthermore, @('xk') may not equal @('vari') and @('varj') for
 distinct @('i'), @('j').</p>

 <p>The first @(tsee let*) above is equivalent to</p>

 @({
  (let ((var1 term1))
   ...
   (let ((varn termn)) body)...)
 })

 <p>Thus, the @('termi') are evaluated successively and after each evaluation
 the corresponding @('vali') is bound to the value of @('termi').  The second
 @(tsee let*) is similarly expanded, except that each for each @('vari') that
 is among the @('(x1 ... xm)'), the form @('(declare (ignore vari))') is
 inserted immediately after @('(vari termi)').</p>

 <p>Each @('(vari termi)') pair in a @('let') or @(tsee let*) form is called a
 ``binding'' of @('vari') and the @('vari') are called the ``local variables''
 of the @('let') or @(tsee let*).  The common use of @('let') and @(tsee let*)
 is to save the values of certain expressions (the @('termi')) so that they may
 be referenced several times in the body without suggesting their
 recomputation.</p>

 <p>@('Let') is part of Common Lisp.  See any Common Lisp documentation for
 more information.</p>")

(defxdoc let*
  :parents (basics acl2-built-ins)
  :short "Binding of lexically scoped (local) variables"
  :long "<p>Examples</p>

 @({
  (let* ((x (* x x))
         (y (* 2 x)))
   (list x y))

  (let* ((x (* x x))
         (y (* 2 x))
         (x (* x y))
         (a (* x x)))
   (declare (ignore a))
   (list x y))
 })

 <p>If the forms above are executed in an environment in which @('x') has the
 value @('-2'), then the respective results are @(''(4 8)') and @(''(32 8)').
 See @(see let) for a discussion of both @(tsee let) and @('let*'), or read on
 for a briefer discussion.</p>

 <p>The difference between @(tsee let) and @('let*') is that the former binds
 its local variables in parallel while the latter binds them sequentially.
 Thus, in @('let*'), the term evaluated to produce the local value of one of
 the locally bound variables is permitted to reference any locally bound
 variable occurring earlier in the binding list and the value so obtained is
 the newly computed local value of that variable.  See @(see let).</p>

 <p>In ACL2 the only @(tsee declare) forms allowed for a @('let*') form are
 @('ignore'), @('ignorable'), and @('type').  See @(see declare).  Moreover, no
 variable declared @('ignore')d or @('ignorable') may be bound more than once.
 A variable with a type declaration may be bound more than once, in which case
 the type declaration is treated by ACL2 as applying to each binding occurrence
 of that variable.  It seems unclear from the Common Lisp spec whether the
 underlying Lisp implementation is expected to apply such a declaration to more
 than one binding occurrence, however, so performance in such cases may depend
 on the underlying Lisp.</p>

 <p>@('Let*') is a Common Lisp macro.  See any Common Lisp documentation for
 more information.</p>")

(defxdoc lexorder
  :parents (<< acl2-built-ins)
  :short "Total order on ACL2 objects"
  :long "<p>@('Lexorder') is a non-strict total order, a ``less than or
 equal,'' on ACL2 objects.  Also see @(see alphorder), the restriction of
 @('lexorder') to atoms; the notion of ``non-strict total order'' is defined
 there.</p>

 <p>@('Lexorder') has a guard of @('t').</p>

 <p>For @('lexorder'), an @(see atom) and a @(see cons) are ordered so that the
 @(see atom) comes first, and two @(see cons)es are ordered so that the one
 with the recursively smaller @(tsee car) comes first, with the @(tsee cdr)s
 being compared only if the @(tsee car)s are equal.  @('Lexorder') compares two
 atoms by using @(tsee alphorder).</p>

 @(def lexorder)")

(defxdoc linear
  :parents (rule-classes)
  :short "Make some arithmetic inequality rules"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 @({
  Example:
  (defthm length-member-leq-length       If inequality reasoning begins to
    (implies (and (eqlablep e)           consider how (length (member a b))
                  (true-listp x))        compares to any other term, add to
             (<= (length (member e x))   the set of known inequalities the fact
                 (length x)))            that it is no larger than (length b),
    :rule-classes :linear)               provided (eqlablep a) and
                                         (true-listp b) rewrite to t.

  General Form:
  (and ...
       (implies (and ...hi...)
                (implies (and ...hk...)
                         (and ...
                              (rel lhs rhs)
                              ...)))
       ...)
 })

 <p>We process the @(':')@(tsee corollary) formula of one @(':linear') rule
 class object to create one or more @(':linear') rules.  The first step is to
 flatten the @(tsee and) and @(tsee implies) structure of the formula,
 transforming it into a conjunction of formulas, each of the form</p>

 @({
  (implies (and h1 ... hn) (rel lhs rhs))
 })

 <p>where no hypothesis is a conjunction and @('rel') is one of the inequality
 relations @(tsee <), @(tsee <=), @(tsee =), @(tsee /=), @(tsee >), or @(tsee
 >=).  If necessary, the hypothesis of such a conjunct may be vacuous.  We
 create a @(':linear') rule for each such conjunct, if possible, and otherwise
 cause an error.  To create a @(':linear') rule from a term (i.e., from a
 single such conjunct), we apply the following sequence of transformations.</p>

 <ol>

 <li>Remove @(see guard-holders) such as @(tsee prog2$) from the term to obtain
 @('(implies hyp concl)'), where @('hyp') is @('t') in the case of an
 unconditional rule.</li>

 <li>If @('concl') is @('(not (not concl2))'), replace @('concl') by
 @('concl2').</li>

 <li>For the resulting @('concl'), replace @(tsee =) and @(tsee /=) by @(tsee
 equal) and @('not equal'), respectively.</li>

 <li>Finally, the resulting @('concl') is processed (``linearized'') to attempt
 to create a corresponding polynomial or disjunction of two polynomials.  This
 process includes the evaluation of ground subexpressions, for example
 replacing @('(* '3 '4)') by @(''12'), and employs techniques that include
 @(see type-set) reasoning.</li>

 </ol>

 <p>Each rule has one or more ``trigger terms'' which may be specified by the
 user using the @(':trigger-terms') field of the rule class or which may be
 defaulted to values chosen by the system.  We discuss the determination of
 trigger terms after discussing how linear rules are used.</p>

 <p>@(':Linear') rules are used by an arithmetic decision procedure during
 rewriting.  See @(see linear-arithmetic) and see @(see non-linear-arithmetic).
 Here we assume that the reader is familiar with the material described in
 @(tsee linear-arithmetic).</p>

 <p>Recall that we eliminate the unknowns of an inequality in term-order,
 largest unknowns first.  (See @(see term-order).)  In order to facilitate this
 strategy, we store the inequalities in ``linear pots''.  For purposes of the
 present discussion, let us say that an inequality is ``about'' its largest
 unknown.  Then, all of the inequalities about a particular unknown are stored
 in the same linear pot, and the pot is said to be ``labeled'' with that
 unknown.  This storage layout groups all of the inequalities which are
 potential candidates for cancellation with each other into one place.  It is
 also key to the efficient operation of @(':linear') rules.</p>

 <p>If the arithmetic decision procedure has stabilized and not yielded a
 contradiction, we scan through the list of linear pots examining each label as
 we go.  If the trigger term of some @(':linear') rule can be instantiated to
 match the label, we so instantiate that rule and attempt to relieve the
 hypotheses with general-purpose rewriting.  If we are successful, we rewrite
 each of the two terms being compared by the conclusion (which is an equality
 or inequality), under the substitution produced by the rule's instantiation.
 We then add the resulting equality or inequality to our set of
 inequalities. This may let cancellation continue.</p>

 <p>Note: Problems may arise if you explicitly store a linear lemma under a
 trigger term that, when instantiated, is not the largest unknown in the
 instantiated concluding inequality.  Suppose for example you store the linear
 rule @('(<= (fn i j) (/ i (* j j)))') under the trigger term @('(fn i j)').
 Then when the system ``needs'' an inequality about @('(fn a b)'), (i.e.,
 because @('(fn a b)') is the label of some linear pot, and hence the largest
 unknown in some inequality), it will appeal to the rule and deduce @('(<= (fn
 a b) (/ a (* b b)))').  However, the largest unknown in this inequality is
 @('(/ a (* b b))') and hence it will be stored in a linear pot labeled with
 @('(/ a (* b b))').  The original, triggering inequality which is in a pot
 about @('(fn a b)') will therefore not be canceled against the new one.  It
 is generally best to specify as a trigger term one of the ``maximal'' terms of
 the polynomial, as described below.</p>

 <p>We now describe how the trigger terms are determined.  Most of the time,
 the trigger terms are not specified by the user and are instead selected by
 the system.  However, the user may specify the terms by including an explicit
 @(':trigger-terms') field in the rule class, e.g.,</p>

 @({
  General Form of a Linear Rule Class:
  (:LINEAR :COROLLARY formula
           :TRIGGER-TERMS (term1 ... termk))
 })

 <p>Each @('termi') must be a term and must not be a variable, quoted constant,
 lambda application, @('let-expression') or @('if-expression').  In addition,
 each @('termi') must be such that if all the variables in the term are
 instantiated and then the hypotheses of the corollary formula are relieved
 (possibly instantiating additional free variables), then all the variables in
 the concluding inequality are instantiated.  We generate a linear rule for
 each conjunctive branch through the corollary and store each rule under each of
 the specified triggers.  Thus, if the corollary formula contains several
 conjuncts, the variable restrictions on the @('termi') must hold for each
 conjunct.</p>

 <p>If @(':trigger-terms') is omitted the system computes a set of trigger
 terms.  Each conjunct of the corollary formula may be given a unique set of
 triggers depending on the variables that occur in the conjunct and the addends
 that occur in the concluding inequality.  In particular, the trigger terms for
 a conjunct is the list of all ``maximal addends'' in the concluding
 inequality.</p>

 <p>The ``addends'' of @('(+ x y)') and @('(- x y)') are the union of the
 addends of @('x') and @('y').  The addends of @('(- x)') and @('(* n x)'),
 where @('n') is a rational constant, is just @('{x}').  The addends of an
 inequality are the union of the addends of the left- and right-hand sides.
 The addends of any other term, @('x'), is @('{x}').</p>

 <p>A term is maximal for a conjunct @('(implies hyps concl)') of the corollary
 if (a) the term is a non-variable, non-quote, non-lambda application,
 non-@(tsee let) and non-@(tsee if) expression, (b) the term contains enough
 variables so that when they are instantiated and the hypotheses are relieved
 (which may bind some free variables; see @(see free-variables)) then all the
 variables in @('concl') are instantiated, and (c) no other addend is always
 ``bigger'' than the term, in the technical sense described below.</p>

 <p>The technical notion referenced above depends on the notion of
 <i>fn-count</i>, the number of function symbols in a term, and
 <i>pseudo-fn-count</i>, which is essentially the number of function symbols
 implicit in a constant (see @(see term-order), specifically the discussion of
 ``pseudo-function application count'' at the end).  We say @('term1') is
 always bigger than @('term2') if all instances of @('term1') have a larger
 fn-count (actually lexicographic order of fn-count and pseudo-fn-count) than
 the corresponding instances of @('term2').  This is equivalent to saying that
 the fn-count of @('term1') is larger than that of @('term2') (by ``fn-count''
 here we mean the lexicographic order of fn-count and pseudo-fn-count) and the
 variable bag for @('term2') is a subbag of that for @('term1').  For example,
 @('(/ a (* b b))') is always bigger than @('(fn a b)') because the first has
 two function applications and @('{a b}') is a subbag of @('{a b b}'), but
 @('(/ a (* b b))') is not always bigger than @('(fn a x)').</p>")

(defxdoc linear-arithmetic
  :parents (linear)
  :short "A description of the linear arithmetic decision procedure"
  :long "<p>We describe the procedure very roughly here.  Fundamental to the
 procedure is the notion of a linear polynomial inequality.  A ``linear
 polynomial'' is a sum of terms, each of which is the product of a rational
 constant and an ``unknown.''  The ``unknown'' is permitted to be @('1') simply
 to allow a term in the sum to be constant.  Thus, an example linear polynomial
 is @('3*x + 7*a + 2'); here @('x') and @('a') are the (interesting) unknowns.
 However, the unknowns need not be variable symbols.  For example, @('(length
 x)') might be used as an unknown in a linear polynomial.  Thus, another linear
 polynomial is @('3*(length x) + 7*a').  A ``linear polynomial inequality'' is
 an inequality (either @(tsee <) or @(tsee <=)) relation between two linear
 polynomials.  Note that an equality may be considered as a pair of
 inequalities; e.q., @('3*x + 7*a + 2 = 0') is the same as the conjunction of
 @('3*x + 7*a + 2 <= 0') and @('0 <= 3*x + 7*a + 2').</p>

 <p>Certain linear polynomial inequalities can be combined by
 cross-multiplication and addition to permit the deduction of a third
 inequality with fewer unknowns.  If this deduced inequality is manifestly
 false, a contradiction has been deduced from the assumed inequalities.</p>

 <p>For example, suppose we have two assumptions</p>

 @({
  p1:       3*x + 7*a <  4
  p2:               3 <  2*x
 })

 <p>and we wish to prove that, given @('p1') and @('p2'), @('a < 0').  As
 suggested above, we proceed by assuming the negation of our goal</p>

 @({
  p3:               0 <= a.
 })

 <p>and looking for a contradiction.</p>

 <p>Our first step will be to eliminate the variable @('x').  To that end, we
 cross-multiply based on the coefficients of @('x') in the two inequalities.
 By multiplying @('p1') by @('2') and @('p2') by @('3'), and then adding the
 respective sides, we deduce the intermediate result</p>

 @({
  p4:  6*x + 14*a + 9 < 8 + 6*x
 })

 <p>which, after cancellation, is:</p>

 @({
  p4:        14*a + 1 <  0.
 })

 <p>If we then cross-multiply and add @('p3') to @('p4'), we get</p>

 @({
  p5:               1 <= 0,
 })

 <p>a contradiction.  Thus, we have proved that @('p1') and @('p2') imply the
 negation of @('p3').</p>

 <p>All of the unknowns of an inequality must be eliminated by cancellation in
 order to produce a constant inequality.  We can choose to eliminate the
 unknowns in any order, but we eliminate them in term-order, largest unknowns
 first.  (See @(see term-order).)  That is, two polys are canceled against
 each other only when they have the same largest unknown.  For instance, in the
 above example we see that @('x') is the largest unknown in each of @('p1') and
 @('p2'), and @('a') in @('p3') and @('p4').</p>

 <p>Now suppose that this procedure does not produce a contradiction but
 instead yields a set of nontrivial inequalities.  A contradiction might still
 be deduced if we could add to the set some additional inequalities allowing
 further cancellations.  That is where @(':linear') lemmas come in.  When the
 set of inequalities has stabilized under cross-multiplication and addition and
 no contradiction is produced, we search the database of @(':')@(tsee linear)
 rules for rules about the unknowns that are candidates for cancellation (i.e.,
 are the largest unknowns in their respective inequalities).  See @(see linear)
 for a description of how @(':')@(tsee linear) rules are used.</p>

 <p>See also @(tsee non-linear-arithmetic) for a description of an extension to
 the linear-arithmetic procedure described here.</p>")

(defxdoc list
  :parents (lists acl2-built-ins)
  :short "Build a list"
  :long "<p>@('List') is the macro for building a list of objects.  For
 example, @('(list 5 6 7)') returns a list of length 3 whose elements are
 @('5'), @('6'), and @('7') respectively.  Also see @(see list*).</p>

 <p>@('List') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>

 @(def list)
 @(def list-macro)")

(defxdoc list*
  :parents (lists acl2-built-ins)
  :short "Build a list"
  :long "<p>@('List*') is the Common Lisp macro for building a list of objects
 from given elements and a tail.  For example, @('(list* 5 6 '(7 8 9))') equals
 the list @(''(5 6 7 8 9)').  Also see @(see list).</p>

 <p>@('List*') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def list*)
 @(def list*-macro)")

(defxdoc listp
  :parents (lists conses acl2-built-ins)
  :short "Recognizer for (not necessarily proper) lists"
  :long "<p>@('(listp x)') is true when @('x') is either a @(tsee cons) pair or
 is @('nil').</p>

 <p>@('Listp') has no @(see guard), i.e., its @(see guard) is @('t').</p>

 <p>@('Listp') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def listp)")

(defxdoc lists
  :parents (programming)
  :short "Lists of objects, the classic Lisp data structure.")

(defxdoc local
  :parents (events)
  :short "Hiding an event in an encapsulation or book"
  :long "@({
  Examples:
  (local (defthm hack1
           (implies (and (acl2-numberp x)
                         (acl2-numberp y)
                         (equal (* x y) 1))
                    (equal y (/ x)))))

  (local (defun double-naturals-induction (a b)
           (cond ((and (integerp a) (integerp b) (< 0 a) (< 0 b))
                  (double-naturals-induction (1- a) (1- b)))
                 (t (list a b)))))

  General Form:
  (local ev)
 })

 <p>where @('ev') is an event form.  If the current default @(see defun-mode)
 (see @(see default-defun-mode)) is @(':')@(tsee logic) and @(tsee
 ld-skip-proofsp) is @('nil') or @('t'), then @('(local ev)') is equivalent to
 @('ev').  But if the current default @(see defun-mode) is @(':')@(tsee
 program) or if @(tsee ld-skip-proofsp) is @(''')@(tsee include-book), then
 @('(local ev)') is a @('no-op').  Thus, if such forms are in the event list of
 an @(tsee encapsulate) event or in a book, they are processed when the
 encapsulation or book is checked for admissibility in @(':')@(tsee logic) mode
 but are skipped when extending the host @(see world).  Such @(see events) are
 thus considered ``local'' to the verification of the encapsulation or book.
 The non-local @(see events) are the ones ``exported'' by the encapsulation or
 book.  See @(see encapsulate) for a thorough discussion.  Also see @(see
 local-incompatibility) for a discussion of a commonly encountered problem with
 such event hiding: you can't make an event local if its presence is required
 to make sense of a non-local one.</p>

 <p>Note that @(see events) that change the default @(see defun-mode), and in
 fact any @(see events) that set the @(tsee acl2-defaults-table), are
 disallowed inside the scope of @('local').  See @(see
 embedded-event-form).</p>")

(defxdoc local-incompatibility
  :parents (miscellaneous)
  :short "When non-local @(see events) won't replay in isolation"
  :long "<p>Sometimes a ``@(tsee local) incompatibility'' is reported while
 attempting to embed some @(see events), as in an @(tsee encapsulate) or @(tsee
 include-book).  This is generally due to the use of a locally defined name in
 a non-local event or the failure to make a witnessing definition @(tsee
 local).</p>

 <p>@(tsee Local) incompatibilities may be detected while trying to execute the
 strictly non-local @(see events) of an embedding.  For example, @(tsee
 encapsulate) operates by first executing all the @(see events) (@(tsee local)
 and non-local) with @(tsee ld-skip-proofsp) @('nil'), to confirm that they are
 all admissible.  Then it attempts merely to assume the non-local ones to
 create the desired theory, by executing the @(see events) with @(tsee
 ld-skip-proofsp) set to @(''')@(tsee include-book).  Similarly, @(tsee
 include-book) assumes the non-local ones, with the understanding that a
 previously successful @(tsee certify-book) has performed the admissibility
 check.</p>

 <p>How can a sequence of @(see events) admitted with @(tsee ld-skip-proofsp)
 @('nil') fail when @(tsee ld-skip-proofsp) is @(''')@(tsee include-book)?  The
 key observation is that in the latter case only the non-local @(see events)
 are processed.  The @(tsee local) ones are skipped and so the non-local ones
 must not depend upon them.</p>

 <p>Two typical mistakes are suggested by the detection of a @(tsee local)
 incompatibility: (1) a locally defined function or macro was used in a
 non-@(tsee local) event (and, in the case of @(tsee encapsulate), was not
 included among the @(see signature)s) and (2) the witnessing definition of a
 function that was included among the @(see signature)s of an @(tsee
 encapsulate) was not made @(tsee local).</p>

 <p>An example of mistake (1) would be to include among your @(see
 encapsulate)d @(see events) both a local definition of @('f') and a non-local
 theorem about @('f'), for example as follows.</p>

 @({
 (encapsulate ()
   (local (defun f (x) x))
   (defun g (x) x)

   (defthm f-is-g (equal (f x) (g x)))
   )
 })

 <p>In this case, either the @(tsee defthm) should be made @(tsee local) or, if
 we want to export the @('defthm'), then the @(tsee defun) of @('f') should be
 made non-local.</p>

 <p>An example of mistake (2) would be to include @('((fn *) => *)') among your
 @(see signature)s and then to write @('(defun fn (x) ...)') in your @(see
 events), instead of @('(local (defun fn ...))'), as shown in the example
 below.  In essence, this is an error because @('fn') is exported twice: once
 by the signature and once by the @('defun').</p>

 @({
 (encapsulate
   ( ((fn *) => *) )

   (defun fn (x) x)
   )
 })

 <p>One subtle aspect of @(tsee encapsulate) is that if you constrain any
 member of a mutually recursive clique you must define the entire clique
 locally and then you must constrain those members of it you want axiomatized
 non-locally.</p>

 <p>Errors due to @(tsee local) incompatibility should never occur in the
 assumption of a fully certified book.  Certification ensures against it.
 Therefore, if @(tsee include-book) reports an incompatibility, we assert that
 earlier in the processing of the @(tsee include-book) a warning was printed
 advising you that some book was uncertified.  If this is not the case &mdash;
 if @(tsee include-book) reports an incompatibility and there has been no prior
 warning about lack of certification &mdash; please report it to us.</p>

 <p>When a @(tsee local) incompatibility is detected, we roll-back to the @(see
 world) in which we started the @(tsee encapsulate) or @(tsee include-book).
 That is, we discard the intermediate @(see world) created by trying to process
 the @(see events) skipping proofs.  This is clean, but we realize it is very
 frustrating because the entire sequence of @(see events) must be processed
 from scratch.  Assuming that the embedded @(see events) were, once upon a
 time, processed as top-level @(see command)s (after all, at some point you
 managed to create this sequence of @(see command)s so that the @(tsee local)
 and non-local ones together could survive a pass in which proofs were done),
 it stands to reason that we could define a predicate that would determine
 then, before you attempted to embed them, if @(tsee local) incompatibilities
 exist.  We hope to do that, eventually.</p>

 <p>We conclude with a subtle example of @(tsee local) incompatibility.  The
 problem is that in order for @('foo-type-prescription') to be admitted using
 the specified @(':typed-term') @('(foo x)'), the conclusion @('(my-natp (foo
 x))') depends on @('my-natp') being a @(see compound-recognizer).  This is
 fine on the first pass of the @(tsee encapsulate), during which lemma
 @('my-natp-cr') is admitted.  But @('my-natp-cr') is skipped on the second
 pass because it is marked @(tsee local), and this causes
 @('foo-type-prescription') to fail on the second pass.</p>

 @({
  (defun my-natp (x)
    (declare (xargs :guard t))
    (and (integerp x)
         (<= 0 x)))

  (defun foo (x)
    (nfix x))

  (encapsulate
   ()
   (local (defthm my-natp-cr
            (equal (my-natp x)
                   (and (integerp x)
                        (<= 0 x)))
            :rule-classes :compound-recognizer))
   (defthm foo-type-prescription
     (my-natp (foo x))
     :hints ((\"Goal\" :in-theory (enable foo)))
     :rule-classes ((:type-prescription :typed-term (foo x)))))
 })")

(defxdoc logand
  :parents (numbers acl2-built-ins)
  :short "Bitwise logical `and' of zero or more integers"
  :long "<p>When integers are viewed in their two's complement representation,
 @('logand') returns their bitwise logical `and'.  In ACL2 @('logand') is a
 macro that expands into calls of the binary function @('binary-logand'),
 except that @('(logand)') expands to @('-1') and @('(logand x)') expands to
 @('x').</p>

 <p>The @(see guard) for @('binary-logand') requires its arguments to be
 integers.  @('Logand') is defined in Common Lisp.  See any Common Lisp
 documentation for more information.</p>

 @(def logand)
 @(def binary-logand)")

(defxdoc logandc1
  :parents (numbers acl2-built-ins)
  :short "Bitwise logical `and' of two ints, complementing the first"
  :long "<p>When integers are viewed in their two's complement representation,
 @('logandc1') returns the bitwise logical `and' of the second with the bitwise
 logical `not' of the first.</p>

 <p>The @(see guard) for @('logandc1') requires its arguments to be integers.
 @('Logandc1') is defined in Common Lisp.  See any Common Lisp documentation
 for more information.</p>

 @(def logandc1)")

(defxdoc logandc2
  :parents (numbers acl2-built-ins)
  :short "Bitwise logical `and' of two ints, complementing the second"
  :long "<p>When integers are viewed in their two's complement representation,
 @('logandc2') returns the bitwise logical `and' of the first with the bitwise
 logical `not' of the second.</p>

 <p>The @(see guard) for @('logandc2') requires its arguments to be integers.
 @('Logandc2') is defined in Common Lisp.  See any Common Lisp documentation
 for more information.</p>

 @(def logandc2)")

(defxdoc logbitp
  :parents (numbers acl2-built-ins)
  :short "The @('i')th bit of an integer"
  :long "<p>For a nonnegative integer @('i') and an integer @('j'), @('(logbitp
 i j)') is a Boolean, which is @('t') if and only if the value of the @('i')th
 bit is @('1') in the two's complement representation of @('j').</p>

 <p>@('(Logbitp i j)') has a @(see guard) that @('i') is a nonnegative integer
 and @('j') is an integer.</p>

 <p>@('Logbitp') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def logbitp)")

(defxdoc logcount
  :parents (numbers acl2-built-ins)
  :short "Number of ``on'' bits in a two's complement number"
  :long "<p>@('(Logcount x)') is the number of ``on'' bits in the two's
 complement representation of @('x').</p>

 <p>@('(Logcount x)') has a @(see guard) of @('(integerp x)').</p>

 <p>@('Logcount') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def logcount)")

(defxdoc logeqv
  :parents (numbers acl2-built-ins)
  :short "Bitwise logical equivalence of zero or more integers"
  :long "<p>When integers are viewed in their two's complement representation,
 @('logeqv') returns their bitwise logical equivalence.  In ACL2 @('logeqv') is
 a macro that expands into calls of the binary function @('binary-logeqv'),
 except that @('(logeqv)') expands to @('-1') and @('(logeqv x)') expands to
 @('x').</p>

 <p>The @(see guard) for @('binary-logeqv') requires its arguments to be
 integers.  @('Logeqv') is defined in Common Lisp.  See any Common Lisp
 documentation for more information.</p>

 @(def logeqv)
 @(def binary-logeqv)")

(defxdoc logic
  :parents (defun-mode)
  :short "To set the default @(see defun-mode) to @(':logic')"
  :long "@({
  Example:
  ACL2 p!>:logic
  ACL2 !>
 })

 <p>Typing the keyword @(':logic') sets the default @(see defun-mode) to
 @(':logic').</p>

 <p>Functions defined in @(':logic') mode are logically defined.  See @(see
 defun-mode).</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 <p>See @(see defun-mode) for a discussion of the @(see defun-mode)s available
 and what their effects on the logic are.  See @(see default-defun-mode) for a
 discussion of how the default @(see defun-mode) is used.  This event is
 equivalent to @('(table acl2-defaults-table :defun-mode :logic)'), and hence
 is @(tsee local) to any @(see books) and @(tsee encapsulate) @(see events) in
 which it occurs. See @(see acl2-defaults-table).</p>

 <p>Recall that the top-level form @(':logic') is equivalent to @('(logic)');
 see @(see keyword-commands).  Thus, to change the default @(see defun-mode) to
 @(':logic') in a book, use @('(logic)'), which is an embedded event form,
 rather than @(':logic'), which is not a legal form for @(see books).  See
 @(see embedded-event-form).</p>")

(defxdoc logic-fns-list-listp
  :parents (termp acl2-built-ins)
  :short "Recognizer for when a given list of lists of @(see term)s calls only
 @(':')@(tsee logic)-mode function symbols"
  :long "<p>For a list @('x') of lists of @(see term)s in @(see world)
 @('wrld'), @('(logic-fns-list-listp x wrld)') is true if and only if every
 function symbol called in @('x') is in @(':')@(tsee logic) mode in @('wrld').
 Unlike @(tsee logic-term-list-listp), @('logic-fns-list-listp') does not check
 that @('x') is a list of lists of terms; rather, @('logic-fns-list-listp')
 should only be applied to such lists.</p>

 @(def logic-fns-list-listp)")

(defxdoc logic-fns-listp
  :parents (termp acl2-built-ins)
  :short "Recognizer for when a given list of @(see term)s calls only
 @(':')@(tsee logic)-mode function symbols"
  :long "<p>For a list @('x') of @(see term)s in @(see world) @('wrld'),
 @('(logic-fns-listp x wrld)') is true if and only if every function symbol
 called in @('x') is in @(':')@(tsee logic) mode in @('wrld').  Unlike @(tsee
 logic-term-listp), @('logic-fns-listp') does not check that @('x') is a list
 of terms; rather, @('logic-fns-listp') should only be applied to such
 lists.</p>

 @(def logic-fns-listp)")

(defxdoc logic-fnsp
  :parents (termp acl2-built-ins)
  :short "Recognizer for when a given @(see term) calls only @(':')@(tsee
 logic)-mode function symbols"
  :long "<p>For a @(see term) @('x') in @(see world) @('wrld'), @('(logic-fnsp
 x wrld)') is true if and only if every function symbol called in @('x') is in
 @(':')@(tsee logic) mode in @('wrld').  Unlike @(tsee logic-termp),
 @('logic-fnsp') does not check that @('x') is a term; rather, @('logic-fnsp')
 should only be applied to terms.</p>

 @(def logic-fnsp)")

(defxdoc logic-knowledge-taken-for-granted
  :parents (introduction-to-the-theorem-prover)
  :short "Background knowledge in ACL2 logic for theorem prover tutorial"
  :long "<p>You might think that in order to use the theorem prover you have to
 know the mathematical logic supported by ACL2.  But you need to know a lot
 less about it than you might think.</p>

 <p>Technically, a theorem is a formula that can be derived from axioms by
 using rules of inference.  Thus, to do a proof you have to know (a) the syntax
 of formulas, (b) the axioms, and (c) the rules of inference.  Traditionally,
 these things are spelled out in excruciating detail in treatments of
 mathematical logic &mdash; and for good reason.</p>

 <p>The whole point of proving theorems is that it is a way to determine that a
 formula is ``always true'' (under some model of the axioms).  By ``always
 true'' we actually mean what logicians mean when they say the formula is
 <i>valid</i>: true in the model, for all possible values of the variables.
 Here by ``model of the axioms'' we mean an understanding of the meaning of the
 various function symbols so that the axioms are true for all values of the
 variables.  If the variables in your conjecture can take on an infinite number
 of values, proof is often the <b>only</b> way to determine that a conjecture
 is ``always true.''  So if proof is being used to determine that a
 questionable formula is always true the proof must be carried out flawlessly.
 Thus, the (a) syntax, (b) axioms, and (c) rules of inference must be described
 precisely and followed to the letter.</p>

 <p>But formal mathematical logic was invented to explain how people reason.
 To the extent that logic mimics human reasoning, proofs can be seen as just
 extremely carefully crafted arguments.  Given that ACL2 is responsible for
 following the rules ``to the letter,'' your main job is ``explain'' the big
 leaps.</p>

 <p>To use the theorem prover you must understand (a) the syntax, because you
 must be able to write formulas flawlessly.  But you don't have to know (b) the
 axioms and (c) the rules of inference at nearly the same level of precision,
 as long as you understand the basic structure and language of proofs.</p>

 <p>Below is part of a proof of a certain theorem.  You ought to be able to
 understand the following.  Since what we describe is a proof of one case of
 the formula, we hope that you're <i>convinced</i> that the formula holds for
 that case.</p>

 <p>Read this and follow the links to confirm that you understand what happens.
 Be sure to then use your browser's <b>Back Button</b> to return to this page
 and continue.</p>

 <p><b>An Annotated Proof of</b></p>

 @({
  (implies (true-listp z)
           (equal (rev (rev z)) z))
 })

 <p>``We will prove that reversing the reverse of a @('true-listp') yields the
 original list.  The formula stating this is above.  We will prove it by <see
 topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INDUCTIVE-PROOF)'>induction</see> on the
 list structure of @('z').</p>

 <p>The <see topic='@(url LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-BASE-CASE)'>base
 case</see> of the induction is:</p>

 @({
  (implies (endp z)
           (implies (true-listp z)
                    (equal (rev (rev z)) z))).
 })

 <p>This formula is equivalent, by <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-PROPOSITIONAL-CALCULUS)'>propositional
 calculus</see>, to</p>

 @({
  (implies (and (endp z)
                (true-listp z))
           (equal (rev (rev z)) z))
 })

 <p><see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-REWRITING)'>Rewriting</see> with the
 definition of @('endp') produces:</p>

 @({
  (implies (and (not (consp z))
                (true-listp z))
           (equal (rev (rev z)) z))
 })

 <p><see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-REWRITING-REPEATEDLY)'>Rewriting
 repeatedly</see> starting with the definition of @('true-listp') produces:</p>

 @({
  (implies (and (not (consp z))
                (equal z nil))
           (equal (rev (rev z)) z))
 })

 <p>Then using the second <i>hypothesis</i>, just <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-EQUALS-FOR-EQUALS)'>substituting equals for
 equals</see>, we get</p>

 @({
  (implies (and (not (consp z))
                (equal z nil))
           (equal (rev (rev nil)) nil))
 })

 <p>Since the <i>conclusion</i> involves no variables, we can <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-EVALUATION)'>evaluate</see> it, getting</p>

 @({
  (implies (and (not (consp z))
                (equal z nil))
           T)
 })

 <p>But this is an <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INSTANCE)'>instance</see> of the <see
 topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-PROPOSITIONAL-CALCULUS)'>tautology</see>
 @('(implies p T)').  Thus, the base case is proved.''</p>

 <p>Now it is time for a little quiz.  There are just three questions.</p>

 <p><b>Q1</b>: The case above was the Base Case of an inductive proof of</p>

 @({
  (implies (true-listp z)
           (equal (rev (rev z)) z))
 })

 <p>in which we did induction on the structure of the linear list @('z').  What
 is the Induction Step?  That is, what do you have to prove besides the Base
 Case to complete this inductive proof?</p>

 <p>Below are four commonly given answers; choose one.  Then look <see
 topic='@(url LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-Q1-ANSWER)'>here</see> to find
 out if you're right.</p>

 <code>
 <i>Induction Step -- Choice (i)</i>:
 (implies (not (endp z))
          (implies (true-listp z)
                   (equal (rev (rev z)) z)))

 <i>Induction Step -- Choice (ii)</i>:
 (implies (true-listp (cdr z))
          (equal (rev (rev (cdr z))) (cdr z)))

 <i>Induction Step -- Choice (iii)</i>:
 (implies (and (not (endp z))
               (equal (rev (rev (cdr x))) (cdr x)))
          (implies (true-listp z)
                   (equal (rev (rev z)) z)))

 <i>Induction Step -- Choice (iv)</i>:
 (implies (and (not (endp z))
               (implies (true-listp (cdr z))
                        (equal (rev (rev (cdr z))) (cdr z))))
          (implies (true-listp z)
                   (equal (rev (rev z)) z)))
 </code>

 <p><b>Q2</b>: To prove the Induction Step we must prove one or more of the
 goals below.</p>

 <p>Which combinations are sufficient to imply the Induction Step?  Decide what
 is required and then look <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-Q2-ANSWER)'>here</see> to find out if you're
 right.  To help you, the Induction Step is of the form:</p>

 <code>
 <i>Induction Step</i>:
 (implies (and <i>c</i>
               (implies <i>p'</i> <i>q'</i>))
          (implies <i>p</i> <i>q</i>))
 </code>

 <p>and beside each candidate subgoal we show its structure in those terms.</p>

 <code>
 <i>Subgoal (i)</i>:
 (implies (and (not (endp z))                        ; (implies (and <i>c</i>
               (true-listp z))                       ;               <i>p</i>)
          (true-listp (cdr z)))                      ;          <i>p'</i>)

 <i>Subgoal (ii)</i>:
 (implies (and (not (endp z))                        ; (implies (and <i>c</i>
               (true-listp z)                        ;               <i>p</i>
               (equal (rev (rev (cdr z))) (cdr z)))  ;               <i>q'</i>)
          (equal (rev (rev z)) z))                   ;          <i>q</i>)

 <i>Subgoal (iii)</i>:
 (implies (and (not (endp z))                        ; (implies (and <i>c</i>
               (equal (rev (rev (cdr z))) (cdr z)))  ;               <i>q'</i>)
          (equal (rev (rev z)) z))                   ;          <i>q</i>)

 <i>Subgoal (iv)</i>:
 (implies (and (not (endp z))                        ; (implies (and <i>c</i>
               (true-listp (cdr z))                  ;               <i>p'</i>
               (equal (rev (rev (cdr z))) (cdr z)))  ;               <i>q'</i>)
          (equal (rev (rev z)) z))                   ;          <i>q</i>)
 </code>

 <p><b>Q3</b>: Suppose you know the theorem</p>

 <code>
 <i>Theorem</i>:
 (implies (p (f x))
          (equal (g (h x))
                 x))
 </code>

 <p>and you wish to rewrite the target @('(g (h a))') to @('a') in</p>

 <code>
 <i>Goal Conjecture</i>:
 (implies (and (q (f a))
               (r a))
          (s (g (h a))))
 </code>

 <p>What must you prove to relieve the hypothesis of <i>Theorem</i>?</p>

 <p>After you've thought about it, look <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-Q3-ANSWER)'>here</see> for our answer.</p>

 <p><b>End of the Quiz</b></p>

 <p>If this page made sense, you're ready to read the introduction to the
 theorem prover.</p>

 <p>If you are reading this as part of the tutorial introduction to the theorem
 prover, use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-the-theorem-prover).</p>")

(defxdoc logic-knowledge-taken-for-granted-base-case
  :parents (introduction-to-the-theorem-prover)
  :short "A brief explanation of base cases"
  :long "<p>According to the sentence, the conjecture being proved is
 ``reversing the reverse of a @('true-listp') yields the original list.''  The
 formula corresponding to this conjecture is:</p>

 @({
  (implies (true-listp z)
           (equal (rev (rev z)) z)).
 })

 <p>We're also told that this is an inductive proof.  Evidently we're doing an
 induction on the structure of the list @('z').  Then the <i>Base Case</i> is
 the formula:</p>

 @({
  (implies (endp z)
           (implies (true-listp z)
                    (equal (rev (rev z)) z))).
 })

 <p>Now use your browser's <b>Back Button</b> to return to the example proof in
 @(see logic-knowledge-taken-for-granted).</p>")

(defxdoc logic-knowledge-taken-for-granted-equals-for-equals
  :parents (introduction-to-the-theorem-prover)
  :short "Substitution of equals for equals"
  :long "<p>Anytime you have an equality hypothesis relating two terms,
  e.g.,</p>

 <code>
 (equal <i>lhs</i> <i>rhs</i>)
 </code>

 <p>it is legal to substitute one for the other anyplace else in the formula.
 Doing so does not change the truth value of the formula.</p>

 <p>You can use a <i>negated equality</i> this way <i>provided</i> it appears
 in the conclusion.  For example, it is ok to transform</p>

 @({
  (implies (true-listp x)
           (not (equal x 23)))
 })

 <p>to</p>

 @({
  (implies (true-listp 23)
           (not (equal x 23)))
 })

 <p>by substitutions of equals for equals.  That is because, by <see
 topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-PROPOSITIONAL-CALCULUS)'>propositional
 calculus</see>, we could rearrange the formulas into their
 <i>contrapositive</i> forms:</p>

 @({
  (implies (equal x 23)
           (not (true-listp x)))
 })

 <p>and</p>

 @({
  (implies (equal x 23)
           (not (true-listp 23)))
 })

 <p>and see the equality as a hypothesis and the substitution of @('23') for
 @('x') as sensible.</p>

 <p>Sometimes people speak loosely and say ``substitution of equals for
 equals'' when they really mean ``substitutions of equivalents for
 equivalents.''  Equality, as tested by @('EQUAL'), is only one example of an
 equivalence relation.  The next most common is propositional equivalence, as
 tested by @('IFF').  You can use propositional equivalence hypotheses to
 substitute one side for the other <i>provided</i> the target term occurs in a
 propositional place, as discussed at the bottom of <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-PROPOSITIONAL-CALCULUS)'>propositional
 calculus</see>.</p>

 <p>Now use your browser's <b>Back Button</b> to return to the example proof in
 @(see logic-knowledge-taken-for-granted).</p>")

(defxdoc logic-knowledge-taken-for-granted-evaluation
  :parents (introduction-to-the-theorem-prover)
  :short "Evaluation during proofs"
  :long "<p>Any time you are proving a formula and see a subterm in the formula
 that contains no variables, you can just evaluate the subterm.</p>

 <p>This is familiar from algebra: It is not uncommon to rearrange a
 polynomial to collect all the constants and then add them up:</p>

 @({
  (3x + 2 + 7y + 2)
  =
  (3x + 7y + (2 + 2))
  =
  (3x + 7y + 4).
 })

 <p>That last step is just evaluation.</p>

 <p>It happens often in ACL2 proofs because theorems involve constants and
 defined functions and when those constants ``drift into the maw'' of a
 function, the function call can be eliminated and replaced by a new constant.
 ACL2 does this automatically; you don't have to tell it.  In fact, there are a
 few occasions where you might prefer it <i>not</i> evaluate and those are the
 ones you have to look out for!  They'll be obvious when they happen because
 you'll see a mysterious constant crop up in the proof.</p>

 <p>Evaluation is legal because it is just the repeated use of unconditional
 rewriting to replace definitions by their instantiated bodies until no
 function calls remain.</p>

 <p>Now use your browser's <b>Back Button</b> to return to the example proof in
 @(see logic-knowledge-taken-for-granted).</p>")

(defxdoc logic-knowledge-taken-for-granted-inductive-proof
  :parents (introduction-to-the-theorem-prover)
  :short "A brief explanation of induction"
  :long "<p>We start by showing classical induction on the natural numbers in
 an ACL2 setting before turning to a more general treatment of induction.</p>

 <p><b>Classical Induction on Natural Numbers</b>: Induction is familiar in the
 arithmetic setting.  Let @('(p n)') denote some formula involving the variable
 @('n') (and perhaps some other variables which we don't exhibit).  Then to
 prove @('(p n)'), for all @('n'), by classical induction on the construction
 of the natural numbers, prove each of the following:</p>

 <code>
 <i>Base Case</i>:
 (implies (zp n) (p n))
 </code>

 <code>
 <i>Induction Step</i>:
 (implies (and (not (zp n))
               (p (- n 1)))
          (p n))
 </code>

 <p>The Base Case establishes that @('p') holds for @('0').  In fact, because
 of the definition of @(tsee zp) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>, it
 establishes that @('(p n)') holds when @('n') is @('0') and it holds when
 @('n') is not a natural number.</p>

 <p>The Induction Step establishes that if @('n') is a natural number other
 than @('0'), and if @('p') holds for @('n')-1, then @('p') holds for @('n').
 The hypothesis @('(p (- n 1))') above is called the <i>induction
 hypothesis</i>.</p>

 <p>Note that if the Base Case and Induction Step are valid, then we know @('(p
 n)'), for all @('n').  You can convince yourself of this by picking any object
 and asking ``how do I know @('p') holds for this object?''  For example, @('(p
 -7)'), @('(p 'abc)'), and @('(p 0)') are all established by the Base Case.
 What about @('(p 1)')?  That follows from @('(p 0)'), given the Induction
 Step.  Why?  To prove @('(p 1)') using the Induction Step, you have to
 establish @('(not (zp 1))'), which is true, and @('(p (- 1 1))'), which is
 @('(p 0)'), which is true by the Base Case.  So @('(p 1)') is true.  Similar
 reasoning proves @('(p 2)') from from @('(p 1)'), etc.  Clearly, for every
 natural number other than @('0') we could reason like this to show that @('p')
 holds.  Since the Base Case handled all the objects that are not natural
 numbers, and handled @('0'), we know @('(p n)'), for all @('n').</p>

 <p>There is a duality between recursion and induction that ACL2 exploits.  The
 fact that the Base and Induction steps above are sufficient to prove @('p')
 for all objects is related to the fact that the following recursion defines a
 total, terminating function:</p>

 @({
  (defun nat-recursion (n)
    (if (zp n)
        n
        (nat-recursion (- n 1))))
 })

 <p>When this function is admitted we have to prove that if @('(zp n)') does
 not hold, then @('(- n 1)') is smaller, in some sense, than @('n').  This
 sense of ``smaller'' is determined by some <i>measure</i> of the arguments.
 That measure must return an ordinal (see @(see ordinals) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>),
 but the most common measures return natural numbers, which are among the
 ordinals.  Furthermore, that measure should insure that the terms in the
 recursive calls are smaller than the formals, i.e., the measure of @('(- n
 1)') must be smaller than the measure of @('n'), when the recursive branches
 are taken.  This sense of ``smaller'' must be <i>well-founded</i>: it must be
 impossible to have an infinitely descending chain of smaller things.  This is
 true of the less-than relation on the ordinals (see @(tsee o<) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>).
 Well-foundedness means that eventually any recursion must ``bottom out''
 because things can't keep getting smaller forever.</p>

 <p>The recursion in @('nat-recursion') <b>suggests</b> the induction shown
 above: the Base Case is defined by the @('if') branch that does not lead to a
 recursive call.  The Induction Step is defined by the other branch.  The
 induction hypothesis is defined by what we recur on, i.e., @('(- n 1)').  The
 theorems proved when @('nat-recursion') is introduced <i>justify</i> the
 classical induction scheme noted above.</p>

 <p>Every recursively defined ACL2 function suggests a legal induction and vice
 versa.</p>

 <p>Furthermore, every call of a recursively defined function on distinct
 variable symbols also suggests a legal induction: just take the induction
 suggested by the function's recursive definition after renaming the formal
 parameters to be the variables in the call.</p>

 <p>For example, it should be clear that @('(nat-recursion a)') suggests a Base
 Case defined by @('(zp a)'), and induction step defined by @('(not (zp a))')
 and an induction hypothesis about @('(- a 1)').</p>

 <p>Note that the term @('(fact n)') suggests the same classical induction on
 natural numbers shown above, where @('fact') is defined as follows (even
 though we've used the formal parameter @('k') below).</p>

 @({
  (defun fact (k)
    (if (zp k)
        1
        (* k (fact (- k 1)))))
 })

 <p>The induction suggested by a term like @('(fact n)') is insensitive to the
 name of the formal parameter used in the @('defun').</p>

 <p>The induction suggested by a function or term is insensitive to the value
 returned by the function or term.</p>

 <p>It doesn't matter what the function returns in its ``base case'' (e.g.,
 @('1') in @('fact')) or what the function ``does'' to its recursive call
 (e.g., multiply by @('k') in the @('defun') of @('fact')).</p>

 <p>All that matters is (i) how the @('if') structure breaks down the cases on
 @('k'), (ii) which branches lead to recursion, and (iii) what arguments are
 passed to the recursive calls.  Those things determine (i) the case analysis
 of the induction scheme, (ii) which cases are Base Cases and which are
 Induction Steps, and (iii) what the induction hypotheses are.</p>

 <p>For a selection of common inductions schemes in ACL2 (e.g., on the
 structure of natural numbers, lists, and trees and on several variables at
 once, multiple base cases, multiple induction hypotheses, multiple induction
 steps, etc.)  <see topic='@(url EXAMPLE-INDUCTIONS)'>check this
 link</see>.</p>

 <p>Every legal ACL2 induction corresponds to an admissible recursive function
 and vice versa.  Similarly, every legal ACL2 induction corresponds to a call
 of a recursively defined function on distinct variables.</p>

 <p>ACL2 chooses which induction to do by looking at the terms that occur in
 the conjecture.  For many elementary theorems, ACL2 chooses the right
 induction by itself.</p>

 <p>You may occasionally need to tell it what induction to do.  You do that by
 showing it a term that suggests the induction you want.  We'll explain how you
 communicate this to ACL2 later.  If you understand how recursive functions
 suggest inductions, then you know what you need to know to use ACL2.</p>

 <p>The main point of this discussion of induction is familiarize you with the
 basic terms: <i>Base Case</i> (of which there may be several), <i>Induction
 Step</i> (of which there may be several), <i>Induction Hypothesis</i> (of
 which there may be several in each Induction Step), <i>measure</i> and
 <i>well-founded relation</i> <i>justifying</i> an induction, and the induction
 <i>suggested</i> by a term or recursive function definition.  Furthermore,
 every Induction Hypothesis is always an <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INSTANCE)'>instance</see> of the conjecture
 being proved: each induction hypothesis is obtained from the conjecture being
 proved by applying a <i>substitution</i> replacing variables by terms.</p>

 <p>If you are reviewing the material taken for granted about logic while
 working your way through the introduction to the theorem prover, please use
 your browser's <b>Back Button</b> to return to the example proof in @(see
 logic-knowledge-taken-for-granted).</p>")

(defxdoc logic-knowledge-taken-for-granted-instance
  :parents (introduction-to-the-theorem-prover)
  :short "A brief explanation of substitution instances"
  :long "<p>Let <i>p</i> and <i>q</i> be terms or formulas (there is no
 difference in ACL2).  Then we say <i>p</i> is an <i>instance</i> or
 <i>substitution instance</i> of <i>q</i> if and only if <i>p</i> can be
 obtained from <i>q</i> by uniformly replacing the variables of <i>q</i> by
 terms.  Sometimes we call <i>p</i> the <i>target</i> and <i>q</i> the
 <i>pattern</i> because by choosing appropriate replacements we can make the
 pattern <i>match</i> many different targets.</p>

 <p>For example, the following <i>target</i> is an instance of the given
 <i>pattern</i>:</p>

 <code>
 <i>target</i>:      (APP (APP (REV A) (REV B)) (REV C))
 <i>pattern</i>:     (APP (APP   x       y    ) (REV z))
 </code>

 <p>The replacement or <i>substitution</i> used in this match of the pattern to
 the target is:</p>

 <code>
 <i>variable in pattern</i>          <i>replacement term</i>
 x                              (REV A)
 y                              (REV B)
 z                              C
 </code>

 <p>Such substitutions are usually written this way in ACL2:</p>

 @({
  ((x  (REV A))
   (y  (REV B))
   (z  C)).
 })

 <p>Please use your browser's <b>Back Button</b> to return to the page that
 mentioned ``instance.''</p>")

(defxdoc logic-knowledge-taken-for-granted-propositional-calculus
  :parents (introduction-to-the-theorem-prover)
  :short "A brief explanation of propositional calculus"
  :long "<p>It is impossible in this short introduction to teach you
 propositional calculus if you don't already know it!</p>

 <p>A typical use of propositional calculus is to observe that</p>

 @({
  (implies (endp z)
           (implies (true-listp z)
                    (equal (rev (rev z)) z)))
 })

 <p>is equivalent to:</p>

 @({
   (implies (and (endp z)
                 (true-listp z))
            (equal (rev (rev z)) z))
 })

 <p>If this is surprising and you know propositional calculus, then the problem
 might be our notation.  We're exploiting the tautology</p>

 <code>
 <i>(p ---&gt; (q ---&gt; r)) &lt;---&gt; ((p &amp; q) ---&gt; r)</i>
 </code>

 <p>where <i>---&gt;</i> and <i>&lt;---&gt;</i> are meant to be the traditional
 arrows denoting logical implication and logical equivalence.</p>

 <p>If you don't know propositional calculus, we'll say just a few things to
 help ease your journey.</p>

 <p>A <i>propositional formula</i>, in ACL2, is any formula written entirely in
 terms of variable symbols, @('T'), @('NIL'), and the propositional functions
 @('AND'), @('OR'), @('NOT'), @('IMPLIES'), and @('IFF').  The ``tautology''
 above in traditional notation is this propositional formula in ACL2:</p>

 @({
  (IFF (IMPLIES P (IMPLIES Q R))
       (IMPLIES (AND P Q) R)).
 })

 <p>If you have a formula like</p>

 <code>
 (implies <i>hyp</i>
          <i>concl</i>)
 </code>

 <p>then we say that formula is an <i>implication</i>, that <i>hyp</i> is the
 <i>hypothesis</i>, and that <i>concl</i> is the conclusion.  If the hypothesis
 is an @('and') expression, as in</p>

 <code>
 (implies (and <i>hyp1</i>
               <i>hyp2</i>
               ...)
          <i>concl</i>)
 </code>

 <p>then we call <i>hyp1</i> is the <i>first hypothesis</i>, <i>hyp2</i> is the
 <i>second hypothesis</i>, etc.</p>

 <p>If a term is of the form</p>

 <code>
 (and <i>term1</i> <i>term2</i> ...)
 </code>

 <p>we say it is a <i>conjunction</i> and that <i>term1</i> is the <i>first
 conjunct</i>, <i>term2</i> is the <i>second conjunct</i>, etc.  We treat an
 @('or')-term analogously but call it a <i>disjunction</i> and its arguments
 are <i>disjuncts</i>.</p>

 <p>A <i>tautology</i> is any propositional formula that can be proved by
 testing it under all combinations of Boolean assignments to its variables.  We
 give an example of such a <i>truth-table proof</i> below, but hasten to add
 that ACL2 does not generally use truth tables to recognize tautologies.  It
 primarily uses @(see normalization) and BDDs to recognize tautologies, which
 can be seen as a mix of symbolic manipulation and case analysis.</p>

 <p>Many tautologies have names, but ACL2 doesn't refer to them by name because
 it derives them from first principles.  We list a few here because we
 sometimes use the names in our documentation; more importantly, you should
 look at these formulas and convince yourself that they're always true for all
 Boolean values of the variables:</p>

 <code>
 <i>Double Negation</i>:
 (iff (not (not p)) p)

 <i>DeMorgan</i>:
 (iff (not (and p q))
      (or (not p) (not q)))

 <i>Distributivity</i>:
 (iff (and p (or q r))
      (or (and p q)
          (and p r)))

 <i>Promotion</i>:
 (iff (implies p (implies q r))
      (implies (and p q) r))

 <i>Implicative Disjunction</i>:
 (iff (implies p q)
      (or (not p) q))

 <i>Contrapositive</i>:
 (iff (implies p q)
      (implies (not q) (not p)))

 <i>Generalized Contrapositive</i>:
 (iff (implies (and p r) q)
      (implies (and p (not q)) (not r)))

 </code>

 <p>There are, of course, many others, even with these same names!  For
 example, there is a dual version of DeMorgan showing how @('not') distributes
 over @('or'), a dual version of Distributivity for @('or') over @('and'),
 etc.</p>

 <p>Dealing with propositional calculus will not generally be a problem for you
 because it is decidable and ACL2 has procedures that decide propositional
 formulas.  However, propositional calculus can lead to exponential explosion
 and can thus explain why ACL2 has ``gone out to lunch.''  In addition,
 sometimes if you are curious as to <i>why</i> ACL2 is working on a certain
 subgoal the reason can be traced back to propositional calculus.</p>

 <p>The most common example of this is that to prove a formula of the form</p>

 @({
  (implies (implies p1 q1)
           (implies p2 q2))
 })

 <p>propositional calculus will convert it to</p>

 @({
  (and (implies (and p2 (not p1)) q2)
       (implies (and p2 q1) q2))
 })

 <p>Many users are surprised that the first conjunct above does not have
 @('q1') as a hypothesis.  If you ever stare at an ACL2 goal and say to
 yourself ``A hypothesis is missing!'' the chances are that propositional
 calculus is ``to blame.''  In particular, if you are trying to prove that
 @('(implies p1 q1)') implies something, you must deal with the case that
 @('(implies p1 q1)') is true because @('p1') is false.  Think about it.</p>

 <p>Now we illustrate the truth table method for deciding tautologies, even
 though that is not what ACL2 generally uses.  Consider the formula called
 Promotion above:</p>

 @({
  (IFF (IMPLIES P (IMPLIES Q R))
       (IMPLIES (AND P Q) R))
 })

 <p>The formula above is a tautology.  It contains three variables, @('P'),
 @('Q'), and @('R'), and so there are 8 combinations of Boolean assignments to
 them.  If we let</p>

 <code>
 <i>formula1</i>:  (IMPLIES P (IMPLIES Q R))
 <i>formula2</i>:  (IMPLIES (AND P Q) R)
 </code>

 <p>then we wish to test the formula @('(IFF ')<i>formula1
 formula2</i>@(')'):</p>

 <code>
 P   Q   R       <i>formula1</i>   <i>formula2</i>   (IFF <i>formula1</i> <i>formula2</i>)
 ---------
 T   T   T            T         T       T
 T   T   NIL          NIL       NIL     T
 T   NIL T            T         T       T
 T   NIL NIL          T         T       T
 NIL T   T            T         T       T
 NIL T   NIL          T         T       T
 NIL NIL T            T         T       T
 NIL NIL NIL          T         T       T
 </code>

 <p>So we see that the formula always returns @('T') and is thus a
 tautology.</p>

 <p>Recall that in the original example at the top of this page we were trying
 to prove the formula</p>

 @({
  (implies (endp z)
           (implies (true-listp z)
                    (equal (rev (rev z)) z)))
 })

 <p>This formula is an <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INSTANCE)'>instance</see> of</p>

 @({
  (implies p (implies q r)).
 })

 <p>The substitution required by the match is</p>

 <code>
 <i>sigma</i>:
 ((p    (endp z))
  (q    (true-listp z))
  (r    (equal (rev (rev z)) z)))
 </code>

 <p>Since we know the tautology:</p>

 @({
  (iff (implies p (implies q r))
       (implies (and p q) r)).
 })

 <p>is always true no matter what Boolean values @('p'), @('q'), and @('r')
 have, then we know this instance of it (obtained by applying the substitution
 <i>sigma</i> above) is always true:</p>

 <code>
 (iff (implies (endp z)                            <i>formula1'</i>
               (implies (true-listp z)
                        (equal (rev (rev z)) z)))
      (implies (and (endp z)                       <i>formula2'</i>
                    (true-listp z))
               (equal (rev (rev z)) z))).
 </code>

 <p>Thus, if we're trying to prove <i>formula1'</i> it is permitted to try to
 to prove <i>formula2'</i> instead, because they return the same
 truthvalue.</p>

 <p>This sketch of propositional reasoning in ACL2 is a little suspect because
 we didn't address the possibility that the substitution might replace the
 propositional variables by non-propositional terms.  But the tautology was
 verified only on Boolean values for those variables.  This actually works out
 because in ACL2 all propositional testing is done against @('nil') and any
 non-@('nil') value, including @('t'), is as good as another.  However, the
 tautology allows us to replace one formula by the other only in contexts in
 which we just care about propositional truth, i.e., whether the formula is
 @('nil') or not.  When we prove a formula in ACL2 we are really establishing
 that it never returns @('nil'), i.e., no matter what the values of the
 variables, the value of the formula is non-@('nil').</p>

 <p>A very simple example of this is with Double Negation.</p>

 @({
  (iff (not (not p)) p)
 })

 <p>is a tautology.  This means that if we were trying to prove</p>

 @({
  (implies (not (not p)) ...)
 })

 <p>we could transform it to</p>

 @({
  (implies p ...).
 })

 <p>But if we were trying to prove:</p>

 @({
  (equal (not (not p)) p)
 })

 <p>we could not prove it by using Double Negation!  The formula above claims
 that @('(not (not p))') and @('p') have identical values.  They do not!  For
 example, @('(not (not 3))') is @('t'), not @('3').  However, @('(not (not
 3))') and @('t') are propositionally equivalent (i.e., satisfy @('iff'))
 because one is as good as the other in a test.  <i>That</i> is what Double
 Negation says.</p>

 <p>As long as you only use propositional formulas in propositional places this
 aspect of ACL2 should not affect you.</p>

 <p>Now please use your browser's <b>Back Button</b> to return to the example
 proof in @(see logic-knowledge-taken-for-granted).</p>")

(defxdoc logic-knowledge-taken-for-granted-q1-answer
  :parents (introduction-to-the-theorem-prover)
  :short "The inductive step of the @('rev-rev') proof &mdash; Answer to Question 1"
  :long "<p>The correct answer to Question 1 in @(see
 logic-knowledge-taken-for-granted) is <i>Choice (iv)</i>.</p>

 <p>The Induction Step of the inductive proof of</p>

 @({
  (implies (true-listp z)
           (equal (rev (rev z)) z))
 })

 <p>for an induction on the linear list @('z') is:</p>

 <code>
 <i>Induction Step</i>:
 (implies (and (not (endp z))
               (implies (true-listp (cdr z))
                        (equal (rev (rev (cdr z))) (cdr z))))
          (implies (true-listp z)
                   (equal (rev (rev z)) z)))
 </code>

 <p>The second hypothesis above is the the <i>induction hypothesis</i>.  The
 conclusion above is the formula we are trying to prove.  Each induction
 hypothesis is <i>always</i> an <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INSTANCE)'>instance</see> of the formula
 being proved, i.e., it is obtained from the formula being proved by uniformly
 replacing the variables in the formula with terms.  Notice how the induction
 hypothesis above is the same as the induction conclusion, except that all the
 @('z')s have been replaced by @('(cdr z)').</p>

 <p>If you thought the right answer was</p>

 <code>
 <i>Induction Step -- Choice (i)</i>:
 (implies (not (endp z))
          (implies (true-listp z)
                   (equal (rev (rev z)) z)))
 </code>

 <p>then perhaps you didn't understand that we're doing an inductive proof.
 Certainly if you prove the Base Case already discussed and you prove <i>Choice
 (i)</i> above, then you will have proved the goal conjecture, but you would
 have done it by simple case analysis: prove it when @('(endp z)') and prove it
 when @('(not (endp z))').  While logically valid, you probably can't prove
 <i>Choice (i)</i> directly because you have no induction hypothesis to work
 with.</p>

 <p>If you thought the right answer was:</p>

 <code>
 <i>Induction Step -- Choice (ii)</i>:
 (implies (true-listp (cdr z))
          (equal (rev (rev (cdr z))) (cdr z)))
 </code>

 <p>then perhaps you misunderstand the difference between the <i>Induction
 Step</i> and the <i>Induction Hypothesis</i>.  The Induction <i>Step</i> is
 the ``other half'' of the main proof, balancing the Base Case.  The Induction
 <i>Hypothesis</i> is just a hypothesis you get to use during the Induction
 Step.  The question Q1 asked what is the Induction Step.</p>

 <p>If you thought the right answer was:</p>

 <code>
 <i>Induction Step -- Choice (iii)</i>:
 (implies (and (not (endp z))
               (equal (rev (rev (cdr x))) (cdr x))) ; <i>``induction hyp''</i>
          (implies (true-listp z)
                   (equal (rev (rev z)) z)))
 </code>

 <p>then you are making the most common mistake newcomers make to induction.
 You are giving yourself an ``induction hypothesis'' that is not an instance of
 the conjecture you're proving.  This alleged induction hypothesis says that
 @('(rev (rev (cdr x)))') is @('(cdr x)'), whereas the correct induction
 hypothesis says those two terms are equal <i>if</i> @('(true-listp (cdr x))').
 This alleged induction hypothesis is a stronger claim than we're trying to
 prove.  It turns out that by making this mistake you can ``prove'' conjectures
 that are not always true!  Remember: the induction hypothesis is always an
 instance of the conjecture you're proving, not just some piece of it.  Of
 course, ACL2 ``knows'' this and will never make this mistake.  But we remind
 you of it because there may be times when you intuit a different hypothesis
 and don't understand why ACL2 doesn't use it.</p>

 <p>If this doesn't make sense, perhaps you should read about <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INDUCTIVE-PROOF)'>induction</see> again.</p>

 <p>When you understand why <i>Choice (iv)</i> is the correct answer, use your
 browser's <b>Back Button</b> to return to @(see
 logic-knowledge-taken-for-granted) and go to question Q2.</p>")

(defxdoc logic-knowledge-taken-for-granted-q2-answer
  :parents (introduction-to-the-theorem-prover)
  :short "The inductive step of the @('rev-rev') proof &mdash; Answer to Question 2"
  :long "<p>The correct answer to Question 2 in @(see
 logic-knowledge-taken-for-granted) is <i>Subgoal (i)</i> plus any one of the
 other other three.  For your reference, the four choices were:</p>

 <code>
 <i>Subgoal (i)</i>:
 (implies (and (not (endp z))
               (true-listp z))
          (true-listp (cdr z)))

 <i>Subgoal (ii)</i>:
 (implies (and (not (endp z))
               (true-listp z)
               (equal (rev (rev (cdr z))) (cdr z)))
          (equal (rev (rev z)) z))

 <i>Subgoal (iii)</i>:
 (implies (and (not (endp z))
               (equal (rev (rev (cdr z))) (cdr z)))
          (equal (rev (rev z)) z))

 <i>Subgoal (iv)</i>:
 (implies (and (not (endp z))
               (true-listp (cdr z))
               (equal (rev (rev (cdr z))) (cdr z)))
          (equal (rev (rev z)) z))
 </code>

 <p>In particular, it is wrong to think the Induction Step of the proof of</p>

 @({
  (implies (true-listp z)
           (equal (rev (rev z)) z))
 })

 <p>can be established by proving just <i>Subgoal (ii)</i>, <i>Subgoal
 (iii)</i>, <i>Subgoal (iv)</i>, or combinations of those three.  You must also
 prove <i>Subgoal (i)</i> or something like it!</p>

 <p>The Inductive Step for the conjecture above is</p>

 <code>
 <i>Induction Step</i>:
 (implies (and (not (endp z))
               ; <i>Induction Hypothesis</i>:
               (implies (true-listp (cdr z))
                        (equal (rev (rev (cdr z))) (cdr z))))
          ; <i>Induction Conclusion</i>:
          (implies (true-listp z)
                   (equal (rev (rev z)) z)))
 </code>

 <p>Note that the Inductive Hypothesis is an implication:</p>

 @({
  (implies (true-listp (cdr z))
           (equal (rev (rev (cdr z))) (cdr z)))
 })

 <p>This hypothesis can be true two different ways.  The ``normal'' way &mdash;
 the way everybody remembers &mdash; is that @('(true-listp (cdr z))') is true
 and thus @('(equal (rev (rev (cdr z))) (cdr z))') is true.  But the way many
 people forget is that @('(true-listp (cdr z))') is false.  You must prove the
 Induction Step even in this ``forgettable'' case.</p>

 <p>In this case, the Induction Step simplifies to</p>

 <code>
 <i>Induction Step</i>:
 (implies (and (not (endp z))
               (not (true-listp (cdr z))))
          (implies (true-listp z)
                   (equal (rev (rev z)) z)))
 </code>

 <p>By Promotion (see the list of tautologies in our discussion of <see
 topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-PROPOSITIONAL-CALCULUS)'>propositional
 calculus</see>) this is</p>

 <code>
 <i>Induction Step'</i>:
 (implies (and (not (endp z))
               (not (true-listp (cdr z)))
               (true-listp z))
          (equal (rev (rev z)) z))
 </code>

 <p>Using the Contrapositive and rearranging the order of the hypotheses (see
 <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-PROPOSITIONAL-CALCULUS)'>propositional
 calculus</see> again), this is</p>

 <code>
 <i>Induction Step''</i>:
 (implies (and (not (endp z))
               (true-listp z)
               (not (equal (rev (rev z)) z)))
          (true-listp (cdr z)))
 </code>

 <p>Notice that <i>Subgoal (i)</i> implies <i>Induction Step''</i>:</p>

 <code>
 <i>Subgoal (i)</i>:
 (implies (and (not (endp z))
               (truelistp z))
          (truelistp (cdr z)))
 </code>

 <p>Every inductive proof of an implication raises a case like this.  If we
 denote the conjecture @('(implies p q)') as @('p ---> q'), then the Induction
 Step will look like this:</p>

 @({
    ( c  &  (p'  --->  q'))
  --->
    (p ---> q)
 })

 <p>where @('c') is the test that determines the inductive step, (e.g., @('(not
 (endp z))')) and @('p'') and @('q'') are inductive instances of @('p') and
 @('q').  Promotion produces</p>

 @({
    ( c  & p & (p'  --->  q'))
  --->
    q
 })

 <p>It is then very common to prove that @('p') implies @('p''),</p>

 <code>
 <i>(i)</i>:
 (c &amp; p) ---&gt; p'
 </code>

 <p>and then prove that @('q'') implies @('q'),</p>

 <code>
 <i>(ii)</i>:
 (c &amp; p &amp; q') ---&gt; q
 </code>

 <p>These correspond exactly to our choices <i>Subgoal (i)</i> and <i>Subgoal
 (ii)</i>.</p>

 <p>It is sometimes helpful to remember this diagram:</p>

 @({
  (c  &  (p'  --->  q')
          ^         |
          |         |
          |         v
   -->   (p   --->  q )
 })

 <p>When you understand why <i>Subgoals (i)</i> and <i>(ii)</i> are sufficient,
 use your browser's <b>Back Button</b> to return to @(see
 logic-knowledge-taken-for-granted) and go to question Q3.</p>")

(defxdoc logic-knowledge-taken-for-granted-q3-answer
  :parents (introduction-to-the-theorem-prover)
  :short "The inductive step of the @('rev-rev') proof &mdash; Answer to Question 2"
  :long "<p>The correct answer to Question 3 in @(see
 logic-knowledge-taken-for-granted) is that you need to prove</p>

 <code>
 <i>Subgoal to Relieve Hyp 1</i>:
 (implies (and (q (f a))
               (r a))
          (p (f a)))
 </code>

 <p>in order to use</p>

 <code>
 <i>Theorem</i>:
 (implies (p (f x))
          (equal (g (h x))
                 x))
 </code>

 <p>to rewrite the target @('(g (h a))') to @('a') in</p>

 <code>
 <i>Goal Conjecture</i>:
 (implies (and (q (f a))
               (r a))
          (s (g (h a))))
 </code>

 <p>If you don't see why, re-read the discussion of <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-REWRITING)'>rewriting</see> again.
 Forgetting about the need to relieve hypotheses is a common mistake in
 informal proofs.  ACL2 won't forget to relieve them.  But if you forget about
 the need to do it, you may be confused when ACL2 doesn't see the ``proof'' you
 see!</p>

 <p>Now use your browser's <b>Back Button</b> to return to the end of quiz in
 @(see logic-knowledge-taken-for-granted).</p>")

(defxdoc logic-knowledge-taken-for-granted-rewriting
  :parents (introduction-to-the-theorem-prover)
  :short "A brief explanation of rewriting from the logical perspective"
  :long "<p>First we give two examples of rewriting.  Then we give a rather
 detailed description.  We recommend you read the description, even if you
 understand the two examples, just so that you learn our terminology.</p>

 <p><b>Example 1</b>: Suppose your goal conjecture is:</p>

 <code>
 <i>Goal Conjecture</i>:
 (implies (and (endp z)
               (true-listp z))
          (equal (rev (rev z)) z))
 </code>

 <p>Then you can use the following theorem (actually the definitional axiom
 introduced by the @('defun') of @('endp')):</p>

 <code>
 <i>Definitional Axiom</i>: endp
 (equal (endp x)
        (not (consp x))).
 </code>

 <p>to <i>rewrite</i> the <i>Goal Conjecture</i> to</p>

 <code>
 <i>Rewritten Goal Conjecture</i>:
 (implies (and (not (consp z))
               (true-listp z))
          (equal (rev (rev z)) z))
 </code>

 <p>Note that in this example, rewriting replaced the call of @('endp') by its
 body after instantiating its body with the actuals from the call.  This is
 sometimes just called <i>expanding</i> the definition of @('endp').  (The
 notions of <i>formal</i>, <i>body</i>, <i>call</i>, and <i>actuals</i> are
 discussed in @(see programming-knowledge-taken-for-granted).)</p>

 <p>Expanding a definition is an example of <i>unconditional</i> rewriting.
 All definitions in ACL2 are just bare equalities relating a call of the
 function on its formals to its body.  Any time you use an equality theorem,
 whether a definitional equality or something more general like</p>

 @({
  (equal (append (append x y) z)
         (append x (append y z)))
 })

 <p>to replace an instance of one side by the corresponding instance of the
 other in a goal conjecture, we call that <i>unconditional</i> rewriting with
 the equality.</p>

 <p><b>Example 2</b>: Suppose your goal conjecture is:</p>

 <code>
 <i>Goal Conjecture</i>:
 (implies (and (subsetp a b)
               (true-listp b)
               (member e a))
          (&lt; (len (rm e b)) (len b))).
 </code>

 <p>This conjecture may be read ``if @('a') is a subset of the @('true-listp')
 @('b') and @('e') is a member of @('a'), then the result of removing @('e')
 from @('b') has a shorter length than @('b').''</p>

 <p>You can use the following theorem:</p>

 <code>
 <i>Theorem</i>:
 (implies (member u v)
          (equal (len (rm u v))
                 (- (len v) 1)))
 </code>

 <p>to <i>rewrite</i> the <i>Goal Conjecture</i> to</p>

 <code>
 <i>Rewritten Goal Conjecture</i>:
 (implies (and (subsetp a b)
               (true-listp b)
               (member e a))
          (&lt; (- (len b) 1) (len b))).
 </code>

 <p>To do this you must know that the following subgoal is provable:</p>

 <code>
 <i>Subgoal to Relieve Hyp 1</i>:
 (implies (and (subsetp a b)
               (true-listp b)
               (member e a))
          (member e b)).
 </code>

 <p>This is an example of <i>conditional</i> rewriting.  In order to use the
 <i>Theorem</i> we had to establish that its hypotheses are satisfied.  That is
 called <i>relieving the hypotheses</i> and was done by proving the <i>Subgoal
 to Relieve Hyp 1</i>.  Conditional rewriting is the most commonly used proof
 technique in ACL2.</p>

 <p>Unconditional rewriting is just a special case, where there are no
 hypotheses to relieve.</p>

 <p>Expanding a definition is just another special case, where there are no
 hypotheses to relieve and the pattern is easy to match because it is a call of
 a function on distinct variables.</p>

 <p>This page discusses <i>rewriting</i> from the logical perspective.  It is
 important that you are familiar with the notions of a <i>pattern</i> term
 being an <see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INSTANCE)'>instance</see> of a <i>target</i>
 term.  We often say the pattern <i>matches</i> the target.  These notions
 involve a corresponding <i>substitution</i> of terms for variables.  All these
 notions are discussed in the link for ``<see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INSTANCE)'>instance</see>'' above and we
 recommend you read it before continuing.  Then use your browser's <b>Back
 Button</b> to come back here.</p>

 <p>You should also be aware of the terms introduced in our discussion of <see
 topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-PROPOSITIONAL-CALCULUS)'>propositional
 calculus</see>.</p>

 <p><i>Rewriting</i> is a fundamental rule of inference in our system.  The
 rule allows you to use a theorem, i.e., an axiom, lemma, or definition, to
 replace one term by another in the goal conjecture you're trying to prove.</p>

 <p>Suppose you have a theorem that is of the form (or can be put into the
 form):</p>

 <code>
 <i>Theorem</i>:
 (implies (and <i>hyp1</i>
               ...
               <i>hypk</i>)
          (equal <i>pattern</i>
                 <i>replacement</i>))
 </code>

 <p>From the logical perspective we don't care how the theorem was actually
 written when it was proved.  It might have no hypotheses (in which case the
 <i>hypi</i> could just be @('t')), or it could have been written in a
 different but equivalent propositional style, @('(or (not') <i>hyp1</i>@(')
 ...)'), or the equality could have been written the other way around,
 @('(equal ')<i>replacement</i> <i>pattern</i>@(')').  Such syntactic details
 don't matter.  Just take a theorem and use propositional calculus to rearrange
 it equivalently into this form for the purposes of this one rewrite step.</p>

 <p>Suppose <i>pattern</i> is an instance of some target term, <i>target</i>
 that occurs in your goal conjecture.  Let the corresponding substitution be
 <i>sigma</i>.  If <i>sigma</i> does not contain a binding for every variable
 that occurs in <i>Theorem</i>, then extend <i>sigma</i> to <i>sigma'</i> by
 adding one binding for each such variable.  (This is necessary only if
 <i>pattern</i> does not contain every variable in <i>Theorem</i>.)</p>

 <p>Let <i>replacement'</i> be the result of instantiating <i>replacement</i>
 with <i>sigma'</i>.  Let <i>hypi'</i> be the result of instantiating
 <i>hypi</i> with <i>sigma'</i>.</p>

 <p>Then the <b>Rewrite Rule of Inference</b> tells us it is permitted to
 replace that occurrence of <i>target</i> in the goal by <i>replacement'</i>
 &mdash; <b>if you can prove</b> each <i>hypi'</i> in this context.  We make
 this last condition clear in a moment.</p>

 <p>The justification for this is that <i>Theorem</i> is true for all values of
 the variables.  Hence, it is true for the values specified by <i>sigma'</i>.
 If the <i>hypi'</i> are true, then the target is really equal to
 <i>replacement'</i>.  But it is always permitted to replace something by
 something it's equal to.</p>

 <p>Rewriting thus involves several steps:</p>

 <p>(1) Finding a <i>target</i> and a <i>theorem</i> to use to rewrite it to
 some more desirable <i>replacement</i>.</p>

 <p>(2) Instantiating <i>pattern</i> in the (rearranged) theorem to match
 <i>target</i>.</p>

 <p>(3) Extending <i>sigma</i> to <i>sigma'</i> to bind all the variables in
 <i>Theorem</i>.</p>

 <p>(4) Establishing that the <i>sigma'</i> instances of each of the
 <i>hypi</i> hold.  This is called <i>relieving the hypotheses</i> of the
 theorem and is discussed in greater detail below.</p>

 <p>(5) Replacing the occurrence of <i>target</i> in the goal conjecture by the
 <i>sigma'</i> instance of <i>replacement</i>, provided all the hypotheses are
 relieved.</p>

 <p>Step (4) above, <i>relieving the hypotheses</i>, requires first identifying
 the ``context'' of the target in the goal conjecture.  To do this, use
 propositional calculus to rearrange the goal conjecture so the occurrence of
 <i>target</i> is in the conclusion and let <i>context</i> be the
 hypothesis.</p>

 <code>
 <i>Rearranged Conjecture</i>:
 (implies <i>context</i>
          (... <i>target</i> ...))
 </code>

 <p>To relieve the hypotheses you must then prove each of the following
 subgoals:</p>

 <code>
 <i>Subgoal to Relieve Hyp i</i>:
 (implies <i>context</i> <i>hypi'</i>).
 </code>

 <p>It is important to note that this description of rewriting with
 <i>Theorem</i> describes the process from a strictly logical perspective.  The
 syntax of the theorem and the goal don't matter.  You're free to use
 propositional calculus to rearrange them to put them into the appropriate
 forms to fit the descriptions given.  Clearly, if you have a candidate Theorem
 in the ``wrong'' form and but it can be rearranged with propositional calculus
 into the ``right'' form, then that rearranged theorem is also a <i>Theorem</i>
 and can be used as described.  But in the actual implementation of ACL2, the
 syntactic form of a proved <i>Theorem</i> affects how it is used by rewriting.
 If a proved theorem takes the form of an implication concluding with an
 equality, ACL2 treats the left-hand side of the equality as <i>pattern</i> and
 the right-hand side as <i>replacement</i>, unless you tell it otherwise.
 We'll discuss this later.</p>

 <p>Furthermore, being from the logical perspective this discussion of
 rewriting does not address (a) how you extend <i>sigma</i> to <i>sigma'</i>
 &mdash; any extension will do provided it allows you to relieve the
 hypotheses.  The ACL2 theorem prover uses certain heuristics which we'll
 discuss later, including methods by which you can guide the system in the
 selection.</p>

 <p>Crucially, it does not discuss whether it is a <i>good idea</i> to do a
 particular rewrite!  For example, the definitional equality:</p>

 @({
  (equal (len x)
         (if (endp x)
             0
             (+ 1 (len (cdr x)))))
 })

 <p>may be used repeatedly, endlessly, to replace @('(len a)') by an ever
 growing sequence of terms:</p>

 @({
  (len a)
  =
  (if (endp a)
      0
      (+ 1 (len (cdr a))))
  =
  (if (endp a)
      0
      (+ 1 (if (endp (cdr a))
               0
               (+ 1 (len (cdr (cdr a)))))))
  = ...
 })

 <p>The ACL2 implementation of rewriting uses certain heuristics and the you can
 guide the system in its choices.  We'll discuss this later.</p>

 <p>Now use your browser's <b>Back Button</b> to return to the example proof in
 @(see logic-knowledge-taken-for-granted).</p>")

(defxdoc logic-knowledge-taken-for-granted-rewriting-repeatedly
  :parents (introduction-to-the-theorem-prover)
  :short "Further information on expanding definitions via rewriting"
  :long "<p>We assume you've read about ``<see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INSTANCE)'>instances</see>'' and picked up
 our basic terminology including the ideas of <i>matching</i> a <i>pattern</i>
 term to a <i>target</i> term, obtaining a <i>substitution</i> and how to
 <i>instantiate</i> a term with a substitution.  We use these notions below
 without further citation.</p>

 <p>In addition, we assume you've read about ``<see topic='@(url
 LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-REWRITING)'>rewriting</see>'' where we
 introduced the idea of treating a theorem (axiom, definition, or lemma) as a
 <i>conditional rewrite</i> rule and replaced one term by an equivalent one
 provided we can <i>relieve the hypotheses</i>.</p>

 <p>Suppose you're trying to prove <i>formula1</i> and you transform it to
 <i>formula2</i> by rewriting.  What happened?</p>

 <code>
 <i>formula1</i>:
 (implies (and (not (consp z))
               (true-listp z))
          (equal (rev (rev z)) z))

 <i>formula2</i>:
 (implies (and (not (consp z))
               (equal z nil))
          (equal (rev (rev z)) z))
 </code>

 <p>Evidently we replaced @('(true-listp z)') by @('(equal z nil)').  But how
 did that happen?  What really happened was the sequential application of
 several unconditional rewrites and the use of replacement of equals by
 equals.</p>

 <p>The definition of @('true-listp') is:</p>

 @({
  (defun true-listp (x)
    (if (consp x)
        (true-listp (cdr x))
        (equal x nil))).
 })

 <p>By rewriting once with the definition of @('true-listp'), we transform
 <i>formula1</i> to:</p>

 <code>
 <i>formula1'</i>:
 (implies (and (not (consp z))
               (if (consp z)
                   (true-listp (cdr z))
                   (equal z nil)))
          (equal (rev (rev z)) z)).
 </code>

 <p>Note how the call of @('true-listp') has been replaced by the entire body
 of @('true-listp').</p>

 <p>Next, note that the first hypothesis above is that @('(consp z)') is false.
 That is, @('(not (consp z))') is the same as @('(equal (consp z) nil)').
 Thus, replacement of equals by equals means we can transform <i>formula1'</i>
 to</p>

 <code>
 <i>formula1''</i>:
 (implies (and (not (consp z))
               (if nil
                   (true-listp (cdr z))
                   (equal z nil)))
          (equal (rev (rev z)) z)).
 </code>

 <p>(We will explore replacement of equals by equals later.)</p>

 <p>Furthermore, we know the basic axiom about @('if'):</p>

 <code>
 <i>Axiom</i> if-nil:
 (if nil x y) = y.
 </code>

 <p>Rewriting with this particular axiom, using @('(if nil x y)') as the
 pattern and @('y') as the replacement, will transform <i>formula1''</i> to</p>

 <code>
 <i>formula2</i>:
 (implies (and (not (consp z))
               (equal z nil))
          (equal (rev (rev z)) z)).
 </code>

 <p>Often when we say we derived one formula from another by ``expansion'' and
 or by ``rewriting'' we take many rewrite steps, as here.  We typically use
 hypotheses of the formula without noting ``replacement of equals by equals''
 as when we replaced @('(consp z)') by @('nil'), and we typically omit to
 mention the use of basic axioms like @('if-nil') above.</p>

 <p>Now use your browser's <b>Back Button</b> to return to the example proof in
 @(see logic-knowledge-taken-for-granted).</p>")

(defxdoc logic-term-list-listp
  :parents (termp acl2-built-ins)
  :short "Recognizer for lists of lists of @(see term)s that call only
 @(':')@(tsee logic)-mode function symbols"
  :long "<p>This predicate strengthens @('(term-list-listp x wrld)'), as it
 also requires @('(logic-fns-list-listp x wrld)'), i.e., that every function
 symbol called in @('x') is in @(':')@(tsee logic) mode in the @(see world),
 @('wrld').</p>

 @(def logic-term-list-listp)")

(defxdoc logic-term-listp
  :parents (termp acl2-built-ins)
  :short "Recognizer for lists of @(see term)s that call only @(':')@(tsee
 logic)-mode function symbols"
  :long "<p>This predicate strengthens @('(term-listp x wrld)'), as it also
 requires @('(logic-fns-listp x wrld)'), i.e., that every function symbol
 called in @('x') is in @(':')@(tsee logic) mode in the @(see world),
 @('wrld').</p>

 @(def logic-term-listp)")

(defxdoc logic-termp
  :parents (termp acl2-built-ins)
  :short "Recognizer for @(see term)s that call only @(':')@(tsee logic)-mode
 function symbols"
  :long "<p>This predicate strengthens @('(termp x wrld)'), as it also requires
 @('(logic-fnsp x wrld)'), i.e., that every function symbol called in @('x') is
 in @(':')@(tsee logic) mode in the @(see world), @('wrld').</p>

 @(def logic-termp)")

(defxdoc logical-name
  :parents (events world)
  :short "A name created by a logical event"
  :long "@({
  Examples:
  assoc
  caddr
  +
  \"ACL2-USER\"
  \"arith\"
  \"project/task-1/arith.lisp\"
  :here
 })

 <p>A logical name is either a name introduced by some event, such as @(tsee
 defun), @(tsee defthm), or @(tsee include-book), or else is the keyword
 @(':here'), which refers to the most recent such event.  See @(see events).
 Every logical name is either a symbol or a string.  For the syntactic rules on
 names, see @(see name).  The symbols name functions, macros, constants,
 axioms, theorems, labels, and @(see theories).  The strings name packages or
 @(see books).  We permit the keyword symbol @(':here') to be used as a logical
 name denoting the most recently completed event.</p>

 <p>The logical name introduced by an @(see include-book) is the full book name
 string for the book (see @(see full-book-name)).  Thus, under the appropriate
 setting for the current book directory (see @(see cbd)) the event
 @('(include-book \"arith\")') may introduce the logical name</p>

 @({
  \"/usr/home/smith/project/task-1/arith.lisp\" .
 })

 <p>Under a different @(tsee cbd) setting, it may introduce a different logical
 name, perhaps</p>

 @({
  \"/local/src/acl2/library/arith.lisp\" .
 })

 <p>It is possible that identical @(tsee include-book) events forms in a
 session introduce two different logical names because of the current book
 directory.</p>

 <p>A logical name that is a string is either a package name or a book name.
 If it is not a package name, we support various conventions to interpret it as
 a book name.  If it does not end with the string @('\".lisp\"') we extend it
 appropriately.  Then, we search for any book name that has the given logical
 name as a terminal substring.  Suppose @('(include-book \"arith\")') is the
 only @(see include-book) so far and that
 @('\"/usr/home/smith/project/task-1/arith.lisp\"') is the source file it
 processed.  Then @('\"arith\"'), @('\"arith.lisp\"') and
 @('\"task-1/arith.lisp\"') are all logical names identifying that @(tsee
 include-book) event (unless they are package names).  Now suppose a second
 @('(include-book \"arith\")') is executed and processes
 @('\"/local/src/acl2/library/arith.lisp\"').  Then @('\"arith\"') is no longer
 a logical name, because it is ambiguous.  However, @('\"task-1/arith\"') is a
 logical name for the first @(tsee include-book) and @('\"library/arith\"') is
 a logical name for the second.  Indeed, the first can be named by
 @('\"1/arith\"') and the second by @('\"y/arith\"').</p>

 <p>Logical names are used primarily in the theory manipulation functions,
 e.g., @(tsee universal-theory) and @(tsee current-theory) with which you may
 obtain some standard @(see theories) as of some point in the historical past.
 The reference points are the introductions of logical names, i.e., the past is
 determined by the @(see events) it contains.  One might ask, ``Why not discuss
 the past with the much more flexible language of @(see command) descriptors?''
 (See @(see command-descriptor).)  The reason is that inside of such @(see
 events) as @(tsee encapsulate) or macro @(see command)s that expand to @(tsee
 progn)s of @(see events), @(see command) descriptors provide too coarse a
 grain.</p>

 <p>When logical names are used as referents in theory expressions used in
 @(see books), one must consider the possibility that the defining event within
 the book in question becomes redundant by the definition of the name prior to
 the assumption of the book.  See @(see redundant-events).</p>")

(defxdoc logior
  :parents (numbers acl2-built-ins)
  :short "Bitwise logical inclusive or of zero or more integers"
  :long "<p>When integers are viewed in their two's complement representation,
 @('logior') returns their bitwise logical inclusive or.  In ACL2 @('logior')
 is a macro that expands into calls of the binary function @('binary-logior'),
 except that @('(logior)') expands to @('0') and @('(logior x)') expands to
 @('x').</p>

 <p>The @(see guard) for @('binary-logior') requires its arguments to be
 integers.  @('Logior') is defined in Common Lisp.  See any Common Lisp
 documentation for more information.</p>

 @(def logior)
 @(def binary-logior)")

(defxdoc lognand
  :parents (numbers acl2-built-ins)
  :short "Bitwise logical `nand' of two integers"
  :long "<p>When integers are viewed in their two's complement representation,
 @('lognand') returns their bitwise logical `nand'.</p>

 <p>The @(see guard) for @('lognand') requires its arguments to be integers.
 @('Lognand') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>

 @(def lognand)")

(defxdoc lognor
  :parents (numbers acl2-built-ins)
  :short "Bitwise logical `nor' of two integers"
  :long "<p>When integers are viewed in their two's complement representation,
 @('lognor') returns the bitwise logical `nor' of the first with the
 second.</p>

 <p>The @(see guard) for @('lognor') requires its arguments to be integers.
 @('Lognor') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>

 @(def lognor)")

(defxdoc lognot
  :parents (numbers acl2-built-ins)
  :short "Bitwise not of a two's complement number"
  :long "<p>@('(lognot i)') is the two's complement bitwise @('`not'') of the
 integer @('i').</p>

 <p>@('Lognot') is actually defined by coercing its argument to an integer (see
 @(see ifix)), negating the result, and then subtracting @('1').</p>

 <p>The @(see guard) for @('lognot') requires its argument to be an
 integer.</p>

 <p>@('Lognot') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def lognot)")

(defxdoc logorc1
  :parents (numbers acl2-built-ins)
  :short "Bitwise logical inclusive or of two ints, complementing the first"
  :long "<p>When integers are viewed in their two's complement representation,
 @('logorc1') returns the bitwise logical inclusive or of the second with the
 bitwise logical `not' of the first.</p>

 <p>The @(see guard) for @('logorc1') requires its arguments to be integers.
 @('Logorc1') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>

 @(def logorc1)")

(defxdoc logorc2
  :parents (numbers acl2-built-ins)
  :short "Bitwise logical inclusive or of two ints, complementing the second"
  :long "<p>When integers are viewed in their two's complement representation,
 @('logorc2') returns the bitwise logical inclusive or of the first with the
 bitwise logical `not' of the second.</p>

 <p>The @(see guard) for @('logorc2') requires its arguments to be integers.
 @('Logorc2') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>

 @(def logorc2)")

(defxdoc logtest
  :parents (numbers acl2-built-ins)
  :short "Test if two integers share a `1' bit"
  :long "<p>When integers @('x') and @('y') are viewed in their two's
 complement representation, @('(logtest x y)') is true if and only if there is
 some position for which both @('x') and @('y') have a `1' bit in that
 position.</p>

 <p>The @(see guard) for @('logtest') requires its arguments to be integers.
 @('Logtest') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>

 @(def logtest)")

(defxdoc logxor
  :parents (numbers acl2-built-ins)
  :short "Bitwise logical exclusive or of zero or more integers"
  :long "<p>When integers are viewed in their two's complement representation,
 @('logxor') returns their bitwise logical exclusive or.  In ACL2 @('logxor')
 is a macro that expands into calls of the binary function @('binary-logxor'),
 except that @('(logxor)') expands to @('0') and @('(logxor x)') expands to
 @('x').</p>

 <p>The @(see guard) for @('binary-logxor') requires its arguments to be
 integers.  @('Logxor') is defined in Common Lisp.  See any Common Lisp
 documentation for more information.</p>

 @(def logxor)
 @(def binary-logxor)")

(defxdoc loop-stopper
  :parents (rewrite)
  :short "Limit application of permutative rewrite rules"
  :long "<p>See @(see rule-classes) for a discussion of the syntax of the
 @(':loop-stopper') field of @(':')@(tsee rewrite) rule-classes.  Here we
 describe how that field is used, and also how that field is created when the
 user does not explicitly supply it.</p>

 <p>For example, the built-in @(':')@(tsee rewrite) rule
 @('commutativity-of-+'),</p>

 @({
  (implies (and (acl2-numberp x)
                (acl2-numberp y))
           (equal (+ x y) (+ y x))),
 })

 <p>creates a rewrite rule with a loop-stopper of @('((x y binary-+))').  This
 means, very roughly, that the term corresponding to @('y') must be ``smaller''
 than the term corresponding to @('x') in order for this rule to apply.
 However, the presence of @(tsee binary-+) in the list means that certain
 functions that are ``invisible'' with respect to @(tsee binary-+) (by default,
 @(tsee unary--) is the only such function) are more or less ignored when
 making this ``smaller'' test.  We are much more precise below.</p>

 <p>Our explanation of loop-stopping is in four parts.  First we discuss ACL2's
 notion of ``term order.''  Next, we bring in the notion of ``invisibility'',
 and use it together with term order to define orderings on terms that are used
 in the loop-stopping algorithm.  Third, we describe that algorithm.  These
 topics all assume that we have in hand the @(':loop-stopper') field of a given
 rewrite rule; the fourth and final topic describes how that field is
 calculated when it is not supplied by the user.</p>

 <p>ACL2 must sometimes decide which of two terms is syntactically simpler.  It
 uses a total ordering on terms, called the ``term order.''  Under this
 ordering constants such as @(''(a b c)') are simpler than terms containing
 variables such as @('x') and @('(+ 1 x)').  Terms containing variables are
 ordered according to how many occurrences of variables there are.  Thus @('x')
 and @('(+ 1 x)') are both simpler than @('(cons x x)') and @('(+ x y)').  If
 variable counts do not decide the order, then the number of function
 applications are tried.  Thus @('(cons x x)') is simpler than @('(+ x (+ 1
 y))') because the latter has one more function application.  Finally, if the
 number of function applications do not decide the order, a lexicographic
 ordering on Lisp objects is used.  See @(see term-order) for details.</p>

 <p>When the loop-stopping algorithm is controlling the use of permutative
 @(':')@(tsee rewrite) rules it allows @('term1') to be moved leftward over
 @('term2') only if @('term1') is smaller, in a suitable sense.  Note: The
 sense used in loop-stopping is <b>not</b> the above explained term order but a
 more complicated ordering described below.  The use of a total ordering stops
 rules like commutativity from looping indefinitely because it allows @('(+ b
 a)') to be permuted to @('(+ a b)') but not vice versa, assuming @('a') is
 smaller than @('b') in the ordering.  Given a set of permutative rules that
 allows arbitrary permutations of the tips of a tree of function calls, this
 will normalize the tree so that the smallest argument is leftmost and the
 arguments ascend in the order toward the right.  Thus, for example, if the
 same argument appears twice in the tree, as @('x') does in the @(tsee
 binary-+) tree denoted by the term @('(+ a x b x)'), then when the allowed
 permutations are done, all occurrences of the duplicated argument in the tree
 will be adjacent, e.g., the tree above will be normalized to @('(+ a b x
 x)').</p>

 <p>Suppose the loop-stopping algorithm used term order, as noted above, and
 consider the @(tsee binary-+) tree denoted by @('(+ x y (- x))').  The
 arguments here are in ascending term order already.  Thus, no permutative
 rules are applied.  But because we are inside a @('+-expression') it is very
 convenient if @('x') and @('(- x)') could be given virtually the same position
 in the ordering so that @('y') is not allowed to separate them.  This would
 allow such rules as @('(+ i (- i) j) = j') to be applied.  In support of this,
 the ordering used in the control of permutative rules allows certain unary
 functions, e.g., the unary minus function above, to be ``invisible'' with
 respect to certain ``surrounding'' functions, e.g., @(tsee +) function
 above.</p>

 <p>Briefly, a unary function symbol @('fn1') is invisible with respect to a
 function symbol @('fn2') if @('fn2') belongs to the value of @('fn1') in
 @(tsee invisible-fns-table); also see @(see set-invisible-fns-table), which
 explains its format and how it can be set by the user.  Roughly speaking,
 ``invisible'' function symbols are ignored for the purposes of the term-order
 test.</p>

 <p>Consider the example above, @('(+ x y (- x))').  The translated version of
 this term is @('(binary-+ x (binary-+ y (unary-- x)))').  The initial @(tsee
 invisible-fns-table) makes @(tsee unary--) invisible with respect to @(tsee
 binary-+).  The commutativity rule for @(tsee binary-+) will attempt to swap
 @('y') and @('(unary-- x)') and the loop-stopping algorithm is called to
 approve or disapprove.  If term order is used, the swap will be disapproved.
 But term order is not used.  While the loop-stopping algorithm is permuting
 arguments inside a @(tsee binary-+) expression, @(tsee unary--) is invisible.
 Thus, instead of comparing @('y') with @('(unary-- x)'), the loop-stopping
 algorithm compares @('y') with @('x'), approving the swap because @('x') comes
 before @('y').</p>

 <p>Here is a more precise specification of the total order used for
 loop-stopping with respect to a list, @('fns'), of functions that are to be
 considered invisible.  Let @('x') and @('y') be distinct terms; we specify
 when ``@('x') is smaller than @('y') with respect to @('fns').''  If @('x') is
 the application of a unary function symbol that belongs to @('fns'), replace
 @('x') by its argument.  Repeat this process until the result is not the
 application of such a function; let us call the result @('x-guts').  Similarly
 obtain @('y-guts') from @('y').  Now if @('x-guts') is the same term as
 @('y-guts'), then @('x') is smaller than @('y') in this order iff @('x') is
 smaller than @('y') in the standard term order.  On the other hand, if
 @('x-guts') is different than @('y-guts'), then @('x') is smaller than @('y')
 in this order iff @('x-guts') is smaller than @('y-guts') in the standard term
 order.</p>

 <p>Now we may describe the loop-stopping algorithm.  Consider a rewrite rule
 with conclusion @('(equiv lhs rhs)') that applies to a term @('x') in a given
 context; see @(see rewrite).  Suppose that this rewrite rule has a
 loop-stopper field (technically, the @(':heuristic-info') field) of @('((x1 y1
 . fns-1) ... (xn yn . fns-n))').  (Note that this field can be observed by
 using the command @(':')@(tsee pr) with the name of the rule; see @(see pr).)
 We describe when rewriting is permitted.  The simplest case is when the
 loop-stopper list is @('nil') (i.e., @('n') is @('0')); in that case,
 rewriting is permitted.  Otherwise, for each @('i') from 1 to @('n') let
 @('xi'') be the actual term corresponding to the variable @('xi') when
 @('lhs') is matched against the term to be rewritten, and similarly correspond
 @('yi'') with @('y').  If @('xi'') and @('yi'') are the same term for all
 @('i'), then rewriting is not permitted.  Otherwise, let @('k') be the least
 @('i') such that @('xi'') and @('yi'') are distinct.  Let @('fns') be the list
 of all functions that are invisible with respect to every function in
 @('fns-k'), if @('fns-k') is non-empty; otherwise, let @('fns') be @('nil').
 Then rewriting is permitted if and only if @('yi'') is smaller than @('xi'')
 with respect to @('fns'), in the sense defined in the preceding paragraph.</p>

 <p>It remains only to describe how the loop-stopper field is calculated for a
 rewrite rule when this field is not supplied by the user.  (On the other hand,
 to see how the user may specify the @(':loop-stopper'), see @(see
 rule-classes).)  Suppose the conclusion of the rule is of the form @('(equiv
 lhs rhs)').  First of all, if @('rhs') is not an instance of the left hand
 side by a substitution whose range is a list of distinct variables, then the
 loop-stopper field is @('nil').  Otherwise, consider all pairs @('(u . v)')
 from this substitution with the property that the first occurrence of @('v')
 appears in front of the first occurrence of @('u') in the print representation
 of @('rhs').  For each such @('u') and @('v'), form a list @('fns') of all
 functions @('fn') in @('lhs') with the property that @('u') or @('v') (or
 both) appears as a top-level argument of a subterm of @('lhs') with function
 symbol @('fn').  Then the loop-stopper for this rewrite rule is a list of all
 lists @('(u v . fns)').</p>")

(defxdoc lower-case-p
  :parents (characters acl2-built-ins)
  :short "Recognizer for lower case characters"
  :long "<p>@('(Lower-case-p x)') is true if and only if @('x') is a lower case
 character, i.e., a member of the list @('#\\A'), @('#\\B'), ...,
 @('#\\Z').</p>

 <p>The @(see guard) for @('lower-case-p') requires its argument to be a
 standard character (see @(see standard-char-p)).</p>

 <p>@('Lower-case-p') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def lower-case-p)")

(defxdoc lp
  :parents (ld)
  :short "The Common Lisp entry to ACL2"
  :long "<p>To enter the ACL2 @(see command) loop from Common Lisp, call the
 Common Lisp program @('lp') (which stands for ``loop,'' as in
 ``read-eval-print loop'' or ``@(see command) loop.'')  The ACL2 @(see command)
 loop is actually coded in ACL2 as the function @(tsee ld) (which stands for
 ``load'').  The @(see command) loop is just what you get by loading from the
 standard object input channel, @(tsee *standard-oi*).  Calling @(tsee ld)
 directly from Common Lisp is possible but fragile because hard lisp errors or
 aborts throw you out of @(tsee ld) and back to the top-level of Common Lisp.
 @('Lp') calls @(tsee ld) in such a way as to prevent this and is thus the
 standard way to get into the ACL2 @(see command) loop.  Also see @(see
 acl2-customization) for information on the loading of an initialization
 file.</p>

 <p>All of the visible functionality of @('lp') is in fact provided by @(tsee
 ld), which is written in ACL2 itself.  Therefore, you should see @(see ld) for
 detailed @(see documentation) of the ACL2 @(see command) loop.  We sketch it
 below, for novice users.</p>

 <p>Every expression typed to the ACL2 top-level must be an ACL2
 expression.</p>

 <p>Any ACL2 expression may be submitted for evaluation.  Well-formedness is
 checked.  Some well-formed expressions cannot be evaluated because they
 involve (at some level) undefined constrained functions (see @(see
 encapsulate)).  In addition, ACL2 does not allow ``global variables'' in
 expressions to be evaluated.  Thus, @('(car '(a b c))') is legal and evaluates
 to @('A'), but @('(car x)') is not, because there is no ``global context'' or
 binding environment that gives meaning to the variable symbol @('x').</p>

 <p>There is an exception to the global variable rule outlined above:
 single-threaded objects (see @(see stobj)) may be used as global variables in
 top-level expressions.  The most commonly used such object is the ACL2
 ``current state,'' which is the value of the variable symbol @(tsee state).
 This variable may occur in the top-level form to be evaluated, but must be
 passed only to ACL2 functions ``expecting'' @('state') as described in the
 documentation for @(tsee state) and for @(tsee stobj)s in general.  If the
 form returns a new @(see state) object as one of its values, then that is
 considered the new ``current'' @(see state) for the evaluation of the
 subsequent form.  See @(see state).</p>

 <p>ACL2 provides some support for the functionality usually provided by global
 variables in a read-eval-print loop, namely the saving of the result of a
 computation for subsequent re-use in another expression.  See @(see assign)
 and see @(see @).</p>

 <p>If the form read is a single keyword, e.g., @(':')@(tsee pe) or
 @(':')@(tsee ubt), then special procedures are followed.  See @(see
 keyword-commands).</p>

 <p>The @(see command) loop keeps track of the @(see command)s you have typed
 and allows you to review them, display them, and roll the logical @(see state)
 back to that created by any @(see command).  See @(see history).</p>

 <p>ACL2 makes the convention that if a top-level form returns three values,
 the last of which is an ACL2 @(see state), then the first is treated as a flag
 that means ``an error occurred,'' the second is the value to be printed if no
 error occurred, and the third is (of course) the new @(see state).  When ``an
 error occurs'' no value is printed.  Thus, if you execute a top-level form
 that happens to return three such values, only the second will be printed (and
 that will only happen if the first is @('nil')!).  See @(see ld) for
 details.</p>")

(defxdoc macros
  :parents (acl2)
  :short "Macros allow you to extend the syntax of ACL2.")

(defxdoc macro-aliases-table
  :parents (macros)
  :short "A @(see table) used to associate function names with macro names"
  :long "@({
  Example:
  (table macro-aliases-table 'append 'binary-append)
 })

 <p>This example associates the function symbol @(tsee binary-append) with the
 macro name @(tsee append).  As a result, the name @(tsee append) may be used
 as a runic designator (see @(see theories)) by the various theory functions.
 Thus, for example, it will be legal to write</p>

 @({
  (in-theory (disable append))
 })

 <p>as an abbreviation for</p>

 @({
  (in-theory (disable binary-append))
 })

 <p>which in turn really abbreviates</p>

 @({
  (in-theory (set-difference-theories (current-theory :here)
                                      '(binary-append)))

  General Form:

  (table macro-aliases-table 'macro-name 'function-name)
 })

 <p>or very generally</p>

 @({
  (table macro-aliases-table macro-name-form function-name-form)
 })

 <p>where @('macro-name-form') and @('function-name-form') evaluate,
 respectively, to a macro name and a symbol in the current ACL2 @(see world).
 See @(see table) for a general discussion of tables and the @('table') event
 used to manipulate tables.</p>

 <p>Note that @('function-name-form') (above) does not need to evaluate to a
 function symbol, but only to a symbol.  As a result, one can introduce the
 alias before defining a recursive function, as follows.</p>

 @({
  (table macro-aliases-table 'mac 'fn)
  (defun fn (x)
    (if (consp x)
        (mac (cdr x))
      x))
 })

 <p>Although this is obviously contrived example, this flexibility can be
 useful to macro writers; see for example the definition of ACL2 system macro
 @(tsee defun-inline).</p>

 <p>The @(tsee table) @(tsee macro-aliases-table) is an alist that associates
 macro symbols with function symbols, so that macro names may be used as runic
 designators (see @(see theories)).  For a convenient way to add entries to
 this @(see table), see @(see add-macro-alias).  To remove entries from the
 @(see table) with ease, see @(see remove-macro-alias).</p>

 <p>This @(see table) is used by the theory functions; see @(see theories).
 For example, in order that @('(disable append)') be interpreted as @('(disable
 binary-append)'), it is necessary that the example form above has been
 executed.  In fact, this @(see table) does indeed associate many of the macros
 provided by the ACL2 system, including @(tsee append), with function symbols.
 Loosely speaking, it only does so when the macro is ``essentially the same
 thing as'' a corresponding function; for example, @('(append x y)') and
 @('(binary-append x y)') represent the same term, for any expressions @('x')
 and @('y').</p>")

(defxdoc macro-args
  :parents (macros)
  :short "The formals list of a macro definition"
  :long "@({
  Examples:
  (x y z)
  (x y z &optional max (base '10 basep))
  (x y &rest rst)
  (x y &key max base)
  (&whole sexpr x y)
 })

 <p>The ``lambda-list'' of a macro definition may include simple formal
 parameter names as well as appropriate uses of the following @('lambda')-list
 keywords from CLTL (pp. 60 and 145), respecting the order shown:</p>

 @({
    &whole,
    &optional,
    &rest,
    &body,
    &key, and
    &allow-other-keys.
 })

 <p>ACL2 does not support @('&aux') and @('&environment').  In addition, we
 make the following restrictions:</p>

 <blockquote>

 <p>(1) initialization forms in @('&optional') and @('&key') specifiers must be
 quoted values;</p>

 <p>(2) @('&allow-other-keys') may only be used once, as the last specifier;
 and</p>

 <p>(3) destructuring is not allowed.</p>

 </blockquote>

 <p>The use of default values is allowed, so that an optional or keyword
 argument may be given in any of the following forms.</p>

 <ul>

 <li>@('arg')</li>

 <li>@('(arg 'init)')</li>

 <li>@('(arg 'init supplied-p)')</li>

 </ul>

 <p>For the second and third forms above, @('init') is the value when the
 argument is not supplied; for the first form, that default value is @('nil').
 Note that it must be quoted.  The @('supplied-p') argument is @('nil') when
 the argument is not supplied, else is @('t'), as illustrated by the demo
 below.</p>

 <p>You are encouraged to experiment with the macro facility.  One way to do so
 is to define a macro that does nothing but return the quotation of its
 arguments, e.g.,</p>

 @({
  (defmacro demo (x y &optional (opt '5) &key (key1 '6 key1p) key2)
    (list 'quote (list x y opt key1 key1p key2)))
 })

 <p>You may then execute the macro on some sample forms, e.g.,</p>

 @({
    term                         value
  (demo 1 2)                (1 2 5 6 NIL NIL)
  (demo 1 2 3)              (1 2 3 6 NIL NIL)
  (demo 1 2 3 :key1 6)      (1 2 3 6 T NIL)
  (demo 1 2 3 :key1 7)      (1 2 3 7 T NIL)
  (demo 1 2 3 :key2 8)      (1 2 3 6 NIL 8)
  (demo 1 2 :key1 3)        error:  non-even key/value arglist
                            (because :key1 is used as opt)
 })

 <p>In particular, Common Lisp specifies that if you use both @('&rest') and
 @('&key'), then both will be bound using the same list of arguments.  The
 following example should serve to illustrate how this works.</p>

 @({
  ACL2 !>(defmacro foo (&rest args &key k1 k2 k3)
           (list 'quote (list args k1 k2 k3)))

  Summary
  Form:  ( DEFMACRO FOO ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FOO
  ACL2 !>(foo :k1 3 :k2 4 :k3 5)
  ((:K1 3 :K2 4 :K3 5) 3 4 5)
  ACL2 !>(foo :k1 3 :k2 4)
  ((:K1 3 :K2 4) 3 4 NIL)
  ACL2 !>(foo :k1 3 :bad-key 7)

  ACL2 Error in macro expansion:  Illegal key/value args (:BAD-KEY 7)
  in macro expansion of (FOO :K1 3 :BAD-KEY 7).  The argument list for
  FOO is
  (&REST ARGS &KEY K1 K2 K3).

  ACL2 !>
 })

 <p>If we don't want to get the error above, we can use @('&allow-other-keys'),
 as follows.</p>

 @({
  ACL2 !>(defmacro bar (&rest args &key k1 k2 k3
                              &allow-other-keys)
           (list 'quote (list args k1 k2 k3)))

  Summary
  Form:  ( DEFMACRO BAR ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   BAR
  ACL2 !>(bar :k1 3 :bad-key 7)
  ((:K1 3 :BAD-KEY 7) 3 NIL NIL)
  ACL2 !>
 })

 <p>Also see @(see trans).</p>")

(defxdoc macro-command
  :parents (proof-builder)
  :short "Compound command for the interactive proof-builder"
  :long "<p>The interactive @(see proof-builder) supports the definition of
 compound commands, called ``macro commands'', which expand into zero or more
 other commands.  Some of these are ``atomic'' macro commands; these are viewed
 as a single command step when completed successfully.</p>

 <p>More @(see documentation) may be written on the interactive @(see
 proof-builder).  For now, we simply point out that there are lots of examples
 of the use of @('define-pc-macro') and @('define-pc-atomic-macro') in the ACL2
 source file @('\"proof-builder-b.lisp\"').  The former is used to create macro
 commands, which can be submitted to the interactive loop (see @(see verify))
 and will ``expand'' into zero or more commands.  The latter is similar, except
 that the undoing mechanism (see @(see acl2-pc::undo)) understands atomic macro
 commands to represent single interactive commands.  Also see @(see
 acl2-pc::comm) and see @(see acl2-pc::commands) for a discussion of the
 display of interactive commands.</p>

 <p>Also see @(see toggle-pc-macro) for how to change a macro command to an
 atomic macro command, and vice versa.</p>")

(defxdoc magic-ev-fncall
  :parents (meta)
  :short "Call the named function on the given arguments and return the value."
  :long "<p>Introduction.  @('Magic-ev-fncall') is a @(see logic)-mode function
 that can apply a given function (which need not be in logic mode) to an
 argument list.  Although the result can be computed, @('magic-ev-fncall') is
 technically a constrained function (with unknown constraints), which can be
 assumed in metafunctions and clause processors to produce correct results, via
 @(see meta-extract).</p>

 <p>Examples:</p>

 @({
  (magic-ev-fncall 'cons '(3 4) state t nil)
    = (mv nil '(3 . 4))
  (magic-ev-fncall (car '(floor foo)) (list (+ 6 7) 5) state t nil)
    = (mv nil 2)
 })

 <p>General Form:</p>

 @({
  (magic-ev-fncall fn arglist state hard-error-returns-nilp aokp)
 })

 <p>where @('fn') is a function symbol, @('arglist') is a suitable argument
 list for @('fn'), and the last two formals are described below.  When
 successful, the result is @('(mv nil value)') where @('value') is the
 application of @('fn') to @('arglist').  Although this fact cannot be proven,
 it may be assumed correct in metafunctions and clause processors via @(see
 meta-extract), assuming of course that @('fn') is a @(see logic)-mode
 function.</p>

 <p>In general, the result is either @('(mv t error-msg)') (if, e.g., the
 function was not defined, the arity was wrong, or the guards were violated) or
 @('(mv nil value)') on success.  In the case of a multiple-valued function the
 second return value is the list of values.  A non-nil error message,
 @('error-msg'), is a message suitable for printing with @(tsee fmt); see @(see
 msg).</p>

 <p>If a hard error is encountered during execution and
 @('hard-error-returns-nilp') is non-@('nil'), then the error is ignored and
 the value returned is @('(mv nil nil)') (note that the logical value of a call
 of @('HARD-ERROR') is @('nil')).  If @('hard-error-returns-nilp') is @('nil')
 then the return value is of the form @('(mv T error-msg)').</p>

 <p>The @('aokp') argument controls whether attachments to constrained
 functions may be executed (see @(see defattach)).  If @('nil'), then an error
 message is returned when an attachment would otherwise be executed.</p>

 <p>When used in a clause-processor or metafunction, it can be assumed via a
 @(see meta-extract) hypothesis that @('magic-ev-fncall') works correctly with
 respect to the evaluator, but only if @('hard-error-returns-nilp') is @('t')
 and @('aokp') is @('nil').</p>

 <p>The @(see guard) for @('(magic-ev-fncall fn arglist state h aokp)') is
 @('t'), but evaluation of this call enforces the following requirements.</p>

 <ul>

 <li>@('Fn') must be a function symbol of the current ACL2 @(see world) other
 than @('if'), whose arity is equal to the length of the true-list,
 @('arglist').:</li>

 <li>@('Fn') must not have any @('stobj') inputs or be a stobj creator.</li>

 <li>Calls of @('fn') must not require a trust tag (see @(see defttag)).</li>

 <li>@('Fn') must not be untouchable (see @(see push-untouchable)).</li>

 </ul>

 <p>The implementation of these checks incorporates a bit of trickery so that
 they are not reasonably efficient.</p>

 <p>Note that @(tsee set-guard-checking) affects evaluation of calls of
 @('(magic-ev-fncall fn ...)') just as it affects calls of @('fn'), for example
 as follows.</p>

 @({
 ACL2 !>(magic-ev-fncall 'car '((a b c)) state t nil)
 (NIL A)
 ACL2 !>(magic-ev-fncall 'car '(3) state t nil)
 (T <... message elided here ...>)
 ACL2 !>(set-guard-checking nil)

 Masking guard violations but still checking guards except for self-
 recursive calls.  To avoid guard checking entirely, :SET-GUARD-CHECKING
 :NONE.  See :DOC set-guard-checking.

 ACL2 >(magic-ev-fncall 'car '(3) state t nil)
 (NIL NIL)
 ACL2 >
 })

 <p>Additional Notes.</p>

 <ul>

 <li>If @('fn') is a @(see program)-mode function, then the call will be
 evaluated under @(see safe-mode), which avoids raw Lisp errors due to calls of
 ill-@(see guard)ed program-mode functions.</li>

 <li>If the application of @('fn') returns multiple values @('(mv v1 v2 ...)'),
 then the resulting value will be the corresponding list @('(v1 v2 ...)').</li>

 <li>A reasonable model for @('(magic-ev-fncall 'fn (list a1 a2 ...) state h
 aokp)') is @('(ec-call (fn a1 a2 ...))').</li>

 </ul>")

(defxdoc make
  :parents (defrec acl2-built-ins)
  :short "Constructor macro for @(see defrec) structures."

  :long "<p>The @('make') macro is built into ACL2, and allows you to construct
 new instances of structures that have been introduced with @(see defrec).  For
 instance:</p>

 @({
    (make employee :name \"Jimmy\"
                   :salary 0
                   :position \"Unpaid Intern\")
 })

 <p>Creates a new @('employee') structure with the given values for its
 @('name'), @('salary'), and @('position') fields.  See @(see defrec) for more
 information.</p>")

(defxdoc make-character-list
  :parents (characters acl2-built-ins)
  :short "@(see coerce) to a list of characters"
  :long "<p>Non-characters in the given list are @(see coerce)d to the
 character with code 0.</p>

 @(def make-character-list)")

(defxdoc make-event
  :parents (events macros)
  :short "Evaluate (expand) a given form and then evaluate the result"
  :long "<p>@('Make-event') is a utility for generating @(see events).  It
 provides a capability not offered by Lisp macros (see @(see defmacro)), as it
 allows access to the ACL2 @(tsee state) and logical @(see world).  In essence,
 the expression @('(make-event form)') replaces itself with the result of
 evaluating @('form'), say, @('ev'), as though one had submitted @('ev')
 instead of the @('make-event') call.  For example,
 @('(make-event (quote (defun f (x) x)))') is equivalent to the event @('(defun
 f (x) x)').</p>

 <p>There are several simple examples below.  See @(see make-event-example) for
 development of a more complex example.</p>

 <p>We break this documentation into the following sections.</p>

 <p><b>Introduction</b><br></br>

 <b>Detailed Documentation</b><br></br>

 <b>Error Reporting</b><br></br>

 <b>Restriction to Event Contexts</b><br></br>

 <b>Examples Illustrating How to Access State</b><br></br>

 <b>Advanced Expansion Control</b></p>

 <p>We begin with an informal introduction, which focuses on examples and
 introduces the key notion of ``expansion phase''.</p>

 <p><b>Introduction</b></p>

 <p>@('Make-event') is particularly useful for those who program using the ACL2
 @(tsee state); see @(see programming-with-state).  That is because the
 evaluation of @('form') may read and even modify the ACL2 @(tsee state).</p>

 <p>Suppose for example that we want to define a constant @('*world-length*'),
 that is the length of the current ACL2 @(see world).  A @('make-event') form
 can accomplish this task, as follows.</p>

 @({
    ACL2 !>(length (w state))
    98883
    ACL2 !>(make-event
            (list 'defconst '*world-length* (length (w state))))

    Summary
    Form:  ( DEFCONST *WORLD-LENGTH* ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

    Summary
    Form:  ( MAKE-EVENT (LIST ...))
    Rules: NIL
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     *WORLD-LENGTH*
    ACL2 !>*world-length*
    98883
    ACL2 !>(length (w state))
    98890
    ACL2 !>
 })

 <p>How did this work?  First, evaluation of the form @('(list 'defconst
 '*world-length* (length (w state)))') returned the event form @('(defconst
 *world-length* 98883)').  Then that event form was automatically submitted to
 ACL2.  Of course, that changed the ACL2 logical @(see world), which is why the
 final value of @('(length (w state))') is greater than its initial value.</p>

 <p>The example above illustrates how the evaluation of a @('make-event') call
 takes place in two phases.  The first phase evaluates the argument of the
 call, in this case @('(list 'defconst '*world-length* (length (w state)))'),
 to compute an event form, in this case @('(defconst *world-length* 98883)').
 We call this evaluation the ``expansion'' phase.  Then the resulting event
 form is evaluated, which in this case defines the constant
 @('*world-length*').</p>

 <p>Now suppose we would like to introduce such a @(tsee defconst) form any
 time we like.  It is common practice to define macros to automate such tasks.
 Now we might be tempted simply to make the following definition.</p>

 @({
  ; WRONG!
  (defmacro define-world-length-constant (name state)
    (list 'defconst name (length (w state))))
 })

 <p>But ACL2 rejects such a definition, because a macro cannot take the ACL2
 state as a parameter; instead, the formal parameter to this macro named
 @('\"STATE\"') merely represents an ordinary object.  You can try to
 experiment with other such direct methods to define such a macro, but they
 won't work.</p>

 <p>Instead, however, you can use the approach illustrated by the
 @('make-event') example above to define the desired macro, as follows.</p>

 @({
  (defmacro define-world-length-constant (name)
    `(make-event (list 'defconst ',name (length (w state)))))
 })

 <p>Here are example uses of this macro.</p>

 @({
    ACL2 !>(define-world-length-constant *foo*)

    Summary
    Form:  ( DEFCONST *FOO* ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

    Summary
    Form:  ( MAKE-EVENT (LIST ...))
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     *FOO*
    ACL2 !>*foo*
    98891
    ACL2 !>:pe *foo*
              2:x(DEFINE-WORLD-LENGTH-CONSTANT *FOO*)

    >             (DEFCONST *FOO* 98891)
    ACL2 !>(length (w state))
    98897
    ACL2 !>(define-world-length-constant *bar*)

    Summary
    Form:  ( DEFCONST *BAR* ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

    Summary
    Form:  ( MAKE-EVENT (LIST ...))
    Rules: NIL
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     *BAR*
    ACL2 !>*bar*
    98897
    ACL2 !>:pe *bar*
              3:x(DEFINE-WORLD-LENGTH-CONSTANT *BAR*)

    >             (DEFCONST *BAR* 98897)
    ACL2 !>(length (w state))
    98903
    ACL2 !>
 })

 <p>Finally, we note that the expansion phase can be used for computation that
 has side effects, generally by modifying state.  Here is a modification of the
 above example that does not change the world at all, but instead saves the
 length of the world in a state global.</p>

 @({
  (make-event
   (pprogn (f-put-global 'my-world-length (length (w state)) state)
           (value '(value-triple nil))))
 })

 <p>Notice that this time, the value returned by the expansion phase is not an
 event form, but rather, is an @(see error-triple) whose value component is an
 event form, namely, the event form @('(value-triple nil)').  Evaluation of
 that event form does not change the ACL2 world (see @(see value-triple)).
 Thus, the sole purpose of the @('make-event') call above is to change the
 @(see state) by associating the length of the current logical world with the
 state global named @(''my-world-length').  After evaluating this form, @('(@
 my-world-length)') provides the length of the ACL2 world, as illustrated by
 the following transcript.</p>

 @({
    ACL2 !>:pbt 0
              0:x(EXIT-BOOT-STRAP-MODE)
    ACL2 !>(length (w state))
    98883
    ACL2 !>(make-event
            (pprogn (f-put-global 'my-world-length (length (w state)) state)
                    (value '(value-triple nil))))

    Summary
    Form:  ( MAKE-EVENT (PPROGN ...))
    Rules: NIL
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     NIL
    ACL2 !>(length (w state))
    98883
    ACL2 !>:pbt 0
              0:x(EXIT-BOOT-STRAP-MODE)
    ACL2 !>
 })

 <p>When @('make-event') is invoked by a book, it is expanded during book
 certification but not, by default, when the book is included.  So for the
 example @('(define-world-length-constant *foo*)') given above, if that form is
 in a book, then the value of @('*foo*') will be the length of the world at the
 time this form was invoked during book certification, regardless of world
 length at @(tsee include-book) time.  (The expansion is recorded in the book's
 @(see certificate), and re-used.)  To overcome this default, you can specify
 keyword value @(':CHECK-EXPANSION t').  This will cause an error if the
 expansion is different, but it can be useful for side effects.  For example,
 if you insert the following form in a book, then the length of the world will
 be printed when the form is encountered, whether during @(tsee certify-book)
 or during @(tsee include-book).</p>

 @({
  (make-event
   (pprogn (fms \"Length of current world: ~x0~|\"
                (list (cons #\\0 (length (w state))))
                *standard-co* state nil)
           (value '(value-triple nil)))
   :check-expansion t)
 })

 <p><b>Detailed Documentation</b></p>

 @({
  Examples:

  ; Trivial example: evaluate (quote (defun foo (x) x)) to obtain
  ; (defun foo (x) x), which is then evaluated.
  (make-event (quote (defun foo (x) x)))

  ; Evaluate (generate-form state) to obtain (mv nil val state), and
  ; then evaluate val.  (Generate-form is not specified here, but
  ; imagine for example that it explores the state and then generates
  ; some desired definition or theorem.)
  (make-event (generate-form state))

  ; As above, but make sure that if this form is in a book, then when
  ; we include the book, the evaluation of (generate-form state)
  ; should return the same value as it did when the book was
  ; certified.
  (make-event (generate-form state)
              :CHECK-EXPANSION t)

  General Form:
  (make-event form :CHECK-EXPANSION chk :ON-BEHALF-OF obj :EXPANSION? form)
 })

 <p>where @('chk') is @('nil') (the default), @('t'), or the intended
 ``expansion result'' from the evaluation of @('form') (as explained below);
 and if supplied, @('obj') is an arbitrary ACL2 object, used only in reporting
 errors in expansion, i.e., in the evaluation of form.  The @(':EXPANSION?')
 keyword is discussed in the final section, on Advanced Expansion Control. See
 @(see make-event-details) for discussion of the @(':ON-BEHALF-OF')
 keyword.</p>

 <p>We strongly recommend that you browse some @('.lisp') files in the
 community books directory @('books/make-event/').  You may even find it
 helpful, in order to understand @('make-event'), to do so before continuing to
 read this documentation.  You may also find it useful to browse community book
 @('books/misc/eval.lisp'), which contains definitions of macros
 @('must-succeed') and @('must-fail') that are useful for testing and are used
 in many books in the @('books/make-event/') directory, especially
 @('eval-tests.lisp').  Another example, @('books/make-event/defrule.lisp'),
 shows how to use macros whose calls expand to @('make-event') forms, which in
 turn can generate @(see events).  For more examples, see file
 @('books/make-event/Readme.lsp').  Other than the examples, the explanations
 here should suffice for most users.  If you want explanations of subtler
 details, see @(see make-event-details).</p>

 <p>Note that @('make-event') is generally legal only where an embedded event
 form is expected: essentially, at the top level of a book or the
 read-eval-print loop, possibly within surrounding calls of @('make-event') or
 of event constructors such as @(tsee progn) and @(tsee encapsulate).  For
 details see the section ``Restriction to Event Contexts'', below.</p>

 <p>@('Make-event') is related to Lisp macroexpansion in the sense that its
 argument is evaluated to obtain an expansion result, which is evaluated again.
 Let us elaborate on each of these notions in turn: ``is evaluated,''
 ``expansion result'', and ``evaluated again.''  The final section, on Advanced
 Expansion Control, will generalize these processes in a way that we ignore for
 now.</p>

 <blockquote>

 <p>``is evaluated'' &mdash; The argument can be any expression, which is
 evaluated as would be any expression submitted to ACL2's top level loop.
 Thus, @(tsee state) and user-defined @(tsee stobj)s may appear in the form
 supplied to @('make-event').  Henceforth, we will refer to this evaluation as
 ``expansion.''  Expansion is actually done in a way that restores ACL2's
 built-in @(tsee state) global variables, including the logical @(see world),
 to their pre-expansion values (with a few exceptions &mdash; see @(see
 make-event-details) &mdash; and where we note that changes to user-defined
 @(tsee state) global variables (see @(see assign)) are preserved).  So, for
 example, events might be evaluated during expansion, but they will disappear
 from the logical @(see world) after expansion returns its result.  Moreover,
 proofs are enabled by default at the start of expansion (see @(see
 ld-skip-proofsp)) if keyword @(':CHECK-EXPANSION') is supplied and has a
 non-@('nil') value.</p>

 <p>``expansion result'' &mdash; The above expansion may result in an ordinary
 (non-@(tsee state), non-@(tsee stobj)) value, which we call the ``expansion
 result.''  Or, expansion may result in a multiple value of the form @('(mv erp
 val state)'), or, more generally, @('(mv erp val state stobj-1 ... stobj-k)')
 where each @('stobj-i') is a @(see stobj); then the expansion result is
 @('val') unless @('erp') is not @('nil'), in which case there is no expansion
 result, and the original @('make-event') evaluates to a soft error.  In either
 case (single or multiple value), either @('val') is an embedded event form
 (see @(see embedded-event-form)), or else the original @('make-event')
 evaluates to a soft error, printed as described under ``Error Reporting''
 below.<br/>
 (<i>Technical remark</i>: The expansion result described above may be modified
 for @(tsee include-book), @(tsee add-include-book-dir), and @(tsee
 add-include-book-dir!), replacing book names by full pathnames, using syntax
 @('(:system . relative-pathname)') for @(see community-books) (i.e., system
 books); see @(see full-book-name), and for further details see comments in
 source function @('make-include-books-absolute').  End of technical
 remark.)</p>

 <p>``evaluated again'' &mdash; the expansion result is evaluated in place of
 the original @('make-event').</p>

 </blockquote>

 <p>The expansion process can invoke subsidiary calls of @('make-event'), and
 the expansion result can (perhaps after macroexpansion) be a call of
 @('make-event').  It can be useful to track all these @('make-event') calls.
 The @(see state) global variable @('make-event-debug') may be set to a
 non-@('nil') value, for example @('(assign make-event-debug t)'), in order to
 see a trace of the expansion process, where a level is displayed (as in
 ``@('3>')'') to indicate the depth of subsidiary expansions.</p>

 <p>Expansion of a @('make-event') call will yield an event that replaces the
 original @('make-event') call.  In particular, if you put a @('make-event')
 form in a book, then in essence it is replaced by its expansion result,
 created during the proof pass of the @(tsee certify-book) process.  We now
 elaborate on this idea of keeping the original expansion.</p>

 <p>A @('make-event') call generates a ``@('make-event') replacement'' that may
 be stored by the system.  In the simplest case, this replacement is the
 expansion result.  When a book is certified, these replacements are stored in
 a book's certificate (technically, in the @(':EXPANSION-ALIST') field).  Thus,
 although the book is not textually altered during certification, one may
 imagine a ``book expansion'' corresponding to the original book, in which
 events are substituted by replacements that were generated during the proof
 phase of certification.  A subsequent @(tsee include-book) will then include
 the book expansion corresponding to the indicated book.  When a book is
 compiled during @(tsee certify-book), it is actually the corresponding book
 expansion, stored as a temporary file, that is compiled instead.  That
 temporary file is deleted after compilation unless one first evaluates the
 form @('(assign keep-tmp-files t)').  Note however that all of the original
 forms must still be legal @(see events); see @(see embedded-event-form).  So
 for example, if the first event in a book is @('(local (defmacro my-id (x)
 x))'), and is followed by @('(my-id (make-event ...))'), the final
 ``@('include-book')'' pass of @(tsee certify-book) will fail because
 @('my-id') is not defined when the @('my-id') call is encountered.</p>

 <p>A @('make-event') replacement might not be the expansion when either of the
 keyword arguments @(':CHECK-EXPANSION') or @(':EXPANSION?') is supplied.  We
 deal with the latter in the final section, on Advanced Expansion Control.  If
 @(':CHECK-EXPANSION t') is supplied and the expansion is @('exp'), then the
 replacement is obtained from the original @('make-event') call, by
 substituting @('exp') for @('t') as the value of keyword
 @(':CHECK-EXPANSION').  Such a @('make-event') call &mdash; during the second
 pass of an @(tsee encapsulate), or during event processing on behalf of @(tsee
 include-book) other than when including a book near the end of its
 certification process &mdash; will do the expansion again and check that the
 expansion result is equal to the original expansion result, @('exp').  In the
 unusual case that you know the expected expansion result, @('res'), you can
 specify @(':CHECK-EXPANSION res') in the first place, so that the check is
 also done during the initial evaluation of the @('make-event') form.
 IMPORTANT BUT OBSCURE DETAIL: That expansion check is only done when
 processing events, not during a preliminary load of a book's compiled file.
 The following paragraph elaborates.</p>

 <p>(Here are details on the point made just above, for those who use the
 @(':CHECK-EXPANSION') argument to perform side-effects on the @(see state).
 When you include a book, ACL2 generally loads a compiled file before
 processing the events in the book; see @(see book-compiled-file).  While it is
 true that a non-@('nil') @(':CHECK-EXPANSION') argument causes @(tsee
 include-book) to perform expansion of the @('make-event') form during event
 processing it does <i>not</i> perform expansion when the compiled file (or
 expansion file; again, see @(see book-compiled-file)) is loaded.)</p>

 <p>ACL2 performs the following space-saving optimization: when the expansion
 result is a @(tsee local) event, then the @('make-event') replacement is
 @('(local (value-triple :ELIDED))').</p>

 <p>The notion of ``expansion'' and ``replacement'' extend to the case that a
 call of @('make-event') is found in the course of macroexpansion.  The
 following example illustrates this point.</p>

 @({
  (encapsulate
   ()
   (defmacro my-mac ()
     '(make-event '(defun foo (x) x)))
   (my-mac))
  :pe :here
 })

 <p>The above call of @(tsee pe) shows that the form @('(my-mac)') has a
 @('make-event') expansion (and replacement) of @('(DEFUN FOO (X) X)'):</p>

 @({
  (ENCAPSULATE NIL
               (DEFMACRO MY-MAC
                         NIL
                         '(MAKE-EVENT '(DEFUN FOO (X) X)))
               (RECORD-EXPANSION (MY-MAC)
                                 (DEFUN FOO (X) X)))
 })

 <p><b>Error Reporting</b></p>

 <p>Suppose that expansion produces a soft error as described above.  That is,
 suppose that the argument of a @('make-event') call evaluates to a multiple
 value @('(mv erp val state ...)') where @('erp') is not @('nil').  If @('erp')
 is a string, then that string is printed in the error message.  If @('erp') is
 a @(tsee cons) pair whose @(tsee car) is a string, then the error prints
 @('\"~@0\"') with @('#\\0') bound to that @('cons') pair; see @(see fmt).  Any
 other non-@('nil') value of @('erp') causes a generic error message to be
 printed.</p>

 <p><b>Restriction to Event Contexts</b></p>

 <p>A @('make-event') call must occur either at the top level, or during
 @('make-event') expansion, or as an argument of an event constructor.  We
 explain in more detail below.  This restriction is imposed to enable ACL2 to
 track expansions produced by @('make-event').</p>

 <p>The following examples illustrate this restriction.</p>

 @({
  ; Legal:
  (progn (with-output
          :on summary
          (make-event '(defun foo (x) x))))

  ; Illegal:
  (mv-let (erp val state)
          (make-event '(defun foo (x) x))
          (mv erp val state))
 })

 <p>More precisely: a @('make-event') call that is not itself evaluated during
 @('make-event') expansion is subject to the following requirement.  After
 macroexpansion has taken place, such a @('make-event') call must be in an
 ``event context'', defined recursively as follows.  (All but the first two
 cases below correspond to similar cases for constructing events; see @(see
 embedded-event-form).)</p>

 <ul>

 <li>A form submitted at the top level, or more generally, supplied to a call
 of @(tsee ld), is in an event context.</li>

 <li>A form occurring at the top level of a book is in an event context.</li>

 <li>If @('(')@(tsee LOCAL)@(' x1)') is in an event context, then so is
 @('x1').</li>

 <li>If @('(')@(tsee SKIP-PROOFS)@(' x1)') is in an event context, then so is
 @('x1').</li>

 <li>If @('(')@(tsee MAKE-EVENT)@(' x ...)') is in an event context and its
 expansion @('x1') is an embedded event form, then @('x1') is in an event
 context.</li>

 <li>If @('(')@(tsee WITH-OUTPUT)@(' ... x1)'), @('(')@(tsee
 WITH-PROVER-STEP-LIMIT)@(' ... x1 ...)'), or @('(')@(tsee
 WITH-PROVER-TIME-LIMIT)@(' ... x1)') is in an event context, then so is
 @('x1').</li>

 <li>For any call of @(tsee PROGN) or @(tsee PROGN!), each of its arguments is
 in an event context.</li>

 <li>For any call of @(tsee ENCAPSULATE), each of its arguments except the
 first (the signature list) is in an event context.</li>

 <li>If @('(RECORD-EXPANSION x1 x2)') is in an event context, then @('x1') and
 @('x2') are in event contexts.  Note: @('record-expansion') is intended for
 use only by the implementation, which imposes the additional restriction that
 @('x1') and its subsidiary @('make-event') calls (if any) must specify a
 @(':CHECK-EXPANSION') argument that is a @(see consp).</li>

 </ul>

 <p>Low-level remark, for system implementors.  There is the one exception to
 the above restriction: a single @(tsee state-global-let*) form immediately
 under a @('progn!') call.  For example:</p>

 @({
  (progn! (state-global-let* <bindings> (make-event ...)))
 })

 <p>However, the following form may be preferable (see @(see progn!)):</p>

 @({
  (progn! :STATE-GLOBAL-BINDINGS <bindings> (make-event ...))
 })

 <p>Also see @(see remove-untouchable) for an interesting use of this
 exception.</p>

 <p><b>Examples Illustrating How to Access State</b></p>

 <p>You can modify the ACL2 @(see state) by doing your state-changing
 computation during the expansion phase, before expansion returns the event
 that is submitted.  Here are some examples.</p>

 <p>First consider the following.  Notice that expansion modifies state global
 @('my-global') during @('make-event') expansion, and then expansion returns a
 @(tsee defun) event to be evaluated.</p>

 @({
  (make-event
    (er-progn (assign my-global (length (w state)))
              (value '(defun foo (x) (cons x x)))))
 })

 <p>Then we get:</p>

 @({
    ACL2 !>(@ my-global)
    72271
    ACL2 !>:pe foo
     L        1:x(MAKE-EVENT (ER-PROGN # #))

    >L            (DEFUN FOO (X) (CONS X X))
    ACL2 !>
 })

 <p>Here's a slightly fancier example, where the computation affects the @(tsee
 defun).  In a new session, execute:</p>

 @({
  (make-event
    (er-progn (assign my-global (length (w state)))
              (value `(defun foo (x) (cons x ,(@ my-global))))))
 })

 <p>Then:</p>

 @({
    ACL2 !>(@ my-global)
    72271
    ACL2 !>:pe foo
     L        1:x(MAKE-EVENT (ER-PROGN # #))

    >L            (DEFUN FOO (X) (CONS X 72271))
    ACL2 !>
 })

 <p>Note that ACL2 @(see table) @(see events) may avoid the need to use @(see
 state) globals.  For example, instead of the example above, consider this
 example in a new session.</p>

 @({
  (make-event
    (let ((world-len (length (w state))))
      `(progn (table my-table :STORED-WORLD-LENGTH ,world-len)
              (defun foo (x) (cons x ,world-len)))))
 })

 <p>Then:</p>

 @({
    ACL2 !>(table my-table)
     ((:STORED-WORLD-LENGTH . 72271))
    ACL2 !>:pe foo
              1:x(MAKE-EVENT (LET # #))

    >L            (DEFUN FOO (X) (CONS X 72271))
    ACL2 !>
 })

 <p>By the way, most built-in @(see state) globals revert after expansion.  But
 your own global (like @('my-global') above) can be set during expansion, and
 the new value will persist.</p>

 <p><b>Advanced Expansion Control</b></p>

 <p>We conclude this @(see documentation) section by discussing three kinds of
 additional control over @('make-event') expansion.  These are all illustrated
 in community book @('books/make-event/make-event-keywords-or-exp.lisp').  The
 discussion below is split into the following three parts.</p>

 <p>(1) The value produced by expansion may have the form @('(:DO-PROOFS
 exp)'), which specifies @('exp') as the expansion result, to be evaluated
 without skipping proofs even when including a book.</p>

 <p>(2) The value produced by expansion may have the form @('(:OR exp-1
 ... exp-k)'), which specifies that the first form @('exp-i') to evaluate
 without error is the expansion result.</p>

 <p>(3) The keyword argument @(':EXPANSION?') can serve to eliminate the
 storing of @('make-event') replacements, as described above for the ``book
 expansion'' of a book.</p>

 <p>We now elaborate on each of these.</p>

 <p>(1) @(':DO-PROOFS') ``call'' produced by expansion.</p>

 <p>We have discussed the expansion result produced by the expansion phase of
 evaluating a @('make-event') call.  However, if the expansion phase produces
 an expression of the form @('(:DO-PROOFS exp)'), then the expansion result is
 actually @('exp').  The @(':DO-PROOFS') wrapper indicates that even if proofs
 are currently being skipped (see @(see ld-skip-proofsp)), then evaluation of
 @('exp') should take place with proofs not skipped.  For example, proofs will
 be performed when evaluating the @('make-event') expansion, namely the
 indicated @('defthm') event, in the following example.</p>

 @({
  (set-ld-skip-proofsp t state)
  (make-event '(:DO-PROOFS
                (defthm app-assoc (equal
                                   (append (append x y) z)
                                   (append x y z)))))
 })

 <p>Note that such use of @(':DO-PROOFS') causes proofs to be performed when
 evaluating the expansion while including an uncertified book.  But when
 including a certified book, then unless @(':CHECK-EXPANSION') is supplied a
 non-@('nil') value, the @('make-event') replacement will just be the
 expansion, which does not include the @(':DO-PROOFS') wrapper and hence will
 be evaluated with proofs skipped.</p>

 <p>(2) @(':OR') ``call'' produced by expansion.</p>

 <p>There may be times where you want to try different expansions.  For
 example, the community book @('books/make-event/proof-by-arith.lisp') attempts
 to admit a given event, which we'll denote @('EV'), by trying events of the
 following form as @('BOOK') varies over different community books.</p>

 @({
  (encapsulate
   ()
   (local (include-book BOOK :DIR :SYSTEM))
   EV)
 })

 <p>A naive implementation of this macro would evaluate all such @(tsee
 encapsulate) events until one succeeds, and then return that successful event
 as the expansion.  Then that event would need to be evaluated again!  With
 some hacking one could avoid that re-evaluation by using @(tsee skip-proofs),
 but that won't work if you are trying to create a certified book without
 skipped proofs.  Instead, the implementation creates an expansion of the form
 @('(:OR ev-1 ev-2 ... ev-k)'), where the list @('(ev-1 ev-2 ... ev-k)')
 enumerates the generated encapsulate events.  In general, for this
 ``disjunctive case'' of a result from expansion, each @('ev-i') is evaluated
 in sequence, and the first that succeeds without error is considered to be the
 expansion result &mdash; and a repeat evaluation is avoided.  If evaluation of
 each @('ev-i') results in an error, then so does the @('make-event') call.</p>

 <p>This special use of @(':OR') in a value produced by expansion is only
 supported at the top level.  That is, the result can be @('(:OR ev-1 ev-2
 ... ev-k)') but then each @('ev-i') must be a legal expansion result, without
 such further use of @(':OR') &mdash; except, @('ev-i') may be <tt>(:DO-PROOFS
 ev-i')</tt>, where @('ev-i'') then would serve as the expansion rather than
 @('ev-i').</p>

 <p>(3) The @(':EXPANSION?') keyword argument.</p>

 <p>If keyword argument @(':EXPANSION?') has a non@('nil') value, then the
 @(':CHECK-EXPANSION') keyword must be omitted or have value @('nil') or
 @('t'), hence not a cons pair.</p>

 <p>The idea of the @(':EXPANSION?') keyword is to give you a way to avoid
 storing expansion results in a book's @(see certificate).  Roughly speaking,
 when the expansion result matches the value of @(':EXPANSION?'), then no
 expansion result is stored for the event by book certification; then when the
 book is later included, the value of @(':EXPANSION?') is used as the
 expansion, thus bypassing the expansion phase.  One could say that the event
 is its own make-event replacement, but it is more accurate to say that there
 is no make-event replacement at all, since nothing is stored in the
 certificate for this event.  Below, we elaborate on make-event replacements
 when @(':EXPANSION?') is used and also discuss other properties of this
 keyword.</p>

 <p>We modify the notion of ``expansion result'' for @('make-event') forms to
 comprehend the use of the @(':EXPANSION?') keyword.  For that purpose, let's
 consider a call of @('make-event') to be ``reducible'' if it has an
 @(':EXPANSION?') keyword with non-@('nil') value, @('exp'), and its
 @(':CHECK-EXPANSION') keyword is missing or has value @('nil'), in which case
 the ``reduction'' of this @('make-event') call is defined to be @('exp').  The
 expansion result as originally defined is modified by the following
 ``recursive reduction'' process: recur through the original expansion, passing
 through calls of @(tsee local), @(tsee skip-proofs), @(tsee with-output),
 @(tsee with-prover-step-limit), and @(tsee with-prover-time-limit), and
 replacing (recursively) any reducible call of @('make-event') by its
 reduction.  Furthermore, we refer to two forms as ``reduction equivalent'' if
 their recursive reductions are equal.  Note that the recursive reduction
 process does not pass through @(tsee progn) or @(tsee encapsulate), but that
 process is applied to the computation of expansions for their subsidiary
 @(tsee make-event) calls.</p>

 <p>To explain further the effect of @(':EXPANSION? exp'), we split into the
 following two cases.</p>

 <p><b>Case 1</b>: Evaluation is not taking place when including a book or
 evaluating the second pass of an @(tsee encapsulate) event; more precisely,
 the value of @('(ld-skip-proofsp state)') is not the symbol @('INCLUDE-BOOK').
 There are two subcases.</p>

 <ul>

 <li>Case 1a: The expansion result is not reduction-equivalent to @('exp').
 Then the @('make-event') call is processed as though the @(':EXPANSION?')
 keyword had been omitted.</li>

 <li>Case 2a: The expansion result is reduction-equivalent to @('exp').  Then
 there is no @('make-event') replacement for this call of @('make-event'); no
 replacement will be put into the @(see certificate) file for a book containing
 this @('make-event') call.  When that book is subsequently included, the
 original form will be evaluated in the manner described in the next
 case.</li>

 </ul>

 <p><b>Case 2</b>: Evaluation is taking place when including a book or evaluating
 the second pass of an @(tsee encapsulate) event; more precisely, the value of
 @('(ld-skip-proofsp state)') is the symbol @('INCLUDE-BOOK').  Then the
 expansion is @('exp').  The expansion phase is skipped unless
 @(':CHECK-EXPANSION') is @('t').</p>

 <p>The @(':EXPANSION?') keyword can be particularly useful in concert with the
 disjunctive (``@(':OR')'') case (2) discussed above.  Suppose that expansion
 produces a value as discussed in (2) above, @('(:OR exp-1 ... exp-k)').  If
 one of these expressions @('exp-i') is more likely than the others to be the
 expansion, then you may wish to specify @(':EXPANSION? exp-i'), as this will
 avoid storing a @('make-event') replacement in that common case.  This could
 be useful if the expressions are large, to avoid enlarging the @(see
 certificate) file for a book containing the @('make-event') call.</p>

 <p>It is legal to specify both @(':EXPANSION? exp') and @(':CHECK-EXPANSION
 t').  When either @('(ld-skip-proofsp state)') is the symbol
 @('INCLUDE-BOOK'), or evaluation is taking place in raw Lisp, then this
 combination is treated the same as if @(':EXPANSION?') is omitted and the
 value of @(':CHECK-EXPANSION') is @('exp').  Otherwise, this combination is
 treated the same as @(':CHECK-EXPANSION t'), modified to accommodate the
 effect of @(':EXPANSION?')  as discussed above: if the expansion is indeed the
 value of @(':EXPANSION?'), then no @('make-event') replacement is
 generated.</p>")

(defxdoc make-event-details
  :parents (make-event)
  :short "Details on @(tsee make-event) expansion"
  :long "<p>The normal user of @('make-event') can probably ignore this
 section, but we include it for completeness.  We assume that the reader has
 read and understood the basic documentation for @('make-event') (see @(see
 make-event)), but we begin below with a summary of expansion.</p>

 <h3>Introduction</h3>

 <p>Here is a summary of how we handle expansion involving @('make-event')
 forms.</p>

 <p>@('(make-event form :check-expansion nil)')</p>

 <p>This shows the @(':check-expansion') default of @('nil'), and is typical
 user input.  We compute the expansion @('exp') of @('form'), which is the
 expansion of the original @('make-event') expression and is evaluated in place
 of that expression.</p>

 <p>@('(make-event form :check-expansion t)')</p>

 <p>The user presumably wants it checked that the expansion doesn't change in
 the future, in particular during @(tsee include-book).  If the expansion of
 @('form') is @('exp'), then we will evaluate @('exp') to obtain the value as
 before, but this time we record that the expansion of the original
 @('make-event') expression is @('(make-event form :check-expansion exp)')
 rather than simply @('exp').</p>

 <p>@('(make-event form :check-expansion exp) ; exp a cons')</p>

 <p>This is generated for the case that @(':check-expansion') is @('t'), as
 explained above.  Evaluation is handled as described in that above case,
 except here we check that the expansion result is the given @('exp').
 (Actually, the user is also allowed supply such a form.)  The original
 @('make-event') expression does not undergo any expansion (intuitively, it
 expands to itself).</p>

 <p>Now let us take a look at how we expand @(tsee progn) forms (@(tsee
 encapsulate) is handled similarly).</p>

 <p>@('(progn ... (make-event form :check-expansion nil) ...)')</p>

 <p>The expansion is obtained by replacing the @('make-event') form as follows.
 Let @('exp') be the expansion of @('form').  Then replace the above
 @('make-event') form, which we denote as @('F'), by @('(record-expansion F
 exp)').  Here, @('record-expansion') is a macro that returns its second
 argument.</p>

 <p>@('(progn ... (make-event form :check-expansion t) ...)')</p>

 <p>The expansion is of the form @('(record-expansion F exp)') as in the
 @('nil') case above, except that this time @('exp') is <tt>(make-event form
 :check-expansion exp')</tt>, where @('exp'') is the expansion of
 @('form').</p>

 <p>@('(progn ... (make-event form :check-expansion exp) ...) ; exp a
 cons')</p>

 <p>No expansion takes place unless expansion takes place for at least one of
 the other subforms of the @('progn'), in which case each such form @('F') is
 replaced by @('(record-expansion F exp)') where @('exp') is the expansion of
 @('F').</p>

 <h3>Detailed semantics</h3>

 <p>In our explanation of the semantics of @('make-event'), we assume
 familiarity with the notion of ``embedded event form'' (see @(see
 embedded-event-form)).</p>

 <p>Let's say that the ``actual embedded event form'' corresponding to a given
 form is the underlying call of an ACL2 event: that is, @(tsee LOCAL)s are
 dropped when @('ld-skip-proofsp') is @(''include-book'), and macros are
 expanded away, thus leaving us with a @(tsee progn), a @(tsee make-event), or
 an event form (possibly @(tsee encapsulate)), any of which might have
 surrounding @(tsee local), @(tsee skip-proofs), or @(tsee with-output)
 calls.</p>

 <p>Thus, such an actual embedded event form can be viewed as having the form
 @('(rebuild-expansion wrappers base-form)') where @('base-form') is a
 @('progn'), a @('make-event'), or an event form (possibly @('encapsulate')),
 and @('wrappers') are (as in ACL2 source function @('destructure-expansion'))
 the result of successively removing the event form from the result of
 macroexpansion, leaving a sequence of @('(local)'), @('(skip-proofs)'), and
 @('(with-output ...)') forms.  In this case we say that the form
 ``destructures into'' the indicated @('wrappers') and @('base-form'), and that
 it can be ``rebuilt from'' those @('wrappers') and @('base-form').</p>

 <p>Elsewhere we define the notion of the ``expansion result'' from an
 evaluation (see @(see make-event)), and we mention that when expansion
 concludes, the ACL2 logical @(see world) and most of the @('state') are
 restored to their pre-expansion values.  Specifically, after evaluation of the
 argument of @('make-event') (even if it is aborted), the ACL2 logical world is
 restored to its pre-evaluation value, as are all state global variables in the
 list @('*protected-system-state-globals*').  Thus, assignments to user-defined
 state globals (see @(see assign)) do persist after expansion, since they are
 not in that list.</p>

 <p>We recursively define the combination of evaluation and expansion of an
 embedded event form, as follows.  We also simultaneously define the notion of
 ``expansion takes place,'' which is assumed to propagate upward (in a sense
 that will be obvious), such that if no expansion takes place, then the
 expansion of the given form is considered to be itself.  It is useful to keep
 in mind a goal that we will consider later: Every @('make-event') subterm of
 an expansion result has a @(':check-expansion') field that is a @(tsee consp),
 where for this purpose @('make-event') is viewed as a macro that returns its
 @(':check-expansion') field.  (Implementation note: The latest expansion of a
 @(tsee make-event), @(tsee progn), @(tsee progn!), or @(tsee encapsulate) is
 stored in state global @(''last-make-event-expansion'), except that if no
 expansion has taken place for that form then @(''last-make-event-expansion')
 has value @('nil').)</p>

 <blockquote>

 <p>If the given form is not an embedded event form, then simply cause a soft
 error, @('(mv erp val state)') where @('erp') is not @('nil').  Otherwise:</p>

 <p>If the evaluation of the given form does not take place (presumably because
 @(tsee local) events are being skipped), then no expansion takes place.
 Otherwise:</p>

 <p>Let @('x') be the actual embedded event form corresponding to the given
 form, which destructures into wrappers @('W') and base-form @('B').  Then the
 original form is evaluated by evaluating @('x'), and its expansion is as
 follows.</p>

 <p>If @('B') is @('(make-event form :check-expansion val)'), then expansion
 takes place if and only if @('val') is not a @('consp') and no error occurs,
 as now described.  Let @('R') be the expansion result from protected
 evaluation of @('form'), if there is no error.  @('R') must be an embedded
 event form, or it is an error.  Then evaluate/expand @('R'), where if @('val')
 is not @('nil') then state global @(''ld-skip-proofsp') is initialized to
 @('nil').  (This initialization is important so that subsequent expansions are
 checked in a corresponding environment, i.e., where proofs are turned on in
 both the original and subsequent environments.)  It is an error if this
 evaluation causes an error.  Otherwise, the evaluation yields a value, which
 is the result of evaluation of the original @('make-event') expression, as
 well as an expansion, @('E_R').  Let @('E') be rebuilt from @('W') and
 @('E_R').  The expansion of the original form is @('E') if @('val') is
 @('nil'), and otherwise is the result of replacing the original form's
 @(':check-expansion') field with @('E'), with the added requirement that if
 @('val') is not @('t') (thus, a @('consp')) then @('E') must equal @('val') or
 else we cause an error.</p>

 <p>If @('B') is either @('(progn form1 form2 ...)') or @('(encapsulate sigs
 form1 form2 ...)'), then after evaluating @('B'), the expansion of the
 original form is the result of rebuilding from @('B'), with wrappers @('W'),
 after replacing each @('formi') in @('B') for which expansion takes place by
 <tt>(record-expansion formi formi')</tt>, where @('formi'') is the expansion
 of @('formi').  Note that these expansions are determined as the @('formi')
 are evaluated in sequence (where in the case of @('encapsulate'), this
 determination occurs only during the first pass).  Except, if no expansion
 takes place for any @('formi'), then the expansion of the original form is
 itself.</p>

 <p>Otherwise, the expansion of the original form is itself.</p>

 </blockquote>

 <p>Similarly to the @(tsee progn) and @(tsee encapsulate) cases above, book
 certification causes a book to be replaced by its so-called ``book
 expansion.''  There, each event @('ev') for which expansion took place during
 the proof pass of certification &mdash; say, producing @('ev'') &mdash; is
 replaced by <tt>(record-expansion ev ev')</tt>.</p>

 <p>Implementation Note.  The book expansion is actually implemented by way of
 the @(':expansion-alist') field of its @(see certificate), which associates
 0-based positions of top-level forms in the book (not including the initial
 @(tsee in-package) form) with their expansions.  Thus, the book's source file
 is not overwritten; rather, the certificate's expansion-alist is applied when
 the book is included or compiled.  End of Implementation Note.</p>

 <p>It is straightforward by computational induction to see that for any
 expansion of an embedded event form, every @('make-event') sub-event has a
 @(tsee consp) @(':check-expansion') field.  Here, by ``sub-event'' we mean to
 expand macros; and we also mean to traverse @('progn') and @('encapsulate')
 forms as well as @(':check-expansion') fields of @('make-event') forms.  Thus,
 we will only see @('make-event') forms with @('consp') @(':check-expansion')
 fields in the course of @('include-book') forms, the second pass of
 @('encapsulate') forms, and raw Lisp.  This fact guarantees that an event form
 will always be treated as its original expansion.</p>

 <h3>Notes on ttags</h3>

 <p>See @(see defttag) for documentation of the notion of ``trust tag''
 (``ttag'').  We note here that even if an event @('(defttag tag-name)') for
 non-@('nil') @('tag-name') is admitted only during the expansion phase of a
 @(tsee make-event) form, then such expansion will nevertheless still cause
 @('tag-name') to be recorded in the logical @(see world) (assuming that the
 @('make-event') form is admitted).  So in order to certify such a book, a
 suitable @(':ttags') argument must be supplied; see @(see certify-book).</p>

 <p>ACL2 does provide a way to avoid the need for @(':ttags') arguments in such
 cases.  The idea is to certify a book twice, where the results of
 @('make-event') expansion are saved from the first call of @(tsee
 certify-book) and provided to the second call.  See @(see
 set-write-acl2x).</p>

 <p>Finally, we discuss a very unusual case where certification does not
 involve trust tags but a subsequent @(tsee include-book) does involve trust
 tags: a @('make-event') call specifying @(':check-expansion t'), whose
 expansion generates a @(tsee defttag) event during @(tsee include-book) but
 not @(tsee certify-book).  Consider the following book.</p>

 @({
  (in-package \"ACL2\")
  (make-event
   (er-progn
    (if (@ skip-notify-on-defttag) ; non-nil when including a certified book
        (pprogn
         (fms \"Value of (@ skip-notify-on-defttag): ~x0~|\"
              (list (cons #0 (@ skip-notify-on-defttag)))
              *standard-co* state nil)
         (encapsulate
          ()
          (defttag :foo)
          (value-triple \"Imagine something bad here!\")))
      (value nil))
    (value '(value-triple :some-value)))
   :check-expansion t)
 })

 <p>This book certifies successfully without the need for a @(':ttags')
 argument for @(tsee certify-book).  Indeed, the above book's @(see
 certificate) does not specify @(':foo') as a trust tag associated with the
 book, because no @('defttag') event was executed during book certification.
 Unfortunately, if we try to include this book without specifying a value of
 @(':ttags') that allows @(':foo'), book inclusion will cause executing of the
 above @(tsee defttag).  If that inclusion happens in the context of certifying
 some superior book and the appropriate @(':ttags') arguments have not been
 provided, that certification will fail.</p>

 <h3>Expansion errors and the @(':ON-BEHALF-OF') keyword</h3>

 <p>Consider the case that expansion returns an @(see error-triple) @('(mv erp
 val state)'), where @('erp') is not @('nil').  Then @('make-event') may
 conclude with an error message, as follows.</p>

 <ul>

 <li>If keyword @(':ON-BEHALF-OF') has value @(':quiet!') then there is no such
 concluding error message.</li>

 <li>Otherwise, if @('erp') is a string, then the concluding error message is
 produced by printing @('erp') with the call @('(er soft ctx erp)'), where
 @('ctx') is the context (see @(see ctx)).</li>

 <li>Otherwise, if @('erp') is a message (see @(see msg)), then the concluding
 error message is produced by the call @('(er soft ctx \"~@0\" erp)'), where
 @('ctx') is the context (see @(see ctx)).</li>

 <li>Otherwise, if keyword @(':ON-BEHALF-OF') has value @(':quiet') then there
 is no concluding error message.</li>

 <li>Otherwise, if keyword @(':ON-BEHALF-OF') is not supplied or has value
 @('nil') &mdash; so we are now in the typical case &mdash; then the concluding
 error message is ``Error in MAKE-EVENT from expansion of:'' followed by the
 form.</li>

 <li>Otherwise, keyword @(':ON-BEHALF-OF') has a value @('x') other than
 @(':quiet!'), @(':quiet'), or @('nil'), in which case the concluding error
 message is as just above, except that after ``Error in MAKE-EVENT'' is
 stated ``on behalf of'' followed by @('x').</li>

 </ul>

 <p>Note that errors generated during expansion are not affected by the cases
 above; those only control the concluding error message, if any.</p>")

(defxdoc make-event-example
  :parents (make-event)
  :short "An example use of @(tsee make-event)"
  :long "<p>Here, we develop a reasonably self-contained example showing how to
 use @('make-event').  Although the documentation for @(tsee make-event) is
 comprehensive, some may find this example to be a good starting point, to get
 a sense of how to develop tools that take advantage of @('make-event').  We
 thank Yan Peng for putting forward this problem.</p>

 <p>We begin by discussing prerequisites for this presentation.  Next, we
 present the challenge problem, followed by code that solves the problem
 together with an example that illustrates its use.  Finally, we start from the
 beginning and show how to develop the solution step-by-step.</p>

 <h3>Prerequisites</h3>

 <p>We assume some general ACL2 and Common Lisp background, including
 familiarity with @(see macros) and backquote.  But we do some programming
 below that goes beyond that general background in our use of the ACL2 @(see
 state).  See @(see programming-with-state) for relevant discussion, including
 state global variables, @(tsee f-get-global), @(tsee f-put-global), @(see
 error-triple)s and their construction using @('value'), @(tsee value-triple),
 and @(tsee pprogn).  We also assume familiarity with both @(tsee progn) and
 the notion of legal event form; see @(see embedded-event-form).  If you are
 not familiar with these notions, then the discussion below might still make
 some sense, but you might need to read about these notions in order to
 complete your understanding.</p>

 <p>Next, we present the challenge problem that we will solve below.</p>

 <h3>Challenge problem</h3>

 <blockquote><p>Define a utility that evaluates a given sequence of
 @(see events), even continuing past errors, which stores the list of event
 forms that caused errors.</p></blockquote>

 <p>Let us call this utility @('progn+'), since it can be viewed as an
 enhancement of @(tsee progn).  So a successful solution should allow us to
 evaluate the following form to define function symbols @('f1'), @('f2'), and
 @('f3'), as well as the event @('good-thm'), and also store the events for
 @('bad-thm') and @('bad-fn').</p>

 @({
 (progn+ (defun f1 (x) x)
         (defthm good-thm (equal 1 1) :rule-classes nil)
         (value-triple (cw \"@@HI~%\"))
         (defthm bad-thm (equal x y) :rule-classes nil) ; error!
         (defun f2 (x) x)
         (defun bad-fn (x) y) ; error!
         (defun f3 (x) x)
         )
 })

 <p>We next present a definition of @('progn+'), together with output from the
 example displayed above.  After that we will start from the beginning and
 describe how one might develop @('progn+') from scratch.</p>

 <h3>The completed code and a test</h3>

 @({

 (defmacro save-progn+-error (x)
   `(make-event
     (pprogn (f-put-global 'progn+-errors
                           (cons ,x
                                 (f-get-global 'progn+-errors state))
                           state)
             (value '(value-triple nil)))))

 (defun progn+-fn (lst)
   (declare (xargs :guard (true-listp lst) :mode :program))
   (cond ((endp lst) nil)
         (t (cons `(make-event '(:or ,(car lst) (save-progn+-error ',(car lst))))
                  (progn+-fn (cdr lst))))))

 (defmacro progn+ (&rest lst)
   (declare (xargs :guard (and (true-listp lst)
                               lst)))
   `(progn (make-event (pprogn (f-put-global 'progn+-errors nil state)
                               (value '(value-triple nil))))
            ,@(progn+-fn lst)))

 ; Example:
 (progn+ (defun f1 (x) x)
         (defthm good-thm (equal 1 1) :rule-classes nil)
         (value-triple (cw \"@@HI~%\"))
         (defthm bad-thm (equal x y) :rule-classes nil)
         (defun f2 (x) x)
         (defun bad-fn (x) y)
         (defun f3 (x) x)
         )
 })

 <p>After running the example (which is the final form above), we expect the
 resulting logical @(see world) to contain definitions of function symbols
 @('f1'), @('f2'), and @('f3'), as well as the event @('good-thm'), but that no
 events would be stored for @('bad-thm') or @('bad-fn').  Moreover, we expect
 that a state global variable holds the event forms for @('bad-thm') and
 @('bad-fn').  Let us check that all of these expectations are met.</p>

 @({
 ACL2 !>:pe f1
            4:x(PROGN+ (DEFUN F1 # ...)
                       (DEFTHM GOOD-THM # ...)
                       ...)
               \
 >L             (DEFUN F1 (X) X)
 ACL2 !>:pe f2
            4:x(PROGN+ (DEFUN F1 # ...)
                       (DEFTHM GOOD-THM # ...)
                       ...)
               \
 >L             (DEFUN F2 (X) X)
 ACL2 !>:pe f3
            4:x(PROGN+ (DEFUN F1 # ...)
                       (DEFTHM GOOD-THM # ...)
                       ...)
               \
 >L             (DEFUN F3 (X) X)
 ACL2 !>(@ progn+-errors) ; same as (f-get-global 'progn+-errors state)
 ((DEFUN BAD-FN (X) Y)
  (DEFTHM BAD-THM (EQUAL X Y)
          :RULE-CLASSES NIL))
 ACL2 !>
 })

 <h3>Development of the solution</h3>

 <p>We now start from the beginning.  Recall that @(tsee progn) does almost
 what we ask @('progn+') to do, except that @(tsee progn) stops at the first
 error.  So our approach will be to define a macro that is much like
 @('progn'), except that each event is modified as follows: if evaluation fails
 for an event, then that event is pushed onto the value of a specific state
 global (see @(see programming-with-state)), @('progn+-errors').  Moreover,
 since @(tsee progn) is applied only to legal event forms (see @(see
 embedded-event-form)), we need this modification to be a legal event form,
 too.  Fortunately, a call of @(tsee make-event) is a legal event form.  So our
 plan is for @('(progn+ ... <event> ...)') to expand to a call @('(progn
 ... (make-event ...) ...)') so that the indicated @('make-event') call
 attempts to evaluate @('<event>'), and if that attempt fails, then
 @('<event>') it is pushed onto @('progn+-errors').</p>

 <p>Thus, we begin with a simple piece of the task, by showing how to create an
 event that will push a specific form, @('(defthm bad-thm (equal x
 y) :rule-classes nil)'), onto @('progn+-errors').</p>

 @({
 (make-event
  (pprogn (f-put-global 'progn+-errors
                        (cons '(defthm bad-thm (equal x y) :rule-classes nil)
                              (f-get-global 'progn+-errors state))
                        state)
          (value '(value-triple nil))))
 })

 <p>It might seem more natural to write @('(f-put-global ...)'), instead of the
 more complex @('(pprogn (f-put-global ...) (value '(value-triple nil)))').
 However, the argument to @('make-event') must evaluate to either: (1) a legal
 event form; or (2) an @(see error-triple), @('(mv nil x state)'), where @('x')
 is a legal event form.  Since the @('f-put-global') call modifies state, (1)
 is not an option; so we choose (2).  Since the role of @('x') is only to
 provide an event form, we choose @('x') to be the trivial event form
 @('(value-triple nil)').</p>

 <p>We follow good programming practice by wrapping the functionality displayed
 above into a concise utility, as follows.</p>

 @({
 (defmacro save-progn+-error (x)
 ; Push x (which is evaluated) onto the value of state global 'progn+-errors.
   `(make-event
     (pprogn (f-put-global 'progn+-errors
                           (cons ,x
                                 (f-get-global 'progn+-errors state))
                           state)
             (value '(value-triple nil)))))
 })

 <p>Before we write @('progn+'), it helps to approximate its expansion in the
 specific ``Example'' displayed above.  We know in advance which two forms will
 fail, so we `cheat' by using @('progn') but with those two forms replaced by
 calls to @('save-progn+-error').</p>

 @({
 (f-put-global 'progn+-errors nil state)
 (progn  (defun f1 (x) x)
         (defthm good-thm (equal 1 1) :rule-classes nil)
         (value-triple (cw \"@@HI~%\"))
         (save-progn+-error
          '(defthm bad-thm (equal x y) :rule-classes nil))
         (defun f2 (x) x)
         (save-progn+-error
          '(defun bad-fn (x) y))
         (defun f3 (x) x)
         )
 })

 <p>Our next task is to find a way to tell ACL2 that it should run a given
 event, and if that event fails it should save it using @('save-progn+-error').
 Fortunately, the @(':OR') keyword of @(tsee make-event) is perfect for this
 task.  Consider the following two examples.</p>

 @({
 (make-event '(:or (defun f2 (x) x)
                   (save-progn+-error '(defun f2 (x) x))))

 (make-event '(:or (defun bad-fn (x) y)
                   (save-progn+-error '(defun bad-fn (x) y))))
 })

 <p>In the first example, @('make-event') invokes the given call of @(tsee
 defun), which runs without error; and @('make-event') then exits without
 error.  In the second example, @('make-event') invokes the given call of
 @('defun'), which causes an error; so then @('make-event') evaluates the
 second argument of the @(':OR'), to invoke @('save-progn+-error') on that same
 @('defun') call.  Since that call of @('save-progn+-error') evaluates without
 error (because it expands to @('(value-triple nil)')), the @('make-event')
 call exits without error.  See @(see make-event) for more information about
 the @(':OR') keyword.</p>

 <p>We can now define @('progn+') to be the result of modifying each of its
 forms as in the two examples displayed just above.  First we write a function
 that transforms a list by applying that modification to each of its
 members.</p>

 @({
 (defun progn+-fn (lst)
   (declare (xargs :guard (true-listp lst) :mode :program))
   (cond ((endp lst) nil)
         (t (cons `(make-event '(:or ,(car lst) (save-progn+-error ',(car lst))))
                  (progn+-fn (cdr lst))))))
 })

 <p>We complete our definition of @('progn+'), by generating a @('progn') call
 with the desired modification of each form in the list, using @('progn+-fn')
 &mdash; but preceded by yet another @('make-event') call, this one for
 initializing our state global to @('nil').</p>

 @({
 (defmacro progn+ (&rest lst)
   (declare (xargs :guard (and (true-listp lst)
                               lst)))
   `(progn (make-event (pprogn (f-put-global 'progn+-errors nil state)
                               (value '(value-triple nil))))
            ,@(progn+-fn lst)))
 })

 <p><b>Exercise</b>: Modify this tool so that instead of merely updating a
 state global, it prints the failed events at the end of execution; and
 moreover, it prints them in their original order.  See @(see
 make-event-example-exercise) for a solution.</p>")

(defxdoc make-event-example-exercise
  :parents (make-event-example)
  :short "Solution to an exercise from @(tsee make-event-example)"
  :long "<p>See @(see make-event-example) for a worked example using @(tsee
 make-event), concluding with an exercise.  Here we present a solution to that
 exercise.  It assumes that we have evaluated the definitions of
 @('save-progn+-error'), @('progn+-fn'), and @('progn+') from @(see
 make-event-example).</p>

 @({
 (defmacro progn+-errors (&rest lst)
   (declare (xargs :guard (and (true-listp lst)
                               lst)))
   `(progn (progn+ ,@lst)
           (make-event
            (list 'value-triple
                  (list 'quote
                        (reverse (f-get-global 'progn+-errors state)))))))
 })")

(defxdoc make-fast-alist
  :parents (fast-alists acl2-built-ins)
  :short "@('(make-fast-alist alist)') creates a fast-alist from the input
alist, returning @('alist') itself or, in some cases, a new object equal to
it."
  :long "<p>Note: it is often better to use @('with-fast-alist'); see @(see
 with-fast-alist).</p>

 <p>Logically, @('make-fast-alist') is the identity function.</p>

 @(def make-fast-alist)

 <p>Under the hood, we construct and return an object that is @('equal') to
 @('alist') and which is a fast alist.  If @('alist') is already a fast alist,
 almost no work is required: we simply return it unchanged.</p>

 <p>When @('alist') is not fast, we must minimally construct a hash table for
 its bindings.  It is often possible to bind this new hash table to @('alist')
 itself.  But in certain cases when the alist keys are not @(see normed), a new
 alist must be constructed, also, and so we may return an @('equal') but not
 @('eq') alist.  (In these cases, we still try to avoid at least some consing
 by reusing the \"longest normed tail\" of the alist.)</p>")

(defxdoc make-list
  :parents (lists acl2-built-ins)
  :short "Make a list of a given size"
  :long "<p>For a nonnegative integer @('size'), @('(Make-list size)') is a
 list of elements of length @('size'), each of which is initialized to the
 @(':initial-element') (which defaults to @('nil')).</p>

 <p>@('Make-list') is a macro in ACL2, defined in terms of a tail recursive
 function @('make-list-ac') whose @(see guard) requires @('size') to be a
 nonnegative integer.  @('Make-list') is a Common Lisp function.  See any
 Common Lisp documentation for more information.</p>

 @(def make-list)
 @(def make-list-ac)")

(defxdoc make-ord
  :parents (ordinals acl2-built-ins)
  :short "A constructor for ordinals."
  :long "<p>@('Make-ord') is the ordinal constructor.  Its use is recommended
 instead of using @(tsee cons) to make ordinals.  For a discussion of ordinals,
 see @(see ordinals).</p>

 <p>For any ordinal, @('alpha < epsilon-0'), there exist natural numbers @('p')
 and @('n'), positive integers @('x1, x2, ..., xn') and ordinals @('a1 > a2 >
 ... > an > 0') such that @('alpha > a1') and @('alpha = w^(a1)x1 + w^(a2)x2 +
 ... + w^(an)xn + p').  We call @('a1') the ``first exponent'', @('x1') the
 ``first coefficient'', and the remainder @('(w^(a2)x2 + ... + w^(an)xn + p)')
 the ``rest'' of alpha.</p>

 <p>@('(Make-ord fe fco rst)') corresponds to the ordinal @('(w^fe)fco + rst').
 Thus the first infinite ordinal, @('w') (@('omega')), is constructed by</p>

 @({
  (make-ord 1 1 0)
 })

 <p>and, for example, the ordinal @('(w^2)5 + w2 + 7') is constructed by:</p>

 @({
  (make-ord 2 5 (make-ord 1 2 7)) .
 })

 <p>The reason @('make-ord') is used rather than @(tsee cons) is that it allows
 us to reason more abstractly about the ordinals, without having to worry about
 the underlying representation.</p>

 @(def make-ord)")

(defxdoc make-tau-interval
  :parents (tau-system acl2-built-ins)
  :short "Make a tau interval"
  :long "@({
  General Form:
  (make-tau-interval doc lo-rel lo hi-rel hi)
 })

 <p>An interval is a structure of the form: @('(')<i>dom</i>
 @('(')<i>lo-rel</i> @('.')  <i>lo</i>@(')') @('.')  @('(')<i>hi-rel</i> @('.')
 <i>hi</i>@('))').  Every tau contains an interval used to represent the
 domain, the upper, and the lower bounds of the objects recognized by the
 tau.</p>

 <p>@('make-tau-interval') constructs well-formed intervals only if its five
 arguments satisfy certain restrictions given below.  When these restrictions
 are violated @('make-tau-interval') can construct objects that are not
 intervals!  @('make-tau-interval') does not attempt to coerce or adjust its
 arguments to make well-formed intervals.</p>

 <p>For examples of intervals (and non-intervals!) constructed by
 @('make-tau-interval') see @(tsee tau-intervalp).  For examples of what
 objects are contained in certain intervals, see @(tsee in-tau-intervalp).</p>

 <p>The components of an interval are as follows:</p>

 <p><i>Dom</i> (``domain'') must be one of four symbols: @('INTEGERP'),
 @('RATIONALP'), @('ACL2-NUMBERP'), or @('NIL') denoting no restriction on the
 domain.</p>

 <p>The two ``relations,'' <i>lo-rel</i> and <i>hi-rel</i> are Booleans, where
 @('t') denotes less-than inequality (@(tsee <)) and @('nil') represents
 less-than-or-equal inequality (@(tsee <=)).  Think of @('t') meaning
 ``strong'' and @('nil') meaning ``weak'' inequality.</p>

 <p><i>Lo</i> and <i>hi</i> must be either @('nil') or explicit rational
 numbers.  If <i>lo</i> is @('nil') it denotes negative infinity; if <i>hi</i>
 is @('nil') it denotes positive infinity.  <i>Lo</i> must be no greater than
 <i>hi</i>.  <i>Note</i>: Even though @('ACL2-NUMBERP') intervals may contain
 complex rationals, the <i>lo</i> and <i>hi</i> bounds must be rational.  This
 is an arbitrary decision made by the implementors to simplify coding.</p>

 <p>Finally, if the <i>dom</i> is @('INTEGERP'), then both relations should be
 weak and <i>lo</i> and <i>hi</i> must be integers when they are
 non-@('nil').</p>

 <p>For <i>x</i> to be ``in'' an interval it must be of the type described by
 the domain predicate <i>dom</i>, <i>lo</i> must be smaller than <i>x</i> in
 the strong or weak sense denoted by <i>lo-rel</i>, and <i>x</i> must be
 smaller than <i>hi</i> in the strong or weak sense denoted by
 <i>hi-rel</i>.</p>

 <p>The components of an interval may be accessed with the functions @(tsee
 tau-interval-dom), @(tsee tau-interval-lo-rel), @(tsee tau-interval-lo),
 @(tsee tau-interval-hi-rel), and @(tsee tau-interval-hi).</p>")

(defxdoc make-wormhole-status
  :parents (wormhole)
  :short "Creates a wormhole status object from given status, entry code, and data"
  :long "@({
  General Form:  (make-wormhole-status whs code data)
 })

 <p>See @(see wormhole).  @('Whs') should be a well-formed wormhole status,
 @('code') should be @(':ENTER') or @(':SKIP'), and @('data') is arbitrary.
 This function returns a new status with the specified entry code and data,
 reusing @('whs') if it is appropriate.</p>")

(defxdoc making-system-changes
  :parents (system-development)
  :short "Guidelines for modifying ACL2 source code"
  :long "<p>ACL2 is maintained solely by Matt Kaufmann and J Moore, although
 for some time they have occasionally vetted code written by others, ultimately
 incorporating it into the system.  Although this is anticipated to remain the
 case for the foreseeable future, a process is underway towards gradually
 turning maintenance over to some other small group of trusted, reliable,
 responsible people.  This documentation topic was motivated by the desire to
 begin to support the eventual development of such a group.  Here we suggest
 steps for making changes to the ACL2 source code.</p>

 <p>(Of course, given the permissive license of ACL2, anyone is allowed to
 modify a copy of its source code.  Here we are talking about what is generally
 called ``ACL2'', which is distributed from github and from the University of
 Texas at Austin.)</p>

 <p>NOTE: See also @(see system-development-hints) for additional helpful hints
 for ACL2 development, and see @(see system-style-guide) for style
 conventions.</p>

 <p>Before you start, you should already be on the @('acl2-devel') mailing
 list.  If not, and if you are a reasonably experienced ACL2 user (a necessary
 prerequisite), you may email Matt Kaufmann with a request to be added.  If you
 are on that list and you want to work towards contributing a patch, we suggest
 that you send email to the list, explaining what you have in mind.  This will
 avoid duplication and also provide an opportunity for feedback.  In
 particular, if you desire that your work will ultimately be incorporated into
 the ACL2 system, you may want to wait for confirmation from Matt and J that at
 least one of them will be willing to review your patch; otherwise they make no
 commitment to do so.</p>

 <p>The first step is to create a patch file, which here we call
 @('patch.lisp').  It will typically have the following shape.</p>

 @({
 ;;; Github commit hash as of your starting ACL2 version (see below)

 ;;; Comments at the top (perhaps an email thread with a request for the
 ;;; change)

 (redef+)

 <your code>

 (redef-)
 (reset-prehistory) ; optional
 })

 <p>The reason to record the github commit hash is to enable Matt and J can
 correctly merge in your changes even after there have been several ACL2
 commits.  You can get that hash by running the following command under the
 main ACL2 directory.</p>

 @({
 git rev-parse HEAD
 })

 <p>Next, start copying into @('patch.lisp') source functions that you want to
 modify.  (It is helpful for this process to use @('meta-.') in Emacs.)  It is
 often best to keep the functions in order: if @('f') calls @('g') and both are
 defined (or redefined) in @('patch.lisp'), then the definition of @('g')
 should precede the definition of @('f') in @('patch.lisp').</p>

 <p>Now modify those source functions and write any additional supporting
 functions that you need.  Try to use existing source functions when possible.
 perhaps finding them by using the Emacs command, @('meta-x tags-apropos').
 For example, to find a function that concatenates a list of strings, you could
 run @('meta-x tags-apropos append') and then search for @('string') in the
 resulting display; you would find @('string-append-lst'), and you could run
 the Emacs command @('meta-.') on that word in order to find its definition in
 the sources, to see if it has the desired functionality.</p>

 <p>If there are further changes you wish to make to the ACL2 source code which
 are not of the form of function definitions or redefinitions &mdash; for
 example, if you want to add or modify a top-level comment, put some of the new
 functions in a particular file or a newly created file, etc. &mdash; then feel
 free to add instructions that reflect your intent in comments in
 @('patch.lisp'), within reason.  We will be reading over @('patch.lisp')
 manually, so human-directed comments are welcome &mdash; the exact format of
 @('patch.lisp') is not rigid.</p>

 <p>Test your patch by starting ACL2 and evaluating the following form in the
 loop (but see below for an exception).  The use of @(':ld-pre-eval-print') is
 optional, but can be helpful when debugging since it prints each form before
 evaluating it.</p>

 @({
 (ld \"patch.lisp\" :ld-pre-eval-print t)
 })

 <p>EXCEPTION: the form above may not work if your patch file has any
 occurrences of the @('acl2-loop-only') readtime conditional (preceded either
 by @('#+') or by @('#-')).  In that case, do the following instead.  NOTE: if
 you are making changes that affect definition processing, then you may need to
 switch the order: first @('load'), then after @('(LP!)'), run @('ld').</p>

 @({
 :q
 (LP!)
 (ld \"patch.lisp\" :ld-pre-eval-print t)
 :q
 (load \"patch.lisp\") ; only needed if #-acl2-loop-only occurs in patch.lisp
 (LP)
 })

 <p>Remark (only rarely to be considered).  If efficiency is a concern and you
 are using a Lisp implementation that does not compile on-the-fly (as of this
 writing, that includes Lisps other than CCL and SBCL), then put
 @('(set-compile-fns t)') near the top of @('patch.lisp'), and replace @('(load
 \"patch.lisp\")') just above by the following (perhaps first adding
 @('(in-package \"ACL2\")') at the top of @('patch.lisp')):</p>

 @({
 (load \"patch.lisp\")
 (compile-file \"patch.lisp\")
 (load \"patch\")
 })

 <p>Now test your patch.  A quick test could be the following.</p>

 @({
 (mini-proveall) ; should complete normally
 (ubt! 1) ; back to just after reset-prehistory was evaluated
 })

 <p>You might also want to do your own tests.  In some cases, you could even
 add a book of tests in directory @('books/system/tests/').  If the change was
 inspired by problems with a specific event in an existing book, the following
 can be useful.</p>

 @({
 (ld \"foo.port\")
 (rebuild \"foo.lisp\" t)
 :ubt <bad-event-name>
 <bad-event>
 })

 <p>When you are satisfied that all is well, take your copy of ACL2 and install
 the patches: for each system function redefined in patch.lisp, replace the
 definition in your copy of the ACL2 sources with the redefinition, preceded by
 new supporting definitions as necessary.  Then in your acl2-sources directory,
 build the system, for example:</p>

 @({
 make LISP=<path_to_your_lisp> >& make.log
 })

 <p>Check the log to see if the build seems to have completed normally, in
 particular with ``Initialization SUCCEEDED'' printed near the end of the log.
 It is a good idea to do case-insensitive searches for the string,
 \"compiler\", if the Lisp is CCL (you should find four occurrences, all of
 them SET-COMPILER-ENABLED) and for \"warning:\" for the other Lisp
 implementations (you should find no occurrences).</p>

 <p>Now do a regression.  The most complete regression might be done with a
 command like the following in the ACL2 sources directory; it could take a few
 hours (perhaps 3 or 4 hours, depending on the Lisp and the machine).</p>

 @({
 make clean-books ; \\
 (time nice make -j 8 regression-everything USE_QUICKLISP=1) \\
   >& make-regression-everything-ccl-quicklisp-j-8.log&
 })

 <p>Be sure to document your changes.  This will typically involve adding a
 release note to a topic like @(see note-8-0).  The XDOC source code
 documentation resides in the community book
 @('books/system/doc/acl2-doc.lisp').  If the change is minor, for example a
 tweak to an error message, a Lisp comment in the corresponding @('defxdoc')
 form is probably best; the existing @('(defxdoc note-xxx ...)') forms can
 provide guidance on this.  Be sure to keep the @(see XDOC) documentation at a
 user level, not at the level of the implementation.  Also be sure to comment
 your code well with Lisp comments.  Ultimately you should also update ACL2
 source file @('doc.lisp'), which is a generated file based on
 @('books/system/doc/acl2-doc.lisp').  Be careful regarding the constant @(tsee
 *acl2-exports*)!  See the ``WARNING'' comment in the definition of
 @('*acl2-exports*').</p>

 <p>Now feel free to send all changed files and also the starting git commit
 hash (or even the entire patch file, too) to whoever has offered to look at
 your patch!</p>")

(defxdoc managing-acl2-packages
  :parents (packages)
  :short "User-contributed documentation on packages"
  :long "<p>Jared Davis has contributed documentation on <a
  href='http://www.cs.utexas.edu/users/moore/acl2/contrib/managing-acl2-packages.html'>managing
  ACL2 packages</a>.</p>

  <p>Also see @(see working-with-packages).</p>")

(defxdoc max
  :parents (numbers acl2-built-ins)
  :short "The larger of two numbers"
  :long "<p>@('(Max x y)') is the larger of the numbers @('x') and @('y').</p>

 <p>The @(see guard) for @('max') requires its arguments to be rational (@(see
 real), in ACL2(r)) numbers.</p>

 <p>@('Max') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def max)")

(defxdoc maximum-length
  :parents (arrays acl2-built-ins)
  :short "Return the @(':maximum-length') from the @(see header) of an array"
  :long "@({
  Example Form:
  (maximum-length 'delta1 a)

  General Form:
  (maximum-length name alist)
 })

 <p>where @('name') is an arbitrary object and @('alist') is a 1- or
 2-dimensional array.  This function returns the contents of the
 @(':maximum-length') field of the @(see header) of @('alist').  Whenever an
 @(tsee aset1) or @(tsee aset2) would cause the length of the alist to exceed
 its maximum length, a @(tsee compress1) or @(tsee compress2) is done
 automatically to remove irrelevant pairs from the array.  @('Maximum-length')
 operates in virtually constant time if @('alist') is the semantic value of
 @('name').  See @(see arrays).</p>

 @(def maximum-length)")

(defxdoc mbe
  :parents (guard programming acl2-built-ins)
  :short "Attach code for execution"
  :long "<p>The macro @('mbe') (``must be equal'') can be used in function
 definitions in order to cause evaluation to use alternate code to that
 provided for the logic.  An example is given below.  However, the use of
 @('mbe') can lead to non-terminating computations.  See @(see defexec),
 perhaps after reading the present documentation, for a way to prove
 termination.</p>

 <p>In the ACL2 logic, @('(mbe :exec exec-code :logic logic-code)') equals
 @('logic-code'); the value of @('exec-code') is ignored.  However, in raw Lisp
 it is the other way around: this form macroexpands simply to @('exec-code').
 ACL2's @(see guard) verification mechanism ensures that the raw Lisp code is
 only evaluated when appropriate, since the guard proof obligations generated
 for (the macroexpansion of) this call of @('mbe') include not only the guard
 proof obligations from @('exec-code'), but also, under suitable contextual
 assumptions, the term @('(equal exec-code logic-code)').  See @(see
 verify-guards) (in particular, for discussion of the contextual assumptions
 from the @(':guard') and @(tsee IF)-tests) and, for general discussion of
 guards, see @(see guard).</p>

 <p>Normally, during evaluation of an @('mbe') call, only the @(':logic') code
 is evaluated unless the call is in the body of a @(see guard)-verified
 function or under a call of a @(':')@(tsee program) mode function; in those
 cases only the @(':exec') code is evaluated.  This implies that equality of
 @(':exec') and @(':logic') code is never checked at runtime. (Rather, such
 equality is proved when verifying guards.)  We qualified with ``normally''
 above because there are two exceptions.  During a ``safe mode'', which is used
 in macroexpansion and evaluation of @(tsee defconst) forms, the @(':logic')
 and @(':exec') code are both evaluated and their equality is checked.  Second,
 when guard-checking is set to @(':all') or @(':none'), then for any @('mbe')
 call in the body of a @(':logic') mode definition, only the @(':logic') code
 will be evaluated.</p>

 <p>Note that the @(':exec') and the @(':logic') code in an @('mbe') call must
 have the same output signature.  For example, one cannot return @('(')@(tsee
 mv)@(' * *)') while the other returns just a single value.</p>

 <p>Also see @(see mbt), which stands for ``must be true.''  You may find it
 more natural to use @(tsee mbt) for certain applications, as described in its
 @(see documentation).</p>

 <p>Here is an example of the use of @('mbe').  Suppose that you want to define
 factorial in the usual recursive manner, as follows.</p>

 @({
  (defun fact (n)
    (if (zp n)
        1
      (* n (fact (1- n)))))
 })

 <p>But perhaps you want to be able to execute calls of @('fact') on large
 arguments that cause stack overflows, perhaps during proofs.  (This isn't a
 particularly realistic example, but it should serve.)  So, instead you can
 define this tail-recursive version of factorial:</p>

 @({
  (defun fact1 (n acc)
    (declare (xargs :guard (and (integerp n) (>= n 0) (integerp acc))))
    (if (zp n)
        acc
      (fact1 (1- n) (* n acc))))
 })

 <p>We are now ready to define @('fact') using @('mbe').  Our intention is that
 logically, @('fact') is as shown in the first definition above, but that
 @('fact') should be executed by calling @('fact1').  Notice that we defer
 @(see guard) verification, since we are not ready to prove the correspondence
 between @('fact1') and @('fact').</p>

 @({
  (defun fact (n)
    (declare (xargs :guard (and (integerp n) (>= n 0))
                    :verify-guards nil))
    (mbe :exec  (fact1 n 1)
         :logic (if (zp n)
                    1
                  (* n (fact (1- n))))))
 })

 <p>Next, we prove the necessary correspondence lemmas.  Notice the inclusion
 of a community book to help with the arithmetic reasoning.</p>

 @({
  (include-book \"arithmetic/top-with-meta\" :dir :system)

  (defthm fact1-fact
    (implies (integerp acc)
             (equal (fact1 n acc)
                    (* acc (fact n)))))
 })

 <p>We may now do guard verification for @('fact'), which will allow the
 execution of the raw Lisp @('fact') function, where the above @('mbe') call
 expands simply to @('(fact1 n 1)').</p>

 @({
  (verify-guards fact)
 })

 <p>Now that guards have been verified, a trace of function calls illustrates
 that the evaluation of calls of @('fact') is passed to evaluation of calls of
 @('fact1').  The outermost call below is of the logical function stored for
 the definition of @('fact'); all the others are of actual raw Common Lisp
 functions.</p>

 @({
  ACL2 !>(trace$ fact fact1)
  NIL
  ACL2 !>(fact 3)
  1> (ACL2_*1*_ACL2::FACT 3)
    2> (FACT 3)
      3> (FACT1 3 1)
        4> (FACT1 2 3)
          5> (FACT1 1 6)
            6> (FACT1 0 6)
            <6 (FACT1 6)
          <5 (FACT1 6)
        <4 (FACT1 6)
      <3 (FACT1 6)
    <2 (FACT 6)
  <1 (ACL2_*1*_ACL2::FACT 6)
  6
  ACL2 !>
 })

 <p>You may occasionally get warnings when you compile functions defined using
 @('mbe').  (For commands that invoke the compiler, see @(see compilation).)
 These can be inhibited by using an @('ignorable') @(tsee declare) form.  Here
 is a simple but illustrative example.  Note that the declarations can
 optionally be separated into two @(tsee declare) forms.</p>

 @({
  (defun foo (x y)
    (declare (ignorable x)
             (xargs :guard (equal x y)))
    (mbe :logic x :exec y))
 })

 <p>Finally, we observe that when the body of a function contains a term of the
 form @('(mbe :exec exec-code :logic logic-code)'), the user would be unlikely
 to notice any difference in the theorem prover if this term were replaced by
 @('logic-code').  ACL2 takes various steps to ensure this.  For example, the
 proof obligations generated for admitting a function treat the above @('mbe')
 term simply as @('logic-code').  Function expansion, @(':use') @(see hints),
 @(':')@(tsee definition) rules, generation of @(see constraint)s for
 functional instantiation, and creation of rules of class @(':')@(tsee rewrite)
 and @(':')@(tsee forward-chaining) also treat @('mbe') calls as their
 @(':logic') code.</p>")

(defxdoc mbe1
  :parents (mbe acl2-built-ins)
  :short "Attach code for execution"
  :long "<p>The form @('(mbe1 exec logic)') is equivalent to the forms
 @('(mbe :logic logic :exec exec)') and @('(must-be-equal logic exec)').  See
 @(see mbe).</p>")

(defxdoc mbt
  :parents (mbe acl2-built-ins)
  :short "Introduce a test into the logic that, however, evaluates to @('t')"
  :long "<p>The macro @('mbt') (``must be true'') can be used in order to add
 code in order to admit function definitions in @(':')@(tsee logic) mode,
 without paying a cost in execution efficiency.  Examples below illustrate its
 intended use.</p>

 <p>Semantically, @('(mbt x)') equals @('x').  However, in raw Lisp @('(mbt
 x)') ignores @('x') entirely, and macroexpands to @('t').  ACL2's @(see guard)
 verification mechanism ensures that the raw Lisp code is only evaluated when
 appropriate, since a guard proof obligation @('(equal x t)') is generated.
 See @(see verify-guards) and, for general discussion of guards, see @(see
 guard).</p>

 <p>Also see @(see mbe), which stands for ``must be equal.''  Although @('mbt')
 is more natural in many cases, @('mbe') has more general applicability.  In
 fact, @('(mbt x)') is essentially defined to be @('(mbe :logic x :exec
 t)').  Another related utility is @(tsee mbt*), which generates the same proof
 obligation as @('mbt') but logically, is simply @('t').</p>

 <p>We can illustrate the use of @('mbt') on the following generic example,
 where @('<g>'), @('<test>'), @('<rec-x>'), and @('<base>') are intended to be
 terms involving only the variable @('x').</p>

 @({
  (defun foo (x)
    (declare (xargs :guard <g>))
    (if <test>
        (foo <rec-x>)
      <base>))
 })

 <p>In order to admit this function, ACL2 needs to discharge the proof
 obligation that @('<rec-x>') is smaller than @('x'), namely:</p>

 <code>
 (implies &lt;test&gt;
          (o&lt; (acl2-count @('<rec-x>'))
               (acl2-count x)))
 </code>

 <p>But suppose we need to know that @('<g>') is true in order to prove this.
 Since @('<g>') is only the @(see guard), it is not part of the logical
 definition of @('foo').  A solution is to add the guard to the definition of
 @('foo'), as follows.</p>

 @({
  (defun foo (x)
    (declare (xargs :guard <g>))
    (if (mbt <g>)
        (if <test>
            (foo <rec-x>)
          <base>)
      nil))
 })

 <p>If we do this using @('<g>') rather than @('(mbt <g>)'), then evaluation of
 every recursive call of @('foo') will cause the evaluation of (the appropriate
 instance of) @('<g>').  But since @('(mbt <g>)') expands to @('t') in raw
 Lisp, then once we verify the guards of @('foo'), the evaluations of @('<g>')
 will be avoided (except at the top level, when we check the guard before
 allowing evaluation to take place in Common Lisp).</p>

 <p>Other times, the guard isn't the issue, but rather, the problem is that a
 recursive call has an argument that itself is a recursive call.  For example,
 suppose that @('<rec-x>') is of the form @('(foo <expr>)').  There is no way
 we can hope to discharge the termination proof obligation shown above.  A
 standard solution is to add some version of this test:</p>

 <code>
 (mbt (o&lt; (acl2-count @('<rec-x>')) (acl2-count x))) </code>

 <p>Here is a specific example based on one sent by Vernon Austel.</p>

 @({
  (defun recurX2 (n)
    (declare (xargs :guard (and (integerp n) (<= 0 n))
                    :verify-guards nil))
    (cond ((zp n) 0)
          (t (let ((call (recurX2 (1- n))))
               (if (mbt (< (acl2-count call) n))
                   (recurX2 call)
                 1 ;; this branch is never actually taken
                 )))))

  (defthm recurX2-0
   (equal (recurX2 n) 0))

  (verify-guards recurX2)
 })

 <p>If you @('(')@(tsee trace$)@(' acl2-count)'), you will see that evaluation
 of @('(recurX2 2)') causes several calls of @(tsee acl2-count) before the
 @(tsee verify-guards).  But this evaluation does not call @('acl2-count')
 after the @('verify-guards'), because the ACL2 evaluation mechanism uses raw
 Lisp to do the evaluation, and the form @('(mbt (< (acl2-count call) n))')
 macroexpands to @('t') in Common Lisp.</p>

 <p>You may occasionally get warnings when you compile functions defined using
 @('mbt').  (For commands that invoke the compiler, see @(see compilation).)
 These can be inhibited by using an @('ignorable') @(tsee declare) form.  Here
 is a simple but illustrative example.  Note that the declarations can
 optionally be separated into two @(tsee declare) forms.</p>

 @({
  (defun foo (x y)
    (declare (ignorable x)
             (xargs :guard (equal x t)))
    (and (mbt x) y))
 })")

(defxdoc mbt*
  :parents (mbe acl2-built-ins)
  :short "Introduce a guard proof obligation"
  :long "<p>The macro @('mbt*') is a variant of @('mbt') (``must be true'').
 However, unlike @('mbt'), the call @('(mbt* test)') is equivalent simply to
 @('t') for both logic and evaluation.  The only effective difference between
 @('(mbt* test)') and @('t') is that @('(mbt* test)') generates a @(see guard)
 proof obligation (when used in a @(tsee logic)-mode definition) of
 @('test').</p>

 <p>If you think that @('mbt*') might be of use, please see @(see assert*),
 which is defined using @('mbt*') to create a @(see guard) proof obligation
 without any logical or execution burden.</p>")

(defxdoc measure

; This topic is appropriately redefined by (define measure ...) in
; books/kestrel/utilities/world-queries.lisp:

  :parents (xargs)
  :short "Declare a measure for a @(tsee defun)"
  :long "<p>See @(see xargs) for discussion of how to use the @(':measure')
 keyword to specify a measure for a definition.  A related utility,
 @('measure'), may be found in the @(see community-books), file
 @('kestrel/utilities/world-queries.lisp').</p>")

(defxdoc measure-debug
  :parents (measure debugging)
  :short "Generate markers to indicate sources of @(see measure) proof obligations"
  :long "<p>When ACL2 is asked to accept a recursive (or mutually recursive)
 function definition, it generates a goal often called the ``measure
 conjecture.''  That goal can split into numerous goals, some of which may not
 be theorems if the definition being processed has bugs.  This @(see
 documentation) topic explains a capability provided by ACL2 to help find such
 bugs.  For a similar utility appropriate for @(see guard) verification, see
 @(see guard-debug).</p>

 <p>We begin with the following simple, admittedly artificial, example.</p>

 @({
 (defun f (x)
   (if (consp x)
       (f (cons x x))
     x))
 })

 <p>ACL2 generates the following proof obligation..</p>

 @({
 (IMPLIES (CONSP X)
          (O< (ACL2-COUNT (CONS X X))
              (ACL2-COUNT X)))
 })

 <p>In this simple example, it is obvious that ACL2 cannot prove the goal
 because in fact, @('(CONS X X)') does not have a smaller @(tsee acl2-count)
 than @('X'), even assuming @('(CONSP X)').  But you can get ACL2 to show
 explicitly the source of this proof obligation by specifying @(':measure-debug
 t') in an @(tsee xargs) @(tsee declare) form, as follows.</p>

 @({
 ACL2 !>(defun f (x)
          (declare (xargs :measure-debug t))
          (if (consp x)
              (f (cons x x))
            x))

 For the admission of F we will use the relation O< (which is known
 to be well-founded on the domain recognized by O-P) and the measure
 (ACL2-COUNT X).  The non-trivial part of the measure conjecture is

 Goal
 (IMPLIES (AND (EXTRA-INFO '(:MEASURE (:RELATION F))
                           '(F (CONS X X)))
               (CONSP X))
          (O< (ACL2-COUNT (CONS X X))
              (ACL2-COUNT X))).
 })

 <p>The @('extra-info') call is telling us the following about the
 <b>measure</b> conjecture:</p>

 <blockquote>The appropriate well-founded <b>relation</b> (typically @(tsee
 o<)) holds between appropriate terms, because of the indicated recursive call,
 @('(F (CONS X X))').</blockquote>

 <p>We now describe the measure-debug utility in some detail.</p>

 <p>@('(Extra-info x y)') always returns @('t') by definition.  However, if the
 measure conjecture takes place with a non-@('nil') value for the @(tsee xargs)
 keyword @(':measure-debug'), then the goals generated will include hypotheses
 that are calls of @('extra-info').  Such a hypothesis has one of the following
 forms.</p>

 @({
  (extra-info '(:MEASURE (:RELATION function-name))
              'recursive-call)

  (extra-info '(:MEASURE (:DOMAIN function-name))
              '(D (M term))) })

 <p>The first form says that the goal is to show that the measure decreases for
 the indicated recursive call in the body of the function named
 @('function-name').  The second form says that the goal is to show that the
 measure always returns a suitable value.</p>

 <p>We illustrate with a slightly more elaborate, but still contrived, example,
 which we hope clearly illustrates the points above.  Notice that
 @(':measure-debug t') need only be specified for a single @(tsee defun) form
 in a call of @(tsee mutual-recursion).  Also notice in the output that when
 there is more than one source for a goal, each source is indicated by its own
 call of @('extra-info').</p>

 @({
 ACL2 !>(defstub my-measure (x) t) ; for the contrived example below
 [[ .. output omitted here .. ]]
 ACL2 !>(mutual-recursion
          (defun f1 (x)
            (declare (xargs :measure (my-measure x) :measure-debug t))
            (if (consp x)
                (f2 (cons x (cdr x)))
              t))
          (defun f2 (x)
            (declare (xargs :measure (my-measure x)))
            (if (consp x)
                (f1 (cons (make-list (car x)) (cdr x)))
              nil)))

 For the admission of F1 and F2 we will use the relation O< (which is
 known to be well-founded on the domain recognized by O-P) and the measure
 (MY-MEASURE X) for F1 and (MY-MEASURE X) for F2.  The non-trivial part
 of the measure conjecture is

 Goal
 (AND (IMPLIES (AND (EXTRA-INFO '(:MEASURE (:RELATION F1))
                                '(F2 (CONS X (CDR X))))
                    (CONSP X))
               (O< (MY-MEASURE (CONS X (CDR X)))
                   (MY-MEASURE X)))
      (IMPLIES (AND (EXTRA-INFO '(:MEASURE (:RELATION F2))
                                '(F1 (CONS (MAKE-LIST-AC (CAR X) NIL NIL)
                                           (CDR X))))
                    (CONSP X))
               (O< (MY-MEASURE (CONS (MAKE-LIST-AC (CAR X) NIL NIL)
                                     (CDR X)))
                   (MY-MEASURE X)))
      (IMPLIES (AND (EXTRA-INFO '(:MEASURE (:DOMAIN F2))
                                '(O-P (MY-MEASURE X)))
                    (EXTRA-INFO '(:MEASURE (:DOMAIN F1))
                                '(O-P (MY-MEASURE X))))
               (O-P (MY-MEASURE X)))).
 })

 <p>All rules (see @(see rune)) associated with @('extra-info') are @(see
 disable)d by default, so that hypotheses of the form described above are not
 simplified to @('t').  These hypotheses are intended to ride along for free:
 you can generally expect the proof to have the same structure whether or not
 the @(':measure-debug') option is supplied, though on rare occasions the
 proofs may diverge.</p>")

(defxdoc member
  :parents (lists acl2-built-ins)
  :short "Membership predicate"
  :long "@({
  General Forms:
  (member x lst)
  (member x lst :test 'eql)   ; same as above (eql as equality test)
  (member x lst :test 'eq)    ; same, but eq is equality test
  (member x lst :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Member x lst)') equals the longest tail of the list @('lst') that
 begins with @('x'), or else @('nil') if no such tail exists.  The optional
 keyword, @(':TEST'), has no effect logically, but provides the test (default
 @(tsee eql)) used for comparing @('x') with successive elements of
 @('lst').</p>

 <p>The @(see guard) for a call of @('member') depends on the test.  In all
 cases, the second argument must satisfy @(tsee true-listp).  If the test is
 @(tsee eql), then either the first argument must be suitable for @(tsee eql)
 (see @(see eqlablep)) or the second argument must satisfy @(tsee
 eqlable-listp).  If the test is @(tsee eq), then either the first argument
 must be a symbol or the second argument must satisfy @(tsee symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('member') and its variants:</p>

 <blockquote><p>@('(member-eq x lst)') is equivalent to @('(member x lst :test
 'eq)');</p>

 <p>@('(member-equal x lst)') is equivalent to @('(member x lst :test
 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('member-equal').</p>

 <p>@('Member') is defined by Common Lisp.  See any Common Lisp documentation
 for more information.</p>

 @(def member-equal)")

(defxdoc memoize
  :parents (programming hons-and-memoization events)
  :short "Turn on memoization for a specified function"
  :long "<p>See @(see hons-and-memoization) for a general discussion of the
 ``@(see hons-enabled)'' features: memoization, hash consing, and applicative
 hash tables.</p>

 @({
  Examples:
  (memoize 'foo)                      ; remember the values of calls
                                      ;   of foo
  (memoize 'foo :condition t)         ; same as above
  (memoize 'foo :condition '(test x)) ; memoize for args satisfying
                                      ;   the given condition
  (memoize 'foo :condition-fn 'test)  ; memoize for args satisfying
                                      ;   a call of the given function
  (memoize 'foo :recursive nil)       ; don't memoize recursive calls
  (memoize 'foo :aokp t)              ; attachments OK for stored results
  (memoize 'foo :stats nil)           ; don't collect info for (memsum)
  (memoize 'foo :ideal-okp t)         ; memoize for raw Lisp even if foo is
                                      ;   in :logic but not guard-verified

  General Form:
  (memoize fn                         ; memoizes fn and returns fn
           :condition    condition    ; optional (default t)
           :condition-fn condition-fn ; optional
           :hints        hints        ; optional, for verifying the
                                      ;   guards of condition-fn
           :otf-flg      otf-flg      ; optional, for verifying the
                                      ;   guards of condition-fn
           :recursive    t/nil        ; optional (default t)
           :commutative  t/lemma-name ; optional (default nil)
           :forget       t/nil        ; optional (default nil)
           :memo-table-init-size size ; optional (default *mht-default-size*)
           :aokp         t/nil        ; optional (default nil)
           :stats        t/nil        ; optional (default t)
           :ideal-okp    t/:warn/nil  ; optional (default nil)
           :verbose      t/nil        ; optional (default t)
           )
 })

 <p>where @('fn') evaluates to a user-defined function symbol; @('condition')
 is either @('t') (the default), @(''t'), @('nil'), or @(''nil'), or else
 evaluates to an expression whose free variables are among the formal
 parameters of @('fn'); and @('condition-fn') is either @('nil') (the default)
 or else evaluates to a legal function symbol.  Further restrictions and
 options are discussed below.  Note that all arguments are evaluated (but for
 the special handling of value @('t') for @(':commutative'), the argument must
 literally be @('t'); see below).</p>

 <p>Generally @('fn') must evaluate to a defined function symbol.  However,
 this value can be the name of a macro that is associated with such a function
 symbol; see @(see macro-aliases-table).  That associated function symbol is
 the one called ``memoized'' in the discussion below, but we make no more
 mention of this subtlety.</p>

 <p>In the most common case, @('memoize') takes a single argument, which
 evaluates to a function symbol.  We call this function symbol the ``memoized
 function'' because ``memos'' are saved and re-used, in the following sense.
 When a call of the memoized function is evaluated, the result is ``memoized''
 by associating the call's arguments with that result, in a suitable table.
 But first an attempt is made to avoid such evaluation, by doing a lookup in
 that table on the given arguments for the result, as stored for a previous
 call on those arguments.  If such a result is found, then it is returned
 without further computation.  This paragraph also applies if @(':condition')
 is supplied but is @('t') or @(''t').</p>

 <p>If keyword argument @(':condition-fn') is supplied, but @(':condition') is
 not, then the result of evaluating @(':condition-fn') must be a defined
 function symbol whose formal parameter list and @(tsee guard) are the same as
 for the function being memoized.  If @('fn') is in @(':')@(tsee logic) mode,
 then @(see guard)s must have been verified for @(':condition-fn').  Such a
 ``condition function'' will be run whenever the memoized function is called,
 on the same parameters, and the lookup or table store described above are only
 performed if the result from the condition function call is non-@('nil').</p>

 <p>Suppose however that @(':condition') is supplied.  If the value supplied is
 @('t') or @(''t'), then the lookup and table store described above are always
 done.  If the value is @('nil') or @(''nil'), then this lookup and table store
 are never done, although statistics may be gathered; see @(see profile).  Now
 consider other values for @(':condition').  An attempt will be made to define
 a condition function whose @(see guard) and formal parameters list are the
 same as those of the memoized function, and whose body is the result, @('r'),
 of evaluating the given @('condition').  The name of that condition function
 is the result of evaluating @(':condition-fn') if supplied, else is the result
 of concatenating the string @('\"-MEMOIZE-CONDITION\"') to the end of the name
 of the memoized function.  The condition function will be defined with @(see
 guard) verification turned off, but that definition will be followed
 immediately by a @(tsee verify-guards) event; and this is where the optional
 @(':hints') and @(':otf-flg') are attached.  At evaluation time the condition
 function is used as described in the preceding paragraph; so in effect, the
 condition (@('r'), above) is evaluated, with its variables bound to the
 corresponding actuals of the memoized function call, and the memoized function
 attempts a lookup or table store if and only if the result of that evaluation
 is non-@('nil').</p>

 <p>Note that @('fn') can be either a @(':')@(tsee logic) mode function or a
 @(':')@(tsee program) mode function.  However, only the corresponding raw Lisp
 function is actually memoized, so @(see guard) violations can defeat
 memoization, and @(':')@(tsee logic) mode functions without their @(see
 guard)s verified will only be memoized when called by @(':')@(tsee program)
 mode functions.  (See @(see guards-and-evaluation) for more information about
 guards and evaluation in ACL2.)  If @('fn') is a @(':')@(tsee logic) mode
 function and @(':condition') is supplied and not @('t') or @('nil'), then the
 condition must be a @(see guard)-verified function.</p>

 <p>Calls of this macro generate events of the form @('(table memoize-table fn
 ((:condition-fn fn) ...))').  When successful, the returned value is of the
 form @('(mv nil function-symbol state)').</p>

 <p>Suppose that a function is already memoized.  Then it is illegal to memoize
 that function.  Moreover, if the function was memoized with an associated
 condition (i.e., was memoized with keyword @(':condition') or
 @(':condition-fn') having value other than @('t') or @('nil')), then it is
 also illegal to convert the function from @(':')@(tsee program) to
 @(':')@(tsee logic) mode (see @(see verify-termination)).  To turn off
 memoization, see @(see unmemoize).</p>

 <p>@('Memoize') is illegal for a function if its arguments include @(tsee
 state) or if it returns any @(see stobj)s.  A stobj can be an input of a
 memoized function, but in that case, the memoization table for that stobj will
 be cleared every time that stobj is updated.</p>

 <p>By default, @('memoize') does not store results when any attachments have
 been used (see @(see defattach)).  However, such results are stored when
 @('memoize') keyword parameter @(':aokp') has value @('t').  Note that for
 purposes of this discussion, the use of a stored value for a subsidiary
 function that was memoized with @(':aokp t') is treated as the use of an
 attachment, since ACL2 does not know whether or not an attachment was actually
 used in that case.</p>

 <p>We conclude with by documenting keyword parameters not discussed above.</p>

 <p>Keyword parameter @(':recursive') is @('t') by default, which means that
 recursive calls of @('fn') will be memoized just as ``top-level'' calls of
 @('fn').  When @(':recursive') is instead set to @('nil'), memoization is only
 done at the top level.  Using @(':recursive nil') is similar to writing a
 wrapper function that just calls @('fn'), and memoizing the wrapper instead of
 @('fn').</p>

 <p>If @(':trace') has a non-@('nil') value, then @('memoize') also traces in a
 traditional Lisp style.  If @(':trace') has value @('notinline') or
 @('notinline'), then a corresponding declaration is added at the beginning of
 the new definition of @('fn').</p>

 <p>A non-@('nil') value for @(':commutative') can be supplied if @('fn') is a
 binary function in @(':logic') mode.  Suppose that the @('memoize') event is
 successful, and consider a subsequent call of @('fn') for which some argument
 to @('fn') is either a rational number or, in some host Lisps (currently
 either CCL, or GCL Version 2.6.12 or later) a @(see hons).  (Indeed, for such
 GCL versions this is true for any cons, not just a hons.)  Then when the
 evaluation of @('fn') on those arguments is memoized, the evaluation of
 @('fn') on the swap of those arguments is, in essence, also memoized.  If
 @(':commutative') is supplied and is not @('nil') or @('t'), then it should be
 the name of a previously-proved theorem whose formula states the commutativity
 of @('fn'), i.e., is the formula @('(equal (fn x y) (fn y x))') for a pair
 @('{x,y}') of distinct variables.  If @(':commutative') is @('t') &mdash; but
 not merely an expression that evaluates to @('t') &mdash; then an attempt to
 prove such a lemma will be made on-the-fly.  The name of the lemma is the
 symbol in the same package as @('fn'), obtained by adding the suffix
 @('\"-COMMUTATIVE\"') to the @(tsee symbol-name) of @('fn').  If the proof
 attempt fails, then you may want first to prove the lemma yourself with
 appropriate hints and perhaps supporting lemmas, and then supply the name of
 that lemma as the value of @(':commutative').</p>

 <p>If @(':commutative') is supplied, and a non-commutative condition is
 provided by @(':condition') or @(':condition-fn'), then although the results
 will be correct, the extra memoization afforded by @(':commutative') is
 unspecified.</p>

 <p>If @(':memo-table-init-size') is supplied, then it should be a positive
 integer specifying the initial size of an associated hash table.</p>

 <p>Argument @(':aokp') is relevant only when attachments are used; see @(see
 defattach) for background on attachments.  When @(':aokp') is @('nil'), the
 default, computed values are not stored when an attachment was used, or even
 when an attachment may have been used because a function was called that had
 been memoized using @(':aokp t').  Otherwise, computed values are always
 stored, but saved values are not used except when attachments are allowed.  To
 summarize:</p>

 @({
    aokp=nil (default): ``Pure'', i.e., values do not depend on attachments
    - Fetch: always legal
    - Store: only store resulting value when attachments were not used

    aokp=t: ``Impure'', i.e., values may depend on attachments
    - Fetch: only legal when attachments are allowed (e.g., not during proofs)
    - Store: always legal
 })

 <p>The default value for @(':stats') is essentially @('t').  (Technically,
 this can be subverted by using raw Lisp, to change the default by changing the
 values of variables @('*record-xxx*') introduced in ACL2 source file
 @('memoize-raw.lisp').)  When @(':stats') has its default value (assuming the
 above raw Lisp changes are not made) or value @('t'), calls of memoized
 functions will collect information that can be displayed by calling @(tsee
 memsum).  But if @(':stats') is @('nil'), this information will not be
 collected, possibly resulting in better performance for the memoized
 function.  As of this writing, built-in memoized functions use @(':stats nil')
 to benefit performance.</p>

 <p>If @(':ideal-okp') is supplied and not @('nil'), then it is permitted to
 memoize an ``ideal-mode'' function: one in @(':')@(tsee logic) mode whose
 @(see guard)s have not been verified.  However, this might not have the effect
 you desire, because you will be memoizing the submitted version of the
 function, not its executable-counterpart that is executed in the ACL2 loop and
 on behalf of the prover (see @(see evaluation)).  Thus, if you memoize an
 ideal-mode function and then call it at the top-level of the ACL2 loop (or,
 for example, it is called to evaluate a ground term arising in a proof or in
 the evaluation of a @(see meta)function in a proof), the effects of
 memoization will not be felt because the raw Lisp code is not run unless
 guards are verified.</p>

 <p>There are circumstances in which the raw Lisp code of an ideal-mode function
 is called.  For example, if the ideal-mode function is called by a
 @(':')@(tsee program) mode function, evaluation can transfer to raw Lisp where
 the effects of memoization will be felt.</p>

 <p>A trick, described below, with @(tsee ec-call) can provide some of the
 benefit of memoizing an ideal-mode function.  The trick exploits the fact that
 @('ec-call') allows you to call an ideal-mode function within a @(see
 guard)-verified (``Common Lisp compliant'') @(':')@(tsee logic) mode function
 without having to verify guards for the ideal-mode function.  The following
 edited log illustrates the points above.</p>

 @({
 ACL2 !>(defun fib (n)
          (declare (xargs :guard (natp n) :verify-guards nil))
          (if (zp n)
              0
            (if (eql n 1)
                1
              (+ (fib (- n 1)) (fib (- n 2))))))
 [[ .. output omitted .. ]]
  FIB
 ACL2 !>(memoize 'fib :ideal-okp t)
 [[ .. output omitted .. ]]
  FIB
 ACL2 !>(time$ (fib 38)) ; slow: uses only executable-counterpart

 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 FIB.  To check guards on all recursive calls:
   (set-guard-checking :all)
 To leave behavior unchanged except for inhibiting this message:
   (set-guard-checking :nowarn)

 ; (EV-REC *RETURN-LAST-ARG3* ...) took
 ; 3.91 seconds realtime, 3.90 seconds runtime
 ; (416 bytes allocated).
 39088169
 ACL2 !>(time$ (fib 38)) ; still slow; no results were stored before

 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 FIB.  To check guards on all recursive calls:
   (set-guard-checking :all)
 To leave behavior unchanged except for inhibiting this message:
   (set-guard-checking :nowarn)

 ; (EV-REC *RETURN-LAST-ARG3* ...) took
 ; 3.92 seconds realtime, 3.91 seconds runtime
 ; (416 bytes allocated).
 39088169
 ACL2 !>(defun fib-logic-wrapper (n) ; guard-verified
          (declare (xargs :guard (natp n)))
          (ec-call (fib n)))
 [[ .. output omitted .. ]]
  FIB-LOGIC-WRAPPER
 ACL2 !>(memoize 'fib-logic-wrapper)
 [[ .. output omitted .. ]]
  FIB-LOGIC-WRAPPER
 ACL2 !>(time$ (fib-logic-wrapper 38)) ; slow; no fib results are stored

 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 FIB.  To check guards on all recursive calls:
   (set-guard-checking :all)
 To leave behavior unchanged except for inhibiting this message:
   (set-guard-checking :nowarn)

 ; (EV-REC *RETURN-LAST-ARG3* ...) took
 ; 3.92 seconds realtime, 3.91 seconds runtime
 ; (2,128 bytes allocated).
 39088169
 ACL2 !>(time$ (fib-logic-wrapper 38)) ; fast; fib-logic-wrapper result was stored
 ; (EV-REC *RETURN-LAST-ARG3* ...) took
 ; 0.00 seconds realtime, 0.00 seconds runtime
 ; (16 bytes allocated).
 39088169
 ACL2 !>(time$ (fib-logic-wrapper 37)) ; slow; result only for 38 was stored

 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 FIB.  To check guards on all recursive calls:
   (set-guard-checking :all)
 To leave behavior unchanged except for inhibiting this message:
   (set-guard-checking :nowarn)

 ; (EV-REC *RETURN-LAST-ARG3* ...) took
 ; 2.42 seconds realtime, 2.42 seconds runtime
 ; (416 bytes allocated).
 24157817
 ACL2 !>(defun fib-program-wrapper (n) ; program mode function
          (declare (xargs :guard (natp n) :mode :program))
          (fib n))

 Summary
 Form:  ( DEFUN FIB-PROGRAM-WRAPPER ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  FIB-PROGRAM-WRAPPER
 ACL2 !>(time$ (fib-program-wrapper 100)) ; fast because raw-Lisp fib is called
 ; (EV-REC *RETURN-LAST-ARG3* ...) took
 ; 0.00 seconds realtime, 0.00 seconds runtime
 ; (7,600 bytes allocated).
 354224848179261915075
 ACL2 !>
 })

 <p>Two non-@('nil') values are allowed for keyword parameter @(':ideal-okp'):
 @(':warn') and @('t').  Both of these values allow memoization of ideal-mode
 functions, but if @(':warn') is supplied then a warning will take place at
 memoization time, specifically for the resulting @(see table) event.  Note
 that you may set the key @(':memoize-ideal-okp') of the @(tsee
 acl2-defaults-table) to value @('t') or @(':warn') to change the default, but
 if parameter @(':ideal-okp') is supplied, the @(tsee acl2-defaults-table)
 value is ignored.</p>

 <p>If @(':verbose') is supplied, it should either be @('nil'), which will
 inhibit proof, event, and summary output (see @(see with-output)), or else
 @('t') (the default), which does not inhibit output.  If the output baffles
 you, try</p>

 @({
  :trans1 (memoize ...)
 })

 <p>to see the single-step macroexpansion of your @('memoize') call.</p>

 <p>The default for @(':forget') is @('nil').  If @(':forget') is supplied, and
 not @('nil'), then it must be @('t'), which causes all memoization done for a
 top-level call of @('fn') to be forgotten when that top-level call
 exits.</p>")

(defxdoc memoize-summary
  :parents (memoize)
  :short "Display all collected profiling and memoization info"
  :long "<p>Logically, this function just returns @('nil'), but it displays
 profiling and memoization table information.  The profiling statistics may be
 cleared with @('(')@(tsee clear-memoize-statistics)@(')').</p>

 <p>Note that by default, statistics might be inaccurate when calls of @(see
 memoize)d functions are aborted.  This issue can be avoided, however; see
 @(see protect-memoize-statistics).</p>

 @(def memoize-summary)")

(defxdoc memsum
  :parents (memoize)
  :short "Display all collected profiling and memoization info"
  :long "<p>This macro is an abbreviation for @(tsee memoize-summary).
 Logically, it just returns @('nil').  Also see @(see
 protect-memoize-statistics).</p>")

(defxdoc meta
  :parents (rule-classes)
  :short "Make a @(':meta') rule (a hand-written simplifier)"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 <p>Meta rules extend the ACL2 simplifier with hand-written code to transform
 certain terms to equivalent ones.  To add a meta rule, the @(':')@(tsee
 corollary) formula must establish that the hand-written ``metafunction''
 preserves the meaning of the transformed term.</p>

 @({
  Examples:
  (defthm fn-correct-1                ; Modify the rewriter to use fn to
    (equal (evl x a)                  ; transform terms that are calls of
           (evl (fn x) a))            ; nth or of foo.
    :rule-classes ((:meta :trigger-fns (nth foo))))

  (defthm fn-correct-2                ; As above, but this illustrates
    (implies (and (pseudo-termp x)    ; that without loss of generality we
                  (alistp a))         ; may restrict x to be shaped like a
             (equal (evl x a)         ; term and a to be an alist.
                    (evl (fn x) a)))
    :rule-classes ((:meta :trigger-fns (nth foo))))

  (defthm fn-correct-3                ; As above (with or without the
    (implies (and (pseudo-termp x)    ; hypotheses on x and a), with the
                  (alistp a)          ; additional restriction that the
                  (evl (hyp-fn x) a)) ; meaning of (hyp-fn x) is true in
             (equal (evl x a)         ; the current context.  That is, the
                    (evl (fn x) a)))  ; applicability of the transformation
    :rule-classes                     ; may be dependent upon some computed
    ((:meta :trigger-fns (nth foo)))) ; hypotheses.
 })

 <p>While our intention is that the set of ACL2 documentation topics is
 self-contained, readers might find it useful to see the following paper for an
 introduction to meta reasoning in ACL2.</p>

 <blockquote><p>W. A. Hunt, Jr., R. B. Krug, M. Kaufmann, J S. Moore and
 E. W. Smith, ``Meta Reasoning in ACL2.''  TPHOLs 2005, ed. J. Hurd and
 T. F. Melham, LNCS 3603, Springer-Verlag, Berlin, 2005,
 pp. 163&ndash;178.</p></blockquote>

 <p>A non-@('nil') list of function symbols must be supplied as the value of
 the @(':trigger-fns') field in a @(':meta') rule class object (except that a
 macro alias can stand in for a function symbol; see @(see
 add-macro-alias)).</p>

 @({
  General Forms:
  (implies (and (pseudo-termp x)        ; this hyp is optional
                (alistp a)              ; this hyp is optional
                (ev (hyp-fn x ...) a)   ; this hyp is optional
                ; meta-extract hyps may also be included (see below)
                )
           (equiv (ev x a)
                  (ev (fn x ...) a)))
 })

 <p>where @('equiv') is a known @(see equivalence) relation, @('x') and @('a')
 are distinct variable names, and @('ev') is an evaluator function (see below),
 and @('fn') is a function symbol, as is @('hyp-fn') when provided.  The
 arguments to @('fn') and @('hyp-fn') should be identical.  In the most common
 case, both take a single argument, @('x'), which denotes the term to be
 simplified.  If @('fn') and/or @('hyp-fn') are @(see guard)ed, their @(see
 guard)s should be trivially implied by @(tsee pseudo-termp).  We say the
 theorem above is a ``metatheorem'' or ``metalemma'' and @('fn') is a
 ``metafunction'', and @('hyp-fn') is a ``hypothesis metafunction''.</p>

 <p>If ``@('...')'' is empty, i.e., the metafunctions take just one argument,
 we say they are ``vanilla flavored.''  If ``@('...')'' is non-empty, we say
 the metafunctions are ``extended.''  Extended metafunctions can access @(tsee
 state) and context sensitive information to compute their results, within
 certain limits.  We discuss vanilla metafunctions here and recommend a
 thorough understanding of them before proceeding (at which time see @(see
 extended-metafunctions)).</p>

 <p>If a metafunction application to a term, @('u'), evaluates to a result of
 the form @('(if TEST NEW-TERM u)'), then @('TEST') is treated as an ``implicit
 hypothesis''.  For discussion of this relatively advanced feature, see @(see
 meta-implicit-hypothesis).</p>

 <p>Additional hypotheses are supported, called ``meta-extract hypotheses''.
 These allow metafunctions to depend on the validity of certain terms extracted
 from the context or the logical @(see world).  These hypotheses provide a
 relatively advanced form of metatheorem so we explain them elsewhere; see
 @(see meta-extract).</p>

 <p>One might think that metafunctions and (if supplied) hypothesis
 metafunctions must be executable: that is, not constrained (i.e., introduced
 in the @(see signature) of @(tsee encapsulate) @(see events)), and not @(see
 declare)d @(':')@(tsee non-executable).  After all, there is no point in
 installing a simplifier that cannot be run!  However, such a restriction is
 not enforced, because one could introduce a metafunction using @(tsee
 encapsulate) and then use @(tsee defattach) to attach it to an executable
 function; see @(see defattach).</p>

 <p>We defer discussion of the case in which there is a hypothesis metafunction
 and for now address the case in which the other two hypotheses are
 present.</p>

 <p>In the discussion below, we refer to the argument, @('x'), of @('fn') and
 @('hyp-fn') as a ``(translated) term,'' i.e., an object satisfying the ACL2
 built-in predicate @('termp').  When these metafunctions are executed by the
 simplifier, they will be applied to (the quotations of) terms.  But during the
 proof of the metatheorem itself, @('x') may not be the quotation of a term.
 If the @(tsee pseudo-termp) hypothesis is omitted, @('x') may be any object.
 Even with the @(tsee pseudo-termp) hypothesis, @('x') may merely ``look like a
 term'' but use non-function symbols or function symbols of incorrect arity.
 In any case, the metatheorem is stronger than necessary to allow us to apply
 the metafunctions to terms, as we do in the discussion below.  We return later
 to the question of proving the metatheorem.</p>

 <p>Suppose the general form of the metatheorem above is proved with the @(tsee
 pseudo-termp) and @(tsee alistp) hypotheses.  Then when the simplifier
 encounters a term, @('(h t1 ... tn)'), that begins with a function symbol,
 @('h'), listed in @(':trigger-fns'), it applies the metafunction, @('fn'), to
 the quotation of the term, i.e., it evaluates @('(fn '(h t1 ... tn))') to
 obtain some result, which can be written as @(''val').  If @(''val') is
 different from @(''(h t1 ... tn)') and @('val') is a well-formed term (see the
 next paragraph), then @('(h t1 ... tn)') is replaced by @('val'), which is
 then passed along for further rewriting.  Because the metatheorem establishes
 the correctness of @('fn') for all terms (even non-terms!), there is no
 restriction on which function symbols are listed in the @(':trigger-fns').
 Generally, of course, they should be the symbols that head up the terms
 simplified by the metafunction @('fn').</p>

 <p>Note that the result of applying a metafunction (or a hypothesis
 metafunction) must be a term, i.e., must satisfy the predicate @(tsee termp)
 in the current logical @(see world).  If not, then an error occurs.  See @(see
 term-table) for how one obtains some assistance towards testing that @('val')
 is indeed a term.  ACL2 actually enforces a stronger requirement, disallowing
 calls of certain ``forbidden'' function symbols as described in @(tsee
 set-skip-meta-termp-checks).  Both of these runtime checks can be avoided by
 proving that the metafunction (and the corresponding hypothesis metafunction,
 if any) always produces an acceptable term.  See @(see
 well-formedness-guarantee).  Alternatively, with an active trust tag (see
 @(see defttag)) you can tell ACL2 to skip these tests; see @(tsee
 set-skip-meta-termp-checks).</p>

 <p>The ``evaluator'' function, @('ev'), is a function that can evaluate a
 certain class of expressions, namely, all of those composed of variables,
 constants, and applications of a fixed, finite set of function symbols,
 @('g1'), ..., @('gk').  Generally speaking, the set of function symbols
 handled by @('ev') is chosen to be exactly the function symbols recognized and
 manipulated by the metafunctions being introduced.  For example, if @('fn')
 manipulates expressions in which @(''')@(tsee equal) and @(''')@(tsee
 binary-append) occur as function symbols, then @('ev') is generally specified
 to handle @(tsee equal) and @(tsee binary-append).  The actual requirements on
 @('ev') become clear when the metatheorem is proved.  The standard way to
 introduce an evaluator is to use the ACL2 macro @(tsee defevaluator), though
 this is not strictly necessary.  See @(see defevaluator) if you want
 details.</p>

 <p>[Aside for the logic-minded.] Why are we justified in using metafunctions
 this way?  Suppose @('(fn 'term1)') is @(''term2').  What justifies replacing
 @('term1') by @('term2')?  The first step is to assert that @('term1') is
 @('(ev 'term1 a)'), where @('a') is an alist that maps @(''var') to @('var'),
 for each variable @('var') in @('term1').  This step is incorrect, because
 @(''term1') may contain function symbols other than the ones, @('g1'), ...,
 @('gk'), that @('ev') knows how to handle.  But we can grow @('ev') to a
 ``larger'' evaluator, @('ev*'), an evaluator for all of the symbols that occur
 in @('term1') or @('term2').  We can prove that @('ev*') satisfies the @(see
 constraint)s on @('ev'), provided no @(tsee defaxiom) events are adding
 constraints to @('ev') (or callers of @('ev'), and recursively); ACL2 checks
 this additional property.  Hence, the metatheorem holds for @('ev*') in place
 of @('ev'), by functional instantiation.  We can then carry out the proof of
 the @(see equivalence) of @('term1') and @('term2') as follows: Fix @('a') to
 be an alist that maps the quotations of the variables of @('term1') and
 @('term2') to themselves.  Then,</p>

 @({
  term1 = (ev* 'term1 a)      ; (1) by construction of ev* and a
        = (ev* (fn 'term1) a) ; (2) by the metatheorem for ev*
        = (ev* 'term2 a)      ; (3) by evaluation of fn
        = term2               ; (4) by construction of ev* and a
 })

 <p>Note that in line (2) above, where we appeal to the (functional
 instantiation of the) metatheorem, we can relieve its (optional) @(tsee
 pseudo-termp) and @(tsee alistp) hypotheses by appealing to the facts that
 @('term1') is a term and @('a') is an alist by construction.  [End of Aside
 for the logic-minded.]</p>

 <p>There are subtleties related to the notion of ``growing'' @('ev') to a
 ``larger'' evaluator, as mentioned in the paragraph just above.  For
 corresponding restrictions on @(':meta') rules, see @(see
 evaluator-restrictions).</p>

 <p>Finally, we turn to the second case, in which there is a hypothesis
 metafunction.  In that case, consider as before what happens when the
 simplifier encounters a term, @('(h t1 ... tn)'), where @('h') is listed in
 @(':trigger-fns').  This time, after it applies @('fn') to @(''(h t1 ... tn)')
 to obtain the quotation of some new term, @(''val'), it then applies the
 hypothesis metafunction, @('hyp-fn').  That is, it evaluates @('(hyp-fn '(h t1
 ... tn))') to obtain some result, which can be written as @(''hyp-val').  If
 @('hyp-val') is not in fact a term, the metafunction is not used.  Provided
 @('hyp-val') is a term, the simplifier attempts to establish (by conventional
 backchaining) that this term is non-@('nil') in the current context.  Note
 that this backchaining is done just as it is done for hypotheses of @(see
 rewrite) (and @(see linear)) rules, namely, by rewriting with special
 attention to calls of certain functions including @(tsee force), @(tsee
 case-split), @(tsee syntaxp), and @(tsee bind-free).  If this attempt to
 establish this term fails, then the meta rule is not applied.  Otherwise,
 @('(h t1...tn)') is replaced by @('val') as in the previous case (where there
 was no hypothesis metafunction).</p>

 <p>Why is it justified to make this extension to the case of hypothesis
 metafunctions?  First, note that the rule</p>

 @({
  (implies (and (pseudo-termp x)
                (alistp a)
                (ev (hyp-fn x) a))
           (equal (ev x a)
                  (ev (fn x) a)))
 })

 <p>is logically equivalent to the rule</p>

 @({
  (implies (and (pseudo-termp x)
                (alistp a))
           (equal (ev x a)
                  (ev (new-fn x) a)))
 })

 <p>where @('(new-fn x)') is defined to be @('(list 'if (hyp-fn x) (fn x) x)').
 (If we're careful, we realize that this argument depends on making an
 extension of @('ev') to an evaluator @('ev*') that handles @(tsee if) and the
 functions manipulated by @('hyp-fn').)  If we write @(''term') for the
 quotation of the present term, and if @('(hyp-fn 'term)') and @('(fn 'term)')
 are both terms, say @('hyp1') and @('term1'), then by the previous argument we
 know it is sound to rewrite term to @('(if hyp1 term1 term)').  But since we
 have established in the current context that @('hyp1') is non-@('nil'), we may
 simplify @('(if hyp1 term1 term)') to @('term1'), as desired.</p>

 <p>We now discuss the role of the @(tsee pseudo-termp) hypothesis.
 @('(Pseudo-termp x)') checks that @('x') has the shape of a term.  Roughly
 speaking, it ensures that @('x') is a symbol, a quoted constant, or a true
 list consisting of a @('lambda') expression or symbol followed by some
 pseudo-terms.  Among the properties of terms not checked by @(tsee
 pseudo-termp) are that variable symbols never begin with ampersand,
 @('lambda') expressions are closed, and function symbols are applied to the
 correct number of arguments.  See @(see pseudo-termp).</p>

 <p>There are two possible roles for @(tsee pseudo-termp) in the development of
 a metatheorem: it may be used as the @(see guard) of the metafunction and/or
 hypothesis metafunction and it may be used as a hypothesis of the metatheorem.
 Generally speaking, the @(tsee pseudo-termp) hypothesis is included in a
 metatheorem only if it makes it easier to prove.  The choice is yours.  (An
 extreme example of this is when the metatheorem is invalid without the
 hypothesis!)  We therefore address ourselves the question: should a
 metafunction have a @(tsee pseudo-termp) @(see guard)?  A @(tsee pseudo-termp)
 @(see guard) for a metafunction, in connection with other considerations
 described below, improves the efficiency with which the metafunction is used
 by the simplifier.</p>

 <p>To make a metafunction maximally efficient you should (a) provide it with a
 @(tsee pseudo-termp) @(see guard) and exploit the @(see guard) when possible
 in coding the body of the function (see @(see guards-and-evaluation),
 especially the section on efficiency issues), (b) verify the @(see guard)s of
 the metafunction (see @(see verify-guards)), and (c) compile the metafunction
 (see @(see comp)).  When these three steps have been taken the simplifier can
 evaluate @('(fn 'term1)') by running the compiled ``primary code'' (see @(see
 guards-and-evaluation)) for @('fn') directly in Common Lisp.  (Note however
 that explicit compilation may be suppressed; see @(see compilation).)</p>

 <p>Before discussing efficiency issues further, let us review for a moment the
 general case in which we wish to evaluate @('(fn 'obj)') for some @(':')@(tsee
 logic) function.  We must first ask whether the @(see guard)s of @('fn') have
 been verified.  If not, we must evaluate @('fn') by executing its logic
 definition.  This effectively checks the @(see guard)s of every subroutine and
 so can be slow.  If, on the other hand, the @(see guard)s of @('fn') have been
 verified, then we can run the primary code for @('fn'), provided @(''obj')
 satisfies the @(see guard) of @('fn').  So we must next evaluate the @(see
 guard) of @('fn') on @(''obj').  If the @(see guard) is met, then we run the
 primary code for @('fn'), otherwise we run the logic code.</p>

 <p>Now in the case of a metafunction for which the three steps above have been
 followed, we know the @(see guard) is (implied by) @(tsee pseudo-termp) and
 that it has been verified.  Furthermore, we know without checking that the
 @(see guard) is met (because @('term1') is a term and hence @(''term1') is a
 @(tsee pseudo-termp)).  Hence, we can use the compiled primary code
 directly.</p>

 <p>We strongly recommend that you compile your metafunctions, as well as all
 their subroutines (unless explicit compilation is suppressed; see @(see
 compilation)).  Guard verification is also recommended.</p>

 <p>Finally, we present a very simple example of the use of @(':meta') rules,
 based on one provided by Robert Krug.  This example illustrates a trick for
 avoiding undesired rewriting after applying a metafunction or any other form
 of rewriting.  To elaborate: in general, the term @('t2') obtained by applying
 a metafunction to a term @('t1') is then handed immediately to the rewriter,
 which descends recursively through the arguments of function calls to rewrite
 @('t2') completely.  But if @('t2') shares a lot of structure with @('t1'),
 then it might not be worthwhile to rewrite @('t2') immediately.  (A rewrite of
 @('t2') will occur anyhow the next time a goal is generated.)  The trick
 involves avoiding this rewrite by wrapping @('t2') inside a call of @(tsee
 hide), which in turn is inside a call of a user-defined ``unhiding'' function,
 @('unhide').</p>

 @({
  (defun unhide (x)
    (declare (xargs :guard t))
    x)

  (defthm unhide-hide
    (equal (unhide (hide x))
           x)
    :hints ((\"Goal\" :expand ((hide x)))))

  (in-theory (disable unhide))

  (defun my-plus (x y)
    (+ x y))

  (in-theory (disable my-plus))

  (defevaluator evl evl-list
    ((my-plus x y)
     (binary-+ x y)
     (unhide x)
     (hide x)))

  (defun meta-fn (term)
    (declare (xargs :guard (pseudo-termp term)))
    (if (and (consp term)
             (equal (length term) 3)
             (equal (car term) 'my-plus))
        `(UNHIDE (HIDE (BINARY-+ ,(cadr term) ,(caddr term))))
      term))

  (defthm my-meta-lemma
    (equal (evl term a)
           (evl (meta-fn term) a))
    :hints ((\"Goal\" :in-theory (enable my-plus)))
    :rule-classes ((:meta :trigger-fns (my-plus))))
 })

 <p>Notice that in the following (silly) conjecture, ACL2 initially does only
 does the simplification directed by the metafunction; a second goal is
 generated before the commutativity of addition can be applied.  If the above
 calls of @('UNHIDE') and @('HIDE') had been stripped off, then @('Goal'')
 would have been the term printed in @('Goal''') below.</p>

 @({
  ACL2 !>(thm
          (equal (my-plus b a)
                 ccc))

  This simplifies, using the :meta rule MY-META-LEMMA and the :rewrite
  rule UNHIDE-HIDE, to

  Goal'
  (EQUAL (+ B A) CCC).

  This simplifies, using the :rewrite rule COMMUTATIVITY-OF-+, to

  Goal''
  (EQUAL (+ A B) CCC).
 })

 <p>The discussion above probably suffices to make good use of this @('(UNHIDE
 (HIDE ...))') trick.  However, we invite the reader who wishes to understand
 the trick in depth to evaluate the following form before submitting the @(tsee
 thm) form above.</p>

 @({
  (trace$ (rewrite :entry (list (take 2 arglist))
                   :exit (list (car values)))
          (rewrite-with-lemma :entry (list (take 2 arglist))
                              :exit (take 2 values)))
 })

 <p>The following annotated subset of the trace output (which may appear a bit
 different depending on the underlying Common Lisp implementation) explains how
 the trick works.</p>

 @({
      2> (REWRITE ((MY-PLUS B A) NIL))>
        3> (REWRITE-WITH-LEMMA
                ((MY-PLUS B A)
                 (REWRITE-RULE (:META MY-META-LEMMA)
                               1822
                               NIL EQUAL META-FN NIL META NIL NIL)))>

  We apply the meta rule, then recursively rewrite the result, which is the
  (UNHIDE (HIDE ...)) term shown just below.

          4> (REWRITE ((UNHIDE (HIDE (BINARY-+ B A)))
                       ((A . A) (B . B))))>
            5> (REWRITE ((HIDE (BINARY-+ B A))
                         ((A . A) (B . B))))>

  The HIDE protects its argument from being touched by the rewriter.

            <5 (REWRITE (HIDE (BINARY-+ B A)))>
            5> (REWRITE-WITH-LEMMA
                    ((UNHIDE (HIDE (BINARY-+ B A)))
                     (REWRITE-RULE (:REWRITE UNHIDE-HIDE)
                                   1806 NIL EQUAL (UNHIDE (HIDE X))
                                   X ABBREVIATION NIL NIL)))>

  Now we apply UNHIDE-HIDE, then recursively rewrite its right-hand
  side in an environment where X is bound to (BINARY-+ B A).

              6> (REWRITE (X ((X BINARY-+ B A))))>

  Notice that at this point X is cached, so REWRITE just returns
  (BINARY-+ B A).

              <6 (REWRITE (BINARY-+ B A))>
            <5 (REWRITE-WITH-LEMMA T (BINARY-+ B A))>
          <4 (REWRITE (BINARY-+ B A))>
        <3 (REWRITE-WITH-LEMMA T (BINARY-+ B A))>
      <2 (REWRITE (BINARY-+ B A))>
 })")

(defxdoc meta-extract
  :parents (meta)
  :short "Meta reasoning using valid terms extracted from context or @(see world)"
  :long "<p>For this advanced topic, we assume familiarity with metatheorems
 and metafunctions (see @(see meta)), as well as extended metafunctions (see
 @(see extended-metafunctions)).  The capability described here &mdash;
 so-called ``meta-extract hypotheses'' for a @(':')@(tsee meta) or a
 @(':')@(tsee clause-processor) rule &mdash; provides an advanced form of
 meta-level reasoning that was initially designed largely by Sol Swords, who
 also provided a preliminary implementation.</p>

 <p>A meta rule or clause-processor rule may have so-called ``meta-extract''
 hypotheses that take forms displayed below.  Here @('evl') is the evaluator,
 @('obj') is an arbitrary term, @('mfc') is the metafunction context (which is
 a variable other than the symbol @('STATE') that represents the metafunction
 context; see @(see extended-metafunctions)), @('state') is literally the
 symbol @('STATE'), @('a') is the second argument of @('evl') in both arguments
 of the conclusion of the rule, and @('aa') is an arbitrary term.</p>

 @({
  (evl (meta-extract-contextual-fact obj mfc state) a)
  (evl (meta-extract-global-fact obj state) aa) ; equivalent to the next form
  (evl (meta-extract-global-fact+ obj state state) aa)
  (evl (meta-extract-global-fact+ obj st state) aa)
 })

 <p>The first form is only legal for @(':meta') rules for which the
 metafunction is an extended metafunction.  The remaining forms are legal for
 both @(':meta') rules and @(':clause-processor') rules.</p>

 <p>Sol Swords has contributed a community book,
 @('clause-processors/meta-extract-user.lisp'), that uses a Skolemization trick
 to allow one to use at most one @('meta-extract-global-fact+') hypothesis and
 at most one @('meta-extract-contextual-fact') hypothesis.</p>

 <p>These additional hypotheses may be necessary in order to prove a proposed
 metatheorem or (for the second type of hypothesis above) clause-processor
 rule, in particular when the correctness of the metafunction depends on the
 correctness of utilities extracting formulas from the logical @(see world) or
 (for the first type) facts from the metafunction context (mfc).  After the
 rule is proved, however, the meta-extract hypotheses have no effect on how the
 rule is applied during a proof.  An argument for correctness of using
 meta-extract hypotheses is given in the ACL2 source code within a comment
 entitled ``Essay on Correctness of Meta Reasoning''.  In the documentation
 below, we focus primarily on @(':')@(tsee meta) rules, since the use of
 @('meta-extract-global-fact') hypotheses in @(':')@(tsee clause-processor)
 rules is entirely analogous.  (At the end, though, we discuss the last of the
 four forms displayed above.)  And for @(':meta') rules we focus not on the
 application of rules but, rather, on how the use of meta-extract hypotheses
 allow you to prove correctness of metafunctions that use facts from the
 logical @(see world) or the metafunction context (mfc).</p>

 <p>Below we describe properties of @('meta-extract-contextual-fact') and
 @('meta-extract-global-fact'), but only after we illustrate their utility with
 an example.  But even before we present that example, we first give a sense of
 how to think about these functions by showing a theorem that one can prove
 about the first of them.  If this snippet doesn't help your intuition, then
 just skip over it and start with the example.</p>

 @({
  (defevaluator evl evl-list
    ((binary-+ x y) (typespec-check x y)))

  (thm (implies
        (not (bad-atom (cdr (assoc-equal 'x alist))))
        (equal (evl (meta-extract-contextual-fact (list :typeset 'x)
                                                  mfc
                                                  state)
                    alist)
               (not (equal 0 ; indicates non-empty intersection
                           (logand (type-set-quote ; type-set of a constant
                                    (cdr (assoc-equal 'x alist)))
                                   (mfc-ts-fn 'x mfc state nil)))))))
 })

 <p>Next we present an example, which comes from the community book,
 @('books/clause-processors/meta-extract-simple-test.lisp').  That book
 presents very basic, contrived examples that nevertheless illustrate
 meta-extract hypotheses.  For a more interesting tutorial example, see the
 community book @('books/demos/nth-update-nth-meta-extract.lisp').</p>

 <p>Our example includes this meta rule.</p>

 @({
  (defthm plus-identity-2-meta
    (implies (and (nthmeta-ev (meta-extract-global-fact '(:formula bar-posp)
                                                        state)
                              (list (cons 'u
                                          (nthmeta-ev (cadr (cadr term))
                                                      a))))
                  (nthmeta-ev (meta-extract-contextual-fact
                               `(:typeset ,(caddr term)) mfc state)
                              a))
             (equal (nthmeta-ev term a)
                    (nthmeta-ev (plus-identity-2-metafn term mfc state) a)))
    :rule-classes ((:meta :trigger-fns (binary-+))))
 })

 <p>The two hypotheses illustrate the two basic kinds of meta-extract
 hypotheses: applications of the evaluator to a call of
 @('meta-extract-global-fact') and to a call of
 @('meta-extract-contextual-fact').  Here is the definition of the metafunction
 used in the above rule, slightly simplified here from what is found in the
 above book (but adequate for proving the two events that follow it in the
 above book).</p>

 @({
  (defun plus-identity-2-metafn (term mfc state)
    (declare (xargs :stobjs state :verify-guards nil))
    (case-match term
      (('binary-+ ('bar &) y)
       (cond
        ((equal (meta-extract-formula 'bar-posp state)
                '(POSP (BAR U)))
         (if (ts= (mfc-ts y mfc state :forcep nil)
                  *ts-character*)
             (cadr term)
           term))
        (t term)))
      (& term)))
 })

 <p>This metafunction returns its input term unchanged except in the case that
 the term is of the form @('(binary-+ (bar x) y)') and the following two
 conditions are met, in which case it returns @('(bar x)').</p>

 @({
  (1)  (equal (meta-extract-formula 'bar-posp state)
              '(POSP (BAR U)))

  (2)  (ts= (mfc-ts y mfc state :forcep nil)
            *ts-character*)
 })

 <p>So suppose that term is @('(list 'binary-+ (list 'bar x) y)').  We show how
 the meta-extract hypotheses together with (1) and (2) imply that the
 conclusion of the above @(':meta') rule holds.  Here is that conclusion after
 a bit of simplification.</p>

 @({
  (equal (nthmeta-ev (list 'binary-+ (list 'bar x) y) a)
         (nthmeta-ev (list 'bar x) a))
 })

 <p>This equality simplifies as follows using the evaluator properties of
 @('nthmeta-ev').</p>

 @({
  (equal (binary-+ (bar (nthmeta-ev x a))
                   (nthmeta-ev y a))
         (bar (nthmeta-ev x a)))
 })

 <p>Since a positive number plus a character is that number, it clearly
 suffices to show:</p>

 @({
  (A)  (posp (bar (nthmeta-ev x a)))

  (B)  (characterp (nthmeta-ev y a))
 })

 <p>It remains then to show that these follow from (1) and (2) together with
 the meta-extract hypotheses.</p>

 <p>First consider (A).  We show that it is just a simplification of the first
 meta-extract hypothesis.</p>

 @({
  (nthmeta-ev (meta-extract-global-fact '(:formula bar-posp)
                                        state)
              (list (cons 'u
                          (nthmeta-ev (cadr (cadr term))
                                      a))))
  = {by our assumption that term is (list 'binary-+ (list 'bar x) y)}
  (nthmeta-ev (meta-extract-global-fact '(:formula bar-posp)
                                        state)
              (list (cons 'u
                          (nthmeta-ev x a))))
  = {by definition of meta-extract-global-fact, as discussed later}
  (nthmeta-ev (meta-extract-formula 'bar-posp state)
              (list (cons 'u
                          (nthmeta-ev x a))))
  = {by (1)}
  (nthmeta-ev '(posp (bar u))
              (list (cons 'u
                          (nthmeta-ev x a))))
  = {by evaluator properties of nthmeta-ev}
  (posp (bar (nthmeta-ev x a)))
 })

 <p>Now consider (B).  We show that it is just a simplification of the second
 meta-extract hypothesis.</p>

 @({
  (nthmeta-ev (meta-extract-contextual-fact
               `(:typeset ,(caddr term)) mfc state)
              a)
  = {by our assumption that term is (list 'binary-+ (list 'bar x) y)}
  (nthmeta-ev (meta-extract-contextual-fact (list ':typeset y) mfc state)
              a)
  = {by definition of meta-extract-contextual-fact, as discussed later}
  (nthmeta-ev (list 'typespec-check
                    (list 'quote
                          (mfc-ts y mfc state :forcep nil))
                    y)
              a)
  = {by (2)}
  (nthmeta-ev (list 'typespec-check
                    (list 'quote *ts-character*)
                    y)
              a)
  = {by evaluator properties of nthmeta-ev}
  (typespec-check *ts-character* (nthmeta-ev y a))
  = {by definition of typespec-check}
  (characterp (nthmeta-ev y a))
 })

 <p>Note the use of @(':forcep nil') above.  All of the @('mfc-xx') functions
 take a keyword argument @(':forcep').  Calls of @('mfc-xx') functions made on
 behalf of @('meta-extract-contextual-fact') always use @(':forcep nil'), so in
 order to reason about these calls in your own metafunctions, you will want to
 use @(':forcep nil').  We have contemplated adding a utility like
 @('meta-extract-contextual-fact') that allows forcing but returns a tag-tree
 (see @(see ttree)), and may do so if there is demand for it.</p>

 <p>Finally, we document what is provided logically by calls of
 @('meta-extract-global-fact') and @('meta-extract-contextual-fact').  Of
 course, you are invited to look at the definitions of these functions in the
 ACL2 source code, or by using @(':')@(tsee pe).  Note that both of these
 functions are non-executable (each of their bodies is inside a call of @(tsee
 non-exec)); their purpose is purely logical, not for execution.  The functions
 return @('*t*'), i.e., @('(quote t)'), in cases that they provide no
 information.</p>

 <p>First we consider the value of @('(meta-extract-global-fact obj state)')
 for various values of @('obj').  When we refer below to concepts like ``body''
 and ``evaluation'', we refer to these with respect to the logical world of the
 input @('state').</p>

 <blockquote>

 <p>CASE @('obj') = @('(list :formula FN)'):</p>

 <p>In this case @('(meta-extract-global-fact obj state)') is equal to
 @('(meta-extract-formula FN state)').  That, in turn, evaluates to the
 ``formula'' of @('FN') in the following sense when @('state') is the ACL2
 ``live'' @(see state) object.  If @('FN') is a function symbol with formals
 @('(X1 ... Xk)'), then the formula is the @(see constraint) on @('FN') if
 @('FN') is constrained or introduced by @(tsee defchoose), and otherwise is
 @('(equal (FN X1 ... Xk) BODY)'), where @('BODY') is the (unsimplified) body
 of the definition of @('FN').  Otherwise, if @('FN') is the name of a theorem,
 the formula is just what is stored for that theorem.  Otherwise, the formula
 is @('*t*').</p>

 <p>CASE @('obj') = @('(list :lemma FN N)'):</p>

 <p>Assume @('N') is a natural number; otherwise, treat @('N') as 0.  Then
 @('(meta-extract-global-fact obj state)') is equal to the formula @('(nth
 N (getpropc FN 'lemmas nil (w state)))') if @('N') is in range, else @('*t*').
 Thus, if @('FN') is a function symbol with more than @('N') associated lemmas
 &mdash; ``associated'' in the sense of being either a @(':')@(tsee definition)
 rule for @('FN') or a @(':')@(tsee rewrite) rule for @('FN') whose left-hand
 side has a top function symbol of @('FN') &mdash; then when @('state') is the
 actual ACL2 ``live'' @(see state) object, @('(meta-extract-global-fact obj
 state)') evaluates to the @('N')th such lemma (with zero-based indexing).</p>

 <p>CASE @('obj') = @('(list :fncall FN ARGLIST)'):</p>

 <p>Consider the term @('(magic-ev-fncall FN ARGLIST state t nil)'), which is
 axiomatized to return a multiple values pair @('(mv erp val)'), and moreover:
 if @('state') is the actual ACL2 ``live'' @(see state) and @('erp') is
 @('nil'), then @('val') is the result of applying @('fn') to @('arglist').
 For example, after submitting @('(defun foo (z) (mv (cdr z) (car z)))'), we
 can evaluate a corresponding call of @('magic-ev-fncall') as follows, noting
 that for this purpose the macro @(tsee mv) is given its logical meaning,
 @(tsee list):</p>

 @({
 ACL2 !>(magic-ev-fncall 'foo '((a b c)) state t nil)
 (NIL ((B C) A))
 ACL2 !>
 })

 <p>Let @('erp') and @('val') be as above: more precisely, let them abbreviate
 the terms @('(nth '0 (magic-ev-fncall FN ARGLIST state t nil))') and @('(nth
 '1 (magic-ev-fncall FN ARGLIST state t nil))'), respectively.  Then
 @('(meta-extract-global-fact obj state)') is either @('*t*'), in the ``error
 case'' that @('erp') is not @('nil'), or else is a term that equates @('val')
 with the application of @('FN') to @('ARGLIST'), as follows.  Assume that
 @('FN') is a @(':')@(tsee logic)-mode function symbol and that @('ARGLIST') is
 a true list of values of the same length as list of formal parameters for
 @('FN') (i.e., as the input arity of @('FN')).  Let @('(QARG1 ... QARGk)') be
 the result of quoting each element of @('ARGLIST'), i.e., replacing each
 @('y') in @('ARGLIST') by the two-element list @('(quote y)').  Then
 @('(meta-extract-global-fact obj state)') reduces to the term @('(equal (FN
 QARG1 ... QARGk) (quote val))').</p>

 <p>CASE otherwise:</p>

 <p>For any other values of @('obj'), the value is @('*t*').</p>

 </blockquote>

 <p>Finally, the value of @('(meta-extract-contextual-fact obj mfc state)') is
 as follows for various values of @('obj').  Note a difference from the
 semantics of @('meta-extract-global-fact'): below, the relevant logical world
 is the one stored in the metafunction context, @('mfc'), not in the input
 @('state').</p>

 <blockquote>

 <p>CASE @('obj') = (list :typeset TERM ...):</p>

 <p>The value is the value of @('(typespec-check ts TERM)'), where @('ts') is
 the value of @('(mfc-ts TERM mfc state :forcep nil :ttreep nil)'), and where
 @('(typespec-check ts val)') is defined to be true when @('val') has type-set
 @('ts').  (Exception: If @('val') satisfies @('bad-atom') then
 @('typespec-check') is true when @('ts') is negative.)</p>

 <p>CASE @('obj') = (list :rw+ TERM ALIST OBJ EQUIV ...):</p>

 <p>We assume below that @('EQUIV') is a symbol that represents an equivalence
 relation, where @('nil') represents @(tsee equal), @('t') represents @(tsee
 iff), and otherwise @('EQUIV') represents itself (an equivalence relation in
 the current logical @(see world)).  For any other @('EQUIV') the value is
 @('*t*').  Now let @('rhs') be the value of @('(mfc-rw+ TERM ALIST OBJ EQUIV
 mfc state :forcep nil :ttreep nil)').  Then the value is the term @('(list
 'equv (sublis-var ALIST TERM) rhs)'), where equv is the equivalence relation
 represented by @('EQUIV'), and @('sublis-var') is defined to substitute a
 variable-binding alist into a term.</p>

 <p>CASE @('obj') = (list :rw TERM OBJ EQUIV ...):</p>

 <p>The value is the same as above but for an @('ALIST') of @('nil'), i.e., for
 the case that @('obj') is @('(list :rw+ TERM nil OBJ EQUIV ...)').</p>

 <p>CASE @('obj') = (list :ap TERM ...):</p>

 <p>The value is @('(list 'not TERM)') if @('(mfc-ap TERM mfc state :forcep
 nil)') is true, else is @('*t*').</p>

 <p>CASE @('obj') = (list :relieve-hyp HYP ALIST RUNE TARGET BKPTR
 ...):</p>

 <p>The value is @('(sublis-var alist hyp)') &mdash; see above for a discussion
 of @('sublis-var') &mdash; if the following is true.</p>

 @({
  (mfc-relieve-hyp hyp alist rune target bkptr mfc state
                   :forcep nil :ttreep nil)
 })

 <p>Otherwise the value is @('*t*').</p>

 <p>CASE otherwise:</p>

 <p>If no case above applies, then the value is @('*t*').</p>

 </blockquote>

 <p>We conclude by considering the fourth of the four forms above (and
 implicitly, its special case represented by the third form above):</p>

 @({
  (evl (meta-extract-global-fact+ obj st state) aa)
 })

 <p>The discussion above is for the function @('meta-extract-global-fact+'),
 but assumes that the logical @(see world)s of @('st') and @('state') are
 equal; otherwise the value returned is @('*t*').  Of course, since a call of
 @('meta-extract-global-fact') expands to a corresponding call of
 @('meta-extract-global-fact+') in which the last two arguments are both
 @('state'), that condition holds automatically for that case.  But the
 @('state') mentioned in the meta-extract hypotheses of a @(see meta) rule or
 @(see clause-processor) rule is in essence an initial state.  In the case of a
 clause-processor rule, the clause-processor function may modify that initial
 state (say, by printing or modifying some state globals) without changing its
 world, and then pass that modified state to @('fncall-term').  While
 @('fncall-term') may produce a different result for this modified state than
 for the initial state, both are valid: other than its world, the state is used
 only for heuristic purposes, such as determining whether guard-checking may
 cause an error.  A useful instance of the hypothesis displayed above will be
 one in which @('st') is that modified state.</p>")

(defxdoc meta-implicit-hypothesis

; For convenience, here is the list of forms from the second section, laid out
; in a way that makes it easy to run them all.  Perhaps it would be worthwhile
; putting this directly into the documentation, but I think that might well be
; more of a distraction than a help.

; (defun foo (x y)
;   (+ x y))

; (defevaluator evl evl-list
;   ((if x y z)
;    (foo x y)
;    (binary-+ x y)
;    (unary-- x)
;    (acl2-numberp x)
;    (not x)))

; (defun meta-helper (term) ; PRETEND that his function is expensive to compute!
;   (declare (xargs :guard (pseudo-termp term)))
;   (case-match term
;     (('foo x ('foo y ('unary-- x)))
;      (declare (ignore x))
;      (mv `(acl2-numberp ,y)
;          y))
;     (& (mv nil term))))

; (defun meta-fn (term)
;   (declare (xargs :guard (pseudo-termp term)))
;   (mv-let (hyp new-term)
;           (meta-helper term)
;           (if hyp new-term term)))

; (defun meta-hyp-fn (term)
;   (declare (xargs :guard (pseudo-termp term)))
;   (mv-let (hyp new-term)
;           (meta-helper term)
;           (declare (ignore new-term))
;           (or hyp ''nil)))

; (defthm meta-fn-correct
;   (implies (evl (meta-hyp-fn x) a)
;            (equal (evl x a)
;                   (evl (meta-fn x) a)))
;   :rule-classes ((:meta :trigger-fns (foo))))

; (in-theory (disable foo))

; (trace$ meta-fn meta-hyp-fn meta-helper)

; (defthm meta-fn-correct-test
;   (implies (acl2-numberp b)
;            (equal (foo a (foo b (- a)))
;                   b)))

; (ubt! 'meta-fn)

; (defun meta-fn (term)
;   (declare (xargs :guard (pseudo-termp term)))
;   (mv-let (hyp new-term)
;           (meta-helper term)
;           (if hyp ; the interesting case
;               `(if ,hyp ,new-term ,term)
;             term)))

; (defthm meta-fn-correct
;   (equal (evl x a)
;          (evl (meta-fn x) a))
;   :rule-classes ((:meta :trigger-fns (foo))))

; (in-theory (disable foo))

; (trace$ meta-fn meta-helper)

; (defthm meta-fn-correct-test
;   (implies (acl2-numberp b)
;            (equal (foo a (foo b (- a)))
;                   b)))

; (thm ; FAILS but does not loop!
;  (equal (foo a (foo b (- a)))
;         b))

; :ubt! meta-fn

; (defun meta-fn (term)
;   (declare (xargs :guard (pseudo-termp term)))
;   (mv-let (hyp new-term)
;           (meta-helper term)
;           (if hyp ; the interesting case ;
;               `(if (not ,hyp) ,term ,new-term)
;             term)))

; (defthm meta-fn-correct
;   (equal (evl x a)
;          (evl (meta-fn x) a))
; :rule-classes ((:meta :trigger-fns (foo))))

; (in-theory (disable foo))

; (defthm meta-fn-correct-test
;   (implies (acl2-numberp b)
;            (equal (foo a (foo b (- a)))
;                   b)))

; (thm ; loops!
;  (equal (foo a (foo b (- a)))
;         b))

  :parents (meta)
  :short "A potentially more efficient way of coding a hypothesis metafunction"
  :long "<p>We assume familiarity with @(see meta) rules.  In this topic, we
 discuss a relatively advanced capability of meta reasoning in ACL2 that can
 increase its efficiency.</p>

 <h3>Introduction</h3>

 <p>In brief: if a metafunction application to a term, @('u'), evaluates to a
 result of the form @('(if TEST NEW-TERM u)'), then @('TEST') is treated as an
 ``implicit hypothesis,'' which must rewrite to true in order for the meta rule
 to simplify the input term.  We now explain in more detail.</p>

 <p>Recall the general form of a meta rule:</p>

 @({
  (implies (and (pseudo-termp x)        ; this hyp is optional
                (alistp a)              ; this hyp is optional
                (ev (hyp-fn x ...) a)   ; this hyp is optional
                ; meta-extract hyps may also be included (see below)
                )
           (equiv (ev x a)
                  (ev (fn x ...) a)))
 })

 <p>When this rule is to be applied to a term, @('x'), then @('(hyp-fn x ...)')
 is evaluated to produce a term, which must rewrite to true in order to
 evaluate the call @('(fn x ...)'), which is then rewritten to a replacement
 for @('x').  But it may be that these calls of @('hyp-fn') and @('fn') share a
 sub-computation.  ACL2 provides the ``implicit hypothesis'' mechanism in order
 to share such a sub-computation.  The next section illustrates how this
 mechanism works. The final section provides a precise specification of
 implicit hypotheses and how they are used in metareasoning.</p>

 <h3>Example</h3>

 <p>The following example is trivial but illustrates the sort of situation for
 which implicit hypotheses can be useful.  First let us introduce a function
 and an evaluator (see @(see defevaluator)).</p>

 @({
 (defun foo (x y)
   (+ x y))

 (defevaluator evl evl-list
   ((if x y z)
    (foo x y)
    (binary-+ x y)
    (unary-- x)
    (acl2-numberp x)
    (not x)))
 })

 <p>Let us write a meta function and associated hypothesis metafunction that
 apply a common function, @('meta-helper'), to a term, @('term'), to return one
 of two multiple values: @('(mv nil term)') in the case that there is no
 simplification; else @('(mv hyp new-term)'), where the following is a
 theorem: `(implies ,hyp (equal ,term ,new-term)).  Of course, the following
 definition introduces a function whose calls can be evaluated very quickly;
 but for purposes of this example, let us pretend that calls of
 @('meta-helper') take a great deal of time to evaluate.</p>

 @({
 (defun meta-helper (term) ; PRETEND that his function is expensive to compute!
   (declare (xargs :guard (pseudo-termp term)))
   (case-match term
     (('foo x ('foo y ('unary-- x)))
      (declare (ignore x))
      (mv `(acl2-numberp ,y)
          y))
     (& (mv nil term))))
 })

 <p>We can now define our meta function and hypothesis metafunction and prove
 a meta rule based on them.</p>

 @({
 (defun meta-fn (term)
   (declare (xargs :guard (pseudo-termp term)))
   (mv-let (hyp new-term)
           (meta-helper term)
           (if hyp new-term term)))

 (defun meta-hyp-fn (term)
   (declare (xargs :guard (pseudo-termp term)))
   (mv-let (hyp new-term)
           (meta-helper term)
           (declare (ignore new-term))
           (or hyp ''nil)))

 (defthm meta-fn-correct
   (implies (evl (meta-hyp-fn x) a)
            (equal (evl x a)
                   (evl (meta-fn x) a)))
   :rule-classes ((:meta :trigger-fns (foo))))
 })

 <p>In order to see this meta rule in action, let us disable @('foo') and try a
 little test.</p>

 @({
 (in-theory (disable foo))

 (defthm meta-fn-correct-test
   (implies (acl2-numberp b)
            (equal (foo a (foo b (- a)))
                   b)))
 })

 <p>Happily, the test succeeds, with the summary showing that our meta rule,
 @('meta-fn-correct'), was indeed used in the proof.  But if we first submit
 the form @('(trace$ meta-fn meta-hyp-fn meta-helper)'), we will see that
 @('meta-helper') is called twice on the term @('(FOO A (FOO B (UNARY-- A)))'):
 once on behalf of @('meta-fn') and once on behalf of @('meta-hyp-fn').  This
 would be unfortunate if @('meta-helper') were expensive to compute.</p>

 <p>So let us back up and try a different approach, which illustrates the idea
 of using an ``implicit hypothesis'' in order to avoid recomputation.  This
 time, we avoid defining a hypothesis metafunction, but instead we define
 @('meta-fn') to return a term of the form @('(if TEST NEW-TERM term)').  Here,
 @('TEST') is @('`(acl2-numberp ,y)'); we call this an ``implicit
 hypothesis.''</p>

 @({
 :ubt! meta-fn

 (defun meta-fn (term)
   (declare (xargs :guard (pseudo-termp term)))
   (mv-let (hyp new-term)
           (meta-helper term)
           (if hyp ; the interesting case
               `(if ,hyp ,new-term ,term)
             term)))
 })

 <p>There is nothing remarkable in the proof of the corresponding meta
 rule.</p>

 @({
 (defthm meta-fn-correct
   (equal (evl x a)
          (evl (meta-fn x) a))
   :rule-classes ((:meta :trigger-fns (foo))))
 })

 <p>Let us test our new implementation.  If we first evaluate the form
 @('(trace$ meta-fn meta-helper)'), we will see that this time,
 @('meta-helper') is called only once on the term @('(FOO A (FOO B (UNARY--
 A)))').</p>

 @({
 (in-theory (disable foo))

 (defthm meta-fn-correct-test
   (implies (acl2-numberp b)
            (equal (foo a (foo b (- a)))
                   b)))
 })

 <p>Note that the following proof attempt fails but does not loop.  Naively,
 one might expect it to loop, since the false branch of the @('IF') term
 returned by @('meta-fn') has the original (input) term as its false branch.
 However, ACL2 notices the special form @('(if TEST NEW-TERM term)') of the
 term returned by calling @('meta-fn'), and treats this result as though
 @('TEST') is the term returned by a hypothesis metafunction and @('NEW-TERM')
 is the term returned by the metafunction.</p>

 @({
 (thm ; FAILS but does not loop!
  (equal (foo a (foo b (- a)))
         b))
 })

 <p>Suppose that instead we had defined @('meta-fn') as follows, that is, with
 the `then' and `else' branches swapped.</p>

 @({
 (defun meta-fn (term)
   (declare (xargs :guard (pseudo-termp term)))
   (mv-let (hyp new-term)
           (meta-helper term)
           (if hyp ; the interesting case ;
               `(if (not ,hyp) ,term ,new-term)
             term)))
 })

 <p>Then the events above go through as before, up to the @(tsee thm) form.
 But that form loops, because the generated @('IF') term no longer has the
 special form @('(if TEST NEW-TERM term)').  In the (likely rare) case that
 really wishes to allow an unresolved case split for which one branch is the
 original term, this swapping of branches is available to defeat the
 recognition of an implicit hypothesis.</p>

 <h3>Precise specification</h3>

 <p>Consider a meta rule:</p>

 @({
  (implies (and (pseudo-termp x)        ; this hyp is optional
                (alistp a)              ; this hyp is optional
                (ev (hyp-fn x ...) a)   ; this hyp is optional
                ; meta-extract hyps may also be included (see below)
                )
           (equiv (ev x a)
                  (ev (fn x ...) a)))
 })

 <p>Recall that when this rule is applied to a term, @('term'), then a list of
 hypotheses is initially generated as follows, where each generated hypothesis
 must be rewritten to a non-@('nil') value in order for the rule to fire.</p>

 <ol>

 <li>If there is a hypothesis metafunction, @('hyp-fn'), then let @('hyps') be
 the list of hypothesis terms returned by the call of @('hyp-fn') on @('term').
 More precisely, the term returned by the call of @('hyp-fn') is flattened into
 a list of ``hypothesis terms,'' so that for example the (translated)
 conjunction @('(if a (if b c 'nil) 'nil)') generates the list @('(a b c)') of
 hypothesis terms.</li>

 <li>Otherwise, let @('hyps') be @('nil').</li>

 </ol>

 <p>When this rule is applied by calling @('fn') on a term, @('term'), we say
 that a term, @('test'), is an ``implicit hypothesis'' if the value returned by
 that call of @('fn') is a term of the form @('(if test new-term term)'): that
 is, @('test') is the test of the resulting @('if') term and the input term is
 the false branch of that @('if') term.  In this case, ACL2 recognizes
 @('test') as an implicit hypothesis, which triggers two changes made in how
 this meta rule is applied.  First, @('hyps') is extended by the flattened list
 of hypotheses generated from @('test').  Second, instead of applying
 @('hyp-fn') to the original term, @('term'), @('hyp-fn') is applied to
 @('new-term').</p>")

(defxdoc metafunction-context

; Note: Many of the descriptions in the bulleted list are taken from Lisp
; comments in the ACL2 source code for the function, rewrite.

  :parents (extended-metafunctions)
  :short "A structure that holds data supporting extended meta reasoning"
  :long "<p>This advanced topic explains the @('mfc') structure documented
 elsewhere; see @(see extended-metafunctions) for prerequisite background.
 This documentation is deliberately minimal, as we consider the @('mfc')
 structure to be implementation-level; comments in the source code may serve to
 provide more information.</p>

 <p><b>WARNING!</b> This is a data structure that supports the ACL2
 implementation.  While it is highly stable in practice, there is no guarantee
 that future ACL2 implementations will avoid changing it.  Use it at your own
 (perhaps small) risk!  If you want to avoid all such risk, use the interfaces
 described in the documentation for @(see extended-metafunctions), such as
 @('mfc-rw').</p>

 <p>The @('mfc') (metafunction-context) structure, which is given in the ACL2
 sources by the form @('(defrec metafunction-context ...)'), currently has the
 following fields.  Each instance is constructed in the context where it is
 needed, for example, during execution of a function that implements the ACL2
 rewriter.</p>

 <ul>

 <li>@('ancestors'): a list of terms assumed true, modified as we backchain</li>

 <li>@('backchain-limit'): heuristic limit to backchaining</li>

 <li>@('fnstack'): functions and terms currently being expanded &mdash; of
 heuristic use only</li>

 <li>@('geneqv'): a generated equivalence relation to maintain</li>

 <li>@('gstack'): either @('nil') or a goal stack, as in @(see cw-gstack)</li>

 <li>@('obj'): this ``objective'' is either @('t'), @('nil'), or @('?') &mdash;
 of heuristic use only.</li>

 <li>@('rcnst'): a @('rewrite-constant') record that holds many fields to be
 accessed by the ACL2 rewriter.  See the definition @('(defrec rewrite-constant
 ...)'), including comments therein, in the ACL2 sources.</li>

 <li>@('rdepth'): maximum allowed rewrite stack depth &mdash; of heuristic use
 only</li>

 <li>@('simplify-clause-pot-lst'): a pot-lst of polynomials (@('poly')
 records)</li>

 <li>@('ttree'): the evolving @(see ttree) describing the rewrites</li>

 <li>@('type-alist'): a @(see type-alist), representing assumptions governing
 the current rewrite</li>

 <li>@('unify-subst'): either @('nil') or a unifying substitution used by the
 rewriter</li>

 <li>@('wrld'): the current ACL2 @(see world)</li>

 </ul>

 <p>Here is an example of the use of these fields, which shows how to access
 the literal of the clause (goal) under which the current rewrite is taking
 place.</p>

 @({
 (defevaluator my-ev my-ev-lst ((if x y z)))

 (defun my-metafn (x mfc state)
   (declare (xargs :stobjs state
                   :verify-guards nil)
            (ignore state))
   (let* ((rcnst (access metafunction-context mfc :rcnst))
          (not-flg/atm (access rewrite-constant rcnst :current-literal))
          (atm (access current-literal not-flg/atm :atm)))
     (prog2$ (cw \"Current literal:~%~x0~%Current term:~%~x1~%\"
                 atm
                 x)
             x)))

 (defthm my-meta-correct
   (equal (my-ev x a)
          (my-ev (my-metafn x mfc state) a))
   :rule-classes ((:meta :trigger-fns (nth))))

 (defthmd mv-nth-is-nth
   (equal (mv-nth x y)
          (nth x y)))

 (set-gag-mode nil)

 (thm (implies (and (true-listp x)
                    (true-listp y))
               (equal (mv-nth n (append (car (cons x x)) y))
                      uuu))
      :hints ((\"Goal\" :do-not '(preprocess))
              (\"Goal'\" :in-theory (enable mv-nth-is-nth))))
 })

 <p>Here is some relevant output from the @(see THM) call, which shows that the
 rule @('mv-nth-is-nth') above has been applied while rewriting the conclusion
 of the proposed theorem &mdash; the meta function's printing happens while in
 the course of rewriting the @('NTH') call resulting from the application of
 the rule (i.e., an instance of the right-hand side of the rule).</p>

 @({
 Goal'
 (IMPLIES (AND (TRUE-LISTP X) (TRUE-LISTP Y))
          (EQUAL (MV-NTH N (APPEND X Y)) UUU)).
 Current literal:
 (EQUAL (MV-NTH N (BINARY-APPEND X Y)) UUU)
 Current term:
 (NTH N (BINARY-APPEND X Y))
 })")

(defxdoc min
  :parents (numbers acl2-built-ins)
  :short "The smaller of two numbers"
  :long "<p>@('(Min x y)') is the smaller of the numbers @('x') and @('y').</p>

 <p>The @(see guard) for @('min') requires its arguments to be rational (@(see
 real), in ACL2(r)) numbers.</p>

 <p>@('Min') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def min)")

(defxdoc minimal-theory
  :parents (theories theory-functions)
  :short "A minimal theory to enable"
  :long "<p>This @(tsee theory) (see @(see theories)) enables only a few
 built-in functions and @(see executable-counterpart)s.  It can be useful when
 you want to formulate lemmas that rather immediately imply the theorem to be
 proved, by way of a @(':use') hint (see @(see hints)), for example as
 follows.</p>

 @({
  :use (lemma-1 lemma-2 lemma-3)
  :in-theory (union-theories '(f1 f2) (theory 'minimal-theory))
 })

 <p>In this example, we expect the current goal to follow from lemmas
 @('lemma-1'), @('lemma-2'), and @('lemma-3') together with rules @('f1') and
 @('f2') and some obvious facts about built-in functions (such as the @(see
 definition) of @(tsee implies) and the @(':')@(tsee executable-counterpart) of
 @(tsee car)).  The @(':')@(tsee in-theory) hint above is intended to speed up
 the proof by turning off all inessential rules.</p>")

(defxdoc minusp
  :parents (numbers acl2-built-ins)
  :short "Test whether a number is negative"
  :long "<p>@('(Minusp x)') is true if and only if @('x < 0').</p>

 <p>The @(see guard) of @('minusp') requires its argument to be a rational
 (@(see real), in ACL2(r)) number.</p>

 <p>@('Minusp') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def minusp)")

(defxdoc miscellaneous
  :parents (acl2)
  :short "A miscellany of documented functions and concepts
               (often cited in more accessible @(see documentation))"
  :long "<p>Perhaps as the system matures this section will become more
  structured.</p>")

(defxdoc mod
  :parents (numbers acl2-built-ins)
  :short "Remainder using @(tsee floor)"
  :long "@({
  ACL2 !>(mod 14 3)
  2
  ACL2 !>(mod -14 3)
  1
  ACL2 !>(mod 14 -3)
  -1
  ACL2 !>(mod -14 -3)
  -2
  ACL2 !>(mod -15 -3)
  0
  ACL2 !>
 })

 <p>@('(Mod i j)') is that number @('k') that @('(* j (floor i j))') added to
 @('k') equals @('i').</p>

 <p>The @(see guard) for @('(mod i j)') requires that @('i') and @('j') are
 rational (@(see real), in ACL2(r)) numbers and @('j') is non-zero.</p>

 <p>@('Mod') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def mod)")

(defxdoc mod-expt
  :parents (numbers acl2-built-ins)
  :short "Exponential function"
  :long "<p>@('(mod-expt r i m)') is the result of raising the number @('r') to
 the integer power @('i') and then taking the residue mod @('m').  That is,
 @('(mod-expt r i m)') is equal to @('(mod (expt r i) m)').</p>

 <p>The @(see guard) for @('(mod-expt r i m)') is that @('r') is a rational
 number and @('i') is an integer; if @('r') is @('0') then @('i') is
 nonnegative; and @('m') is a non-zero rational number.</p>

 <p>In some implementations (GCL Version 2.7.0 as of this writing), this
 function is highly optimized when @('r') and @('i') are natural numbers, not
 both zero, and @('m') is a positive integer.  For other Lisp implementations,
 consider using function @('mod-expt-fast'), defined in the community book
 @('arithmetic-3/floor-mod/mod-expt-fast.lisp'), which should still provide
 significantly improved performance over this function.</p>

 @(def mod-expt)")

(defxdoc monitor
  :parents (break-rewrite)
  :short "To monitor the attempted application of a rule name"
  :long "@({
  Examples:
  (monitor '(:rewrite assoc-of-app) 't)
  :monitor (:rewrite assoc-of-app) t
  (monitor '(:r assoc-of-app) t)
  :monitor (:r assoc-of-app) t
  :monitor assoc-of-app t
  :monitor (:definition app) (equal (brr@ :target) '(app c d))
  :monitor (:linear rule3) t
 })

 <p>In the examples above, the first four forms are equivalent; see @(see
 keyword-commands).  Those are equivalent to the fifth form if the event
 @('assoc-of-app') corresponds to a rewrite rule, or more precisely, to a
 single @(see rune), @('(:rewrite assoc-of-app)').</p>

 @({
  General Forms:
  (monitor x condition)
  :monitor y z ; same as (monitor 'y 'z)
 })

 <p>where we focus below on the first form, in which the arguments are
 evaluated.  Above, @('x') (or more precisely, the result of evaluating @('x'))
 is a runic designator other than a theory name (see @(see theories)) and
 (the value of) @('condition') is a term, called the ``break condition.'' If
 @('x') is not a symbol then it must designate a rune corresponding to a rule
 of class @(':')@(tsee rewrite), @(':')@(tsee definition), or @(':')@(tsee
 linear).  If @('x') is a symbol then it represents all such runes that it
 designates, and there must be at least one such.  (Thus, @('x') cannot name an
 event that generates only rules of classes other than those three.)</p>

 <p>When a @(see rune) is @(see monitor)ed any attempt to apply it may result
 in an interactive break in an ACL2 ``@(see wormhole) @(see state).'' There you
 will get a chance to see how the application proceeds.  See @(see
 break-rewrite) for a description of the interactive loop entered.  Whether an
 interactive break occurs depends on the value of the break condition
 expression associated with the @(see monitor)ed @(see rune).</p>

 <p>NOTE: Some @(':rewrite') rules are considered ``simple abbreviations''; see
 @(see simple).  These can be be monitored, but only at certain times during
 the proof.  Monitoring is carried out by code inside the rewriter but
 abbreviation rules may be applied by a special purpose simplifier inside the
 so-called <i>preprocess</i> phase of a proof.  If you desire to monitor an
 abbreviation rule, a warning will be printed suggesting that you may want to
 supply the hint @(':DO-NOT '(PREPROCESS)'); see @(see hints).  Without such a
 hint, an abbreviation rule can be applied during the preprocess phase of a
 proof, and no such application will cause an interactive break.</p>

 <p>To remove a @(see rune) from the list of @(see monitor)ed @(see rune)s, use
 @('unmonitor').  To see which @(see rune)s are @(see monitor)ed and what their
 break conditions are, evaluate @('(monitored-runes)').</p>

 <p>@('Monitor'), @('unmonitor') and @('monitored-runes') are macros that
 expand into expressions involving @('state').  While these macros appear to
 return the list of @(see monitor)ed @(see rune)s this is an illusion.  They
 all print @(see monitor)ed @(see rune) information to the comment window and
 then return @(see error-triple)s instructing @('ld') to print nothing.  It is
 impossible to return the list of @(see monitor)ed @(see rune)s because it
 exists only in the @(see wormhole) @(see state) with which you interact when a
 break occurs.  This allows you to change the @(see monitor)ed @(see rune)s and
 their conditions during the course of a proof attempt without changing the
 @(see state) in which the the proof is being constructed.</p>

 <p>Unconditional break points are obtained by using the break condition
 @('t').  We now discuss conditional break points.  The break condition,
 @('condition'), must be a term that contains no free variables other than
 @('state') and that returns a single non-@('state') result.  In fact, the
 result should be @('nil'), @('t'), or a true list of commands to be fed to the
 resulting interactive break.  Whenever the system attempts to use the
 associated rule, the break condition (that is, @('condition')) is evaluated in
 the @(see wormhole) interaction @(see state).  A break occurs only if the
 result of evaluating @('condition') is non-@('nil').  If the result is a true
 list, that list is appended to the front of @('standard-oi') and hence is
 taken as the initial user commands issued to the interactive break.</p>

 <p>In order to develop effective break conditions it must be possible to
 access context sensitive information, i.e., information about the context in
 which the @(see monitor)ed @(see rune) is being tried.  The @(tsee brr@) macro
 may be used in break conditions to access such information as the term being
 rewritten and the current governing assumptions.  This information is not
 stored in the proof @(see state) but is transferred into the @(see wormhole)
 @(see state) when breaks occur.  The macro form is @('(brr@ :sym)') where
 @(':sym') is one of several keyword symbols, including @(':target') (the term
 being rewritten), @(':unify-subst') (the substitution that instantiates the
 left-hand side of the conclusion of the rule so that it is the target term),
 and @(':')@(tsee type-alist) (the governing assumptions).  See @(see
 brr@).</p>

 <p>For example,</p>

 @({
  ACL2 !>:monitor (:rewrite assoc-of-app)
                  (equal (brr@ :target) '(app a (app b c)))
 })

 <p>will monitor @('(:rewrite assoc-of-app)') but will cause an interactive
 break only when the target term, the term being rewritten, is @('(app a (app b
 c))').</p>

 <p>Because break conditions are evaluated in the interaction environment, the
 user developing a break condition for a given @(see rune) can test candidate
 break conditions before installing them.  For example, suppose an
 unconditional break has been installed on a @(see rune), that an interactive
 break has occurred and that the user has determined both that this particular
 application is uninteresting and that many more such applications will likely
 occur.  An appropriate response would be to develop an expression that
 recognizes such applications and returns @('nil').  Of course, the hard task
 is figuring out what makes the current application uninteresting.  But once a
 candidate expression is developed, the user can evaluate it in the current
 context simply to confirm that it returns @('nil').</p>

 <p>Recall that when a break condition returns a non-@('nil') true list that
 list is appended to the front of @('standard-oi').  For example,</p>

 @({
  ACL2 !>:monitor (:rewrite assoc-of-app) '(:go)
 })

 <p>will cause @('(:rewrite assoc-of-app)') to be @(see monitor)ed and will
 make the break condition be @(''(:go)').  This break condition always
 evaluates the non-@('nil') true list @('(:go)').  Thus, an interactive break
 will occur every time @('(:rewrite assoc-of-app)') is tried.  The break is fed
 the command @(':go').  Now the command @(':go') causes @('break-rewrite') to
 (a) evaluate the attempt to apply the lemma, (b) print the result of that
 attempt, and (c) exit from the interactive break and let the proof attempt
 continue.  Thus, in effect, the above @(':monitor') merely ``traces'' the
 attempted applications of the @(see rune) but never causes an interactive
 break requiring input from the user.</p>

 <p>It is possible to use this feature to cause a conditional break where the
 effective break condition is tested <b>after</b> the lemma has been tried.
 For example:</p>

 @({
  ACL2 !>:monitor (:rewrite lemma12)
                  '(:unify-subst
                    :eval$ nil
                    :ok-if (or (not (brr@ :wonp))
                               (not (equal (brr@ :rewritten-rhs) '(foo a))))
                    :rewritten-rhs)
 })

 <p>causes the following behavior when @('(:rewrite lemma12)') is tried.  A
 break always occurs, but it is fed the commands above.  The first,
 @(':unify-subst'), causes @('break-rewrite') to print out the unifying
 substitution.  Then in response to @(':eval$') @('nil') the lemma is tried but
 with all @(see rune)s temporarily @(see unmonitor)ed.  Thus no breaks will
 occur during the rewriting of the hypotheses of the lemma.  When the attempt
 has been made, control returns to @('break-rewrite') (which will print the
 results of the attempt, i.e., whether the lemma was applied, if so what the
 result is, if not why it failed).  The next command, the @(':ok-if') with its
 following expression, is a conditional exit command.  It means exit
 @('break-rewrite') if either the attempt was unsuccessful, @('(not (brr@
 :wonp))'), or if the result of the rewrite is any term other than @('(foo
 a)').  If this condition is met, the break is exited and the remaining break
 commands are irrelevant.  If this condition is not met then the next command,
 @(':rewritten-rhs'), prints the result of the application (which in this
 contrived example is known to be @('(foo a)')).  Finally, the list of supplied
 commands is exhausted but @('break-rewrite') expects more input.  Therefore,
 it begins prompting the user for input.  The end result, then, of the above
 @(':monitor') command is that the @(see rune) in question is elaborately
 traced and interactive breaks occur whenever it rewrites its target to @('(foo
 a)').</p>

 <p>We recognize that the above break condition is fairly arcane.  We suspect
 that with experience we will develop some useful idioms.  For example, it is
 straightforward now to define macros that monitor @(see rune)s in the ways
 suggested by the following names: @('trace-rune'), @('break-if-target-is'),
 and @('break-if-result-is').  For example, the last could be defined as</p>

 @({
  (defmacro break-if-result-is (rune term)
    `(monitor ',rune
              '(quote (:eval :ok-if
                             (not (equal (brr@ :rewritten-rhs) ',term))))))
 })

 <p>(Note however that the submitted term must be in translated form.)</p>

 <p>Since we don't have any experience with this kind of control on lemmas we
 thought it best to provide a general (if arcane) mechanism and hope that the
 ACL2 community will develop the special cases that we find most
 convenient.</p>")

(defxdoc monitored-runes
  :parents (break-rewrite)
  :short "Print the @(see monitor)ed @(see rune)s and their break conditions"
  :long "@({
  Example and General Form:
  :monitored-runes
 })

 <p>This macro prints a list, each element of which is of the form @('(rune
 condition)'), showing each @(see monitor)ed @(see rune) and its current break
 condition.</p>")

(defxdoc msg
  :parents (io acl2-built-ins)
  :short "Construct a ``message'' suitable for the @('~@') directive of @(tsee
  fmt)"
  :long "<p>See @(see fmt) for background on formatted printing with ACL2.</p>

 <p>In short: for a call @('(msg s arg0 arg1 arg2 ...')), @('s') should be a
 string suitable as an argument to @(tsee fmt) and @('(arg0 arg1 arg2 ...)')
 should be the bindings of @('#\\0'), @('#\\1'), @('#\\2'), and so on.  See
 @(see msgp) for a weak recognizer of objects returned by @('msg').  Now, for a
 more careful explanation:</p>

 <p>We document @('msg') precisely below, but first, we give an informal
 introduction and illustrate with an example.  Suppose you are writing a
 program that is to do some printing.  Typically, you will either pass the ACL2
 state around (see @(see programming-with-state)) and use formatted printing
 functions that take the state as an argument (see @(see fmt))), or else you
 might avoid using state by calling the utility, @(tsee cw), to do your
 printing.  Alternatively, you might print error messages upon encountering
 illegal situations; see @(see er).  But there are times where instead of
 printing immediately, you may prefer to pass messages around, for example to
 accumulate them before printing a final message.  In such cases, it may be
 desirable to construct ``message'' objects to pass around.</p>

 <p>For example, consider the following pair of little programs.  The first
 either performs a computation or prints an error, and the second calls the
 first on two inputs.</p>

 @({
  (defun invert1 (x)
    (if (consp x)
        (cons (cdr x) (car x))
      (prog2$ (cw \"ERROR: ~x0 expected a cons, but was given ~x1.~|\"
                  'invert1 x)
              nil)))

  (defun invert2 (x1 x2)
    (list (invert1 x1) (invert1 x2)))
 })

 <p>For example:</p>

 @({
    ACL2 !>(invert1 '(3 . 4))
    (4 . 3)
    ACL2 !>(invert1 'a)
    ERROR: INVERT1 expected a cons, but was given A.
    NIL
    ACL2 !>(invert2 '(3 . 4) '(5 . 6))
    ((4 . 3) (6 . 5))
    ACL2 !>(invert2 'a 'b)
    ERROR: INVERT1 expected a cons, but was given A.
    ERROR: INVERT1 expected a cons, but was given B.
    (NIL NIL)
    ACL2 !>
 })

 <p>Notice that when there are errors, there is no attempt to explain that
 these are due to a call of @('invert2').  That could be fixed, of course, by
 arranging for @('invert2') to print its own error; but for complicated
 programs it can be awkward to coordinate printing from many sources.  So let's
 try a different approach.  This time, the first function returns two results.
 The first result is an ``error indicator'' &mdash; either a message object or
 @('nil') &mdash; while the second is the computed value (only of interest when
 the first result is @('nil')).  Then the higher-level function can print a
 single error message that includes the error message(s) from the lower-level
 function, as shown below.</p>

 @({
  (defun invert1a (x)
    (if (consp x)
        (mv nil
            (cons (cdr x) (car x)))
      (mv (msg \"ERROR: ~x0 expected a cons, but was given ~x1.~|\"
               'invert1a x)
          nil)))

  (defun invert2a (x1 x2)
    (mv-let (erp1 y1)
            (invert1a x1)
            (mv-let (erp2 y2)
                    (invert1a x2)
                    (if erp1
                        (if erp2
                            (cw \"~x0 failed with two errors:~|  ~@1  ~@2\"
                                'invert2a erp1 erp2)
                          (cw \"~x0 failed with one error:~|  ~@1\"
                              'invert2a erp1))
                      (if erp2
                          (cw \"~x0 failed with one error:~|  ~@1\"
                              'invert2a erp2)
                        (list y1 y2))))))
 })

 <p>For example:</p>

 @({
    ACL2 !>(invert2a '(3 . 4) '(5 . 6))
    ((4 . 3) (6 . 5))
    ACL2 !>(invert2a '(3 . 4) 'b)
    INVERT2A failed with one error:
      ERROR: INVERT1A expected a cons, but was given B.
    NIL
    ACL2 !>(invert2a 'a 'b)
    INVERT2A failed with two errors:
      ERROR: INVERT1A expected a cons, but was given A.
      ERROR: INVERT1A expected a cons, but was given B.
    NIL
    ACL2 !>
 })

 <p>If you study the example above, you might well understand @('msg').  But we
 conclude with precise documentation.</p>

 @({
  General Form:
  (msg str arg1 ... argk)
 })

 <p>where @('str') is a string and @('k') is at most 9.</p>

 <p>This macro returns a pair suitable for giving to the @('fmt') directive
 @('~@').  Thus, suppose that @('#\\c') is bound to the value of @('(msg str
 arg1 ... argk)'), where @('c') is a character and @('k') is at most 9.  Then
 the @('fmt') directive @('~@c') will print out the string, @('str'), in the
 context of the alist in which the successive @('fmt') variables @('#\\0'),
 @('#\\1'), ..., @('#\\k') are bound to the successive elements of @('(arg1
 ... argk)').</p>")

(defxdoc msgp
  :parents (io acl2-built-ins)
  :short "Weak recognizer for a ``message''"
  :long "<p>The form @('(msgp x)') evaluates to true when @('x') evaluates
 either to a string or to a null-terminated list (see @(see true-listp)) whose
 first element is a string.  Thus, @('msgp') distinguishes <i>messages</i>
 &mdash; that is, values suitable as arguments for @('~@') directives of @(tsee
 fmt) &mdash; from Booleans and other values that are obviously not messages.
 Note that @('msgp') should always hold for the output of the macro, @('msg');
 see @(see msg).</p>

 @(def msgp)")

(defxdoc must-be-equal
  :parents (mbe acl2-built-ins)
  :short "Attach code for execution"
  :long "<p>The form @('(must-be-equal logic exec)') evaluates to @('logic') in
 the ACL2 logic but evaluates to @('exec') in raw Lisp.  The point is to be
 able to write one definition to reason about logically but another for
 evaluation.  Please see @(see mbe) and see @(see mbt) for appropriate macros
 to use, rather than calling @('must-be-equal') directly, since it is easy to
 commute the arguments of @('must-be-equal') by accident.</p>

 <p>In essence, the guard for @('(must-be-equal x y)') is @('(equal x y)').
 However, note that @('must-be-equal') is a macro: @('(must-be-equal logic
 exec)') expands to @('(mbe1 exec logic)'), which expands to a call of @(tsee
 return-last).</p>")

(defxdoc mutual-recursion
  :parents (events programming defun)
  :short "Define some mutually recursive functions"
  :long "@({
  Example:
  (mutual-recursion
   (defun evenlp (x)
     (if (consp x) (oddlp (cdr x)) t))
   (defun oddlp (x)
     (if (consp x) (evenlp (cdr x)) nil)))

  General Form:
  (mutual-recursion def1 ... defn)
 })

 <p>where each @('defi') is a call of @(tsee defun), @(tsee defund), @(tsee
 defun-nx), or @('defund-nx').</p>

 <p>When mutually recursive functions are introduced it is necessary to do the
 termination analysis on the entire clique of definitions.  Each @(tsee defun)
 form specifies its own measure, either with the @(':measure') keyword
 @('xarg') (see @(see xargs)) or by default to @(tsee acl2-count).  When a
 function in the clique calls a function in the clique, the measure of the
 callee's actuals must be smaller than the measure of the caller's formals
 &mdash; just as in the case of a simply recursive function.  But with mutual
 recursion, the callee's actuals are measured as specified by the callee's
 @(tsee defun) while the caller's formals are measured as specified by the
 caller's @(tsee defun).  These two measures may be different but must be
 comparable in the sense that @(tsee o<) decreases through calls.</p>

 <p>If you want to specify @(':')@(tsee hints) or @(':guard-hints') (see @(see
 xargs)), you can put them in the @(tsee xargs) declaration of any of the
 @(tsee defun) forms, as the @(':')@(tsee hints) from each form will be
 appended together, as will the @(tsee guard-hints) from each form.</p>

 <p>You may find it helpful to use a lexicographic order, the idea being to
 have a measure that returns a list of two arguments, where the first takes
 priority over the second.  Here is an example.</p>

 @({
  (include-book \"ordinals/lexicographic-ordering\" :dir :system)

  (encapsulate
   ()
   (set-well-founded-relation l<) ; will be treated as LOCAL

   (mutual-recursion
    (defun foo (x)
      (declare (xargs :measure (list (acl2-count x) 1)))
      (bar x))
    (defun bar (y)
      (declare (xargs :measure (list (acl2-count y) 0)))
      (if (zp y) y (foo (1- y))))))
 })

 <p>The @(tsee guard) analysis must also be done for all of the functions at
 the same time.  If any one of the @(tsee defun)s specifies the @(':')@(tsee
 verify-guards) @('xarg') to be @('nil'), then @(see guard) verification is
 omitted for all of the functions.  Similarly, if any one of the @(tsee defun)s
 specifies the @(':non-executable') @('xarg') to be @('t'), or if any of the
 definitions uses @(tsee defun-nx) or @('defund-nx'), then every one of the
 definitions will be treated as though it specifies a @(':non-executable')
 @('xarg') of @('t').</p>

 <p>Technical Note: Each @('defi') above must be a call of @(tsee defun),
 @(tsee defund), @(tsee defun-nx), or @('defund-nx').  In particular, it is not
 permitted for a @('defi') to be an arbitrary form that macroexpands into a
 @(tsee defun) form.  This is because @('mutual-recursion') is itself a macro,
 and since macroexpansion occurs from the outside in, at the time
 @('(mutual-recursion def1 ... defk)') is expanded the @('defi') have not yet
 been macroexpanded.</p>

 <p>Suppose you have defined your own @(tsee defun)-like macro and wish to use
 it in a @('mutual-recursion') expression.  Well, you can't.  (!)  But you can
 define your own version of @('mutual-recursion') that allows your @(tsee
 defun)-like form.  Here is an example.  Suppose you define</p>

 @({
  (defmacro my-defun (&rest args) (my-defun-fn args))
 })

 <p>where @('my-defun-fn') takes the arguments of the @('my-defun') form and
 produces from them a @(tsee defun) form.  As noted above, you are not allowed
 to write @('(mutual-recursion (my-defun ...) ...)').  But you can define the
 macro @('my-mutual-recursion') so that</p>

 @({
  (my-mutual-recursion (my-defun ...) ... (my-defun ...))
 })

 <p>expands into @('(mutual-recursion (defun ...) ... (defun ...))') by
 applying @('my-defun-fn') to each of the arguments of
 @('my-mutual-recursion').</p>

 @({
  (defun my-mutual-recursion-fn (lst)
    (declare (xargs :guard (alistp lst)))

  ; Each element of lst must be a consp (whose car, we assume, is always
  ; MY-DEFUN).  We apply my-defun-fn to the arguments of each element and
  ; collect the resulting list of DEFUNs.

    (cond ((atom lst) nil)
          (t (cons (my-defun-fn (cdr (car lst)))
                   (my-mutual-recursion-fn (cdr lst))))))

  (defmacro my-mutual-recursion (&rest lst)

  ; Each element of lst must be a consp (whose car, we assume, is always
  ; MY-DEFUN).  We obtain the DEFUN corresponding to each and list them
  ; all inside a MUTUAL-RECURSION form.

    (declare (xargs :guard (alistp lst)))
    (cons 'mutual-recursion (my-mutual-recursion-fn lst))).
 })")

(defxdoc mutual-recursion-proof-example
  :parents (tutorial5-miscellaneous-examples mutual-recursion)
  :short "A small proof about mutually recursive functions"
  :long "<p>Sometimes one wants to reason about mutually recursive functions.
 Although this is possible in ACL2, it can be a bit awkward.  This example is
 intended to give some ideas about how one can go about such proofs.</p>

 <p>For an introduction to mutual recursion in ACL2, see @(see
 mutual-recursion).</p>

 <p>We begin by defining two mutually recursive functions: one that collects
 the variables from a @(see term), the other that collects the variables from a
 list of @(see term)s.  We actually imagine the @(see term) argument to be a
 @('pseudo-termp'); see @(see pseudo-termp).</p>

 @({
  (mutual-recursion

  (defun free-vars1 (term ans)
    (cond ((atom term)
           (add-to-set-eq term ans))
          ((fquotep term) ans)
          (t (free-vars1-lst (cdr term) ans))))

  (defun free-vars1-lst (lst ans)
    (cond ((atom lst) ans)
          (t (free-vars1-lst (cdr lst)
                             (free-vars1 (car lst) ans)))))

  )
 })

 <p>Now suppose that we want to prove the following theorem.</p>

 @({
  (defthm symbol-listp-free-vars1-try-1
    (implies (and (pseudo-termp x)
                  (symbol-listp ans))
             (symbol-listp (free-vars1 x ans))))
 })

 <p>Often ACL2 can generate a proof by induction based on the structure of
 definitions of function symbols occurring in the conjecture.  In this case,
 ACL2 chooses to use an induction scheme suggested by @('(symbol-listp ans)'),
 and sadly, that doesn't work.  If one were doing this proof with pencil and
 paper, one would be more likely to prove a combination of the conjecture above
 and an analogous conjecture about free-vars1-lst.  Feel free to try a pencil
 and paper proof!  Or you can read on, to see how one can get ACL2 to do such a
 proof after all.</p>

 <p>The trick is to define a function that suggests an appropriate induction.
 The induction suggested is based on the if-then-else structure of the
 function's definition, where inductive hypotheses are generated for recursive
 calls &mdash; below we explain how that works for this function.</p>

 @({
  (defun symbol-listp-free-vars1-induction (x ans)
    (if (atom x)
  ; then we just make sure x and ans aren't considered irrelevant:
        (list x ans)
      (list (symbol-listp-free-vars1-induction (car x) ans)
            (symbol-listp-free-vars1-induction (cdr x) ans)
            (symbol-listp-free-vars1-induction (cdr x)
                                               (free-vars1 (car x) ans)))))
 })

 <p>The if-then-else structure of this function generates two cases.  In one
 case, @('(atom x)') is true, and the theorem to be proved should be proved
 under no additional hypotheses except for @('(atom x)'); in other words,
 @('(atom x)') gives us the base case of the induction.  In the other case,
 @('(not (atom x))') is assumed together with three instances of the theorem to
 be proved, one for each recursive call.  So, one instance substitutes @('(car
 x)') for @('x'); one substitutes @('(cdr x)') for @('x'); and the third
 substitutes @('(cdr x)') for @('x') and @('(free-vars1 (car x) ans)') for
 @('ans').  If you think about how you would go about a hand proof of the
 theorem to follow, you'll likely come up with a similar scheme.</p>

 <p>We now prove the two theorems together as a conjunction, because the
 inductive hypotheses for one are sometimes needed in the proof of the other
 (even when you do this proof on paper!).</p>

 @({
  (defthm symbol-listp-free-vars1
    (and (implies (and (pseudo-termp x)
                       (symbol-listp ans))
                  (symbol-listp (free-vars1 x ans)))
         (implies (and (pseudo-term-listp x)
                       (symbol-listp ans))
                  (symbol-listp (free-vars1-lst x ans))))
    :hints
    ((\"Goal\" :induct (symbol-listp-free-vars1-induction x ans))))
 })

 <p>The above works, but we conclude by illustrating a more efficient approach,
 in which we restrict to appropriate inductive hypotheses for each case.</p>

 @({
  (ubt 'symbol-listp-free-vars1-induction)

  (defun symbol-listp-free-vars1-induction (flg x ans)

  ; Flg is nil if we are ``thinking'' of a single term.

    (if (atom x) ; whether x is a single term or a list of terms
        (list x ans)
      (if flg ; i.e., if x is a list of terms
          (list (symbol-listp-free-vars1-induction nil (car x) ans)
                (symbol-listp-free-vars1-induction t
                                                   (cdr x)
                                                   (free-vars1 (car x) ans)))
        (symbol-listp-free-vars1-induction t (cdr x) ans))))
 })

 <p>We now state the theorem as a conditional, so that it can be proved nicely
 using the @(see induction) scheme that we have just coded.  The prover will
 not store an @(tsee IF) @(see term) as a @(see rewrite) rule, but that's OK
 (provided we tell it not to try), because we're going to derive the
 corollaries of interest later and make <b>them</b> into @(see rewrite)
 rules.</p>

 @({
  (defthm symbol-listp-free-vars1-flg
    (if flg
        (implies (and (pseudo-term-listp x)
                      (symbol-listp ans))
                 (symbol-listp (free-vars1-lst x ans)))
      (implies (and (pseudo-termp x)
                    (symbol-listp ans))
               (symbol-listp (free-vars1 x ans))))
    :hints
    ((\"Goal\" :induct (symbol-listp-free-vars1-induction flg x ans)))
    :rule-classes nil)
 })

 <p>And finally, we may derive the theorems we are interested in as immediate
 corollaries.</p>

 @({
  (defthm symbol-listp-free-vars1
    (implies (and (pseudo-termp x)
                  (symbol-listp ans))
             (symbol-listp (free-vars1 x ans)))
    :hints ((\"Goal\" :by (:instance symbol-listp-free-vars1-flg
                                   (flg nil)))))

  (defthm symbol-listp-free-vars1-lst
    (implies (and (pseudo-term-listp x)
                  (symbol-listp ans))
             (symbol-listp (free-vars1-lst x ans)))
    :hints ((\"Goal\" :by (:instance symbol-listp-free-vars1-flg
                                   (flg t)))))

 })

 <p>You may find @(see community-books) that help you to automate this kind of
 reasoning about mutually recursive functions.  See for example @(see
 make-flag).</p>")

(defxdoc mv
  :parents (basics acl2-built-ins)
  :short "Returning a multiple value"
  :long "<p>@('Mv') is the mechanism provided by ACL2 for returning two or more
 values.  Logically, @('(mv x1 x2 ... xn)') is the same as @('(list x1 x2
 ... xn)'), a list of the indicated values.  However, ACL2 avoids the cost of
 building this list structure, with the cost that @('mv') may only be used in a
 certain style in definitions: if a function ever returns using @('mv') (either
 directly, or by calling another function that returns a multiple value), then
 this function must always return the same number of values.</p>

 <p>For more explanation of the multiple value mechanism, see @(see mv-let).
 Also see @(see mv-list) for a way to convert a multiple value into an ordinary
 list.</p>

 <p>ACL2 does not support the Common Lisp construct @('values'), whose logical
 meaning seems difficult to characterize.  @('Mv') is the ACL2 analogue of that
 construct.</p>")

(defxdoc mv-let
  :parents (mv basics acl2-built-ins)
  :short "Calling multi-valued ACL2 functions"
  :long "@({
  Example Form:
  (mv-let (x y z)              ; local variables
          (mv 1 2 3)           ; multi-valued expression
          (declare (ignore y)) ; optional declarations
          (cons x z))          ; body
 })

 <p>The form above binds the three ``local variables,'' @('x'), @('y'), and
 @('z'), to the three results returned by the multi-valued expression and then
 evaluates the body.  The result is @(''(1 . 3)').  The second local, @('y'),
 is @(see declare)d @('ignore')d.  The multi-valued expression can be any ACL2
 expression that returns @('k') results, where @('k') is the number of local
 variables listed.  Often however it is simply the application of a
 @('k')-valued function.  @('Mv-let') is the standard way to invoke a
 multi-valued function when the caller must manipulate the vector of results
 returned.</p>

 @({
  General Form:
  (mv-let (var1 ... vark)
          term
          body)
  or
  (mv-let (var1 ... vark)
          term
          (declare ...) ... (declare ...)
          body)
 })

 <p>where the @('vari') are distinct variables, @('term') is a term that
 returns @('k') results and mentions only variables bound in the environment
 containing the @('mv-let') expression, and @('body') is a term mentioning only
 the @('vari') and variables bound in the environment containing the
 @('mv-let').  Each @('vari') must occur in @('body') unless it is @(see
 declare)d @('ignore')d or @('ignorable') in one of the optional @(tsee
 declare) forms, unless this requirement is turned off; see @(see
 set-ignore-ok).  The value of the @('mv-let') term is the result of evaluating
 @('body') in an environment in which the @('vari') are bound, in order, to the
 @('k') results obtained by evaluating @('term') in the environment containing
 the @('mv-let').</p>

 <p>Here is an extended example that illustrates both the definition of a
 multi-valued function and the use of @('mv-let') to call it.  Consider a
 simple binary tree whose interior nodes are @(tsee cons)es and whose leaves
 are non-@(tsee cons)es.  Suppose we often need to know the number, @('n'), of
 interior nodes of such a tree; the list, @('syms'), of symbols that occur as
 leaves; and the list, @('ints'), of integers that occur as leaves.  (Observe
 that there may be leaves that are neither symbols nor integers.)  Using a
 multi-valued function we can collect all three results in one pass.</p>

 <p>Here is the first of two definitions of the desired function.  This
 definition is ``primitive recursive'' in that it has only one argument and
 that argument is reduced in size on every recursion.</p>

 @({
  (defun count-and-collect (x)

  ; We return three results, (mv n syms ints) as described above.

    (cond ((atom x)

  ; X is a leaf.  Thus, there are 0 interior nodes, and depending on
  ; whether x is a symbol, an integer, or something else, we return
  ; the list containing x in as the appropriate result.

           (cond ((symbolp x) (mv 0 (list x) nil))
                 ((integerp x)(mv 0 nil      (list x)))
                 (t           (mv 0 nil      nil))))
          (t

  ; X is an interior node.  First we process the car, binding n1, syms1, and
  ; ints1 to the answers.

             (mv-let (n1 syms1 ints1)
                     (count-and-collect (car x))

  ; Next we process the cdr, binding n2, syms2, and ints2.

                     (mv-let (n2 syms2 ints2)
                             (count-and-collect (car x))

  ; Finally, we compute the answer for x from those obtained for its car
  ; and cdr, remembering to increment the node count by one for x itself.

                             (mv (1+ (+ n1 n2))
                                 (append syms1 syms2)
                                 (append ints1 ints2)))))))
 })

 <p>This use of a multiple value to ``do several things at once'' is very
 common in ACL2.  However, the function above is inefficient because it @(see
 append)s @('syms1') to @('syms2') and @('ints1') to @('ints2'), copying the
 list structures of @('syms1') and @('ints1') in the process.  By adding
 ``accumulators'' to the function, we can make the code more efficient.</p>

 @({
  (defun count-and-collect1 (x n syms ints)
    (cond ((atom x)
           (cond ((symbolp x) (mv n (cons x syms) ints))
                 ((integerp x) (mv n syms (cons x ints)))
                 (t (mv n syms ints))))
          (t (mv-let (n2 syms2 ints2)
                     (count-and-collect1 (cdr x) (1+ n) syms ints)
                     (count-and-collect1 (car x) n2 syms2 ints2)))))
 })

 <p>We claim that @('(count-and-collect x)') returns the same triple of results
 as @('(count-and-collect1 x 0 nil nil)').  The reader is urged to study this
 claim until convinced that it is true and that the latter method of computing
 the results is more efficient.  One might try proving the theorem</p>

 @({
  (defthm count-and-collect-theorem
    (equal (count-and-collect1 x 0 nil nil) (count-and-collect x))).
 })

 <p>Hint: the inductive proof requires attacking a more general theorem.</p>

 <p>ACL2 does not support the Common Lisp construct @('multiple-value-bind'),
 whose logical meaning seems difficult to characterize.  @('Mv-let') is the
 ACL2 analogue of that construct.  Also see @(see mv) and see @(see
 mv-list).</p>")

(defxdoc mv-list
  :parents (mv acl2-built-ins)
  :short "Converting multiple-valued result to a single-valued list"
  :long "@({
  Example Forms:
  ; Returns the list (3 4):
  (mv-list 2 (mv 3 4))

  ; Returns a list containing the three values returned by var-fn-count:
  (mv-list 3 (var-fn-count '(cons (binary-+ x y) z) nil))

  General form:
  (mv-list n term)
 })

 <p>Logically, @('(mv-list n term)') is just @('term'); that is, in the logic
 @('mv-list') simply returns its second argument.  However, the evaluation of a
 call of @('mv-list') on explicit values always results in a single value,
 which is a (null-terminated) list.  For evaluation, the term @('n') above (the
 first argument to an @('mv-list') call) must ``essentially'' (see below) be an
 integer not less than 2, where that integer is the number of values returned
 by the evaluation of @('term') (the second argument to that @('mv-list')
 call).</p>

 <p>We say ``essentially'' above because it suffices that the translation of
 @('n') to a term (see @(see trans)) be of the form @('(quote k)'), where
 @('k') is an integer greater than 1.  So for example, if @('term') above
 returns three values, then @('n') can be the expression @('3'), or @('(quote
 3)'), or even @('(mac 3)') if @('mac') is a macro defined by @('(defmacro mac
 (x) x)').  But @('n') cannot be @('(+ 1 2)'), because even though that
 expression evaluates to @('3'), nevertheless it translates to @('(binary-+ '1
 '2)'), not to @('(quote 3)').</p>

 <p>@('Mv-list') is the ACL2 analogue of the Common Lisp construct
 @('multiple-value-list').</p>

 @(def mv-list)")

(defxdoc mv-nth
  :parents (mv acl2-built-ins)
  :short "The mv-nth element (zero-based) of a list"
  :long "<p>@('(Mv-nth n l)') is the @('n')th element of @('l'), zero-based.
 If @('n') is greater than or equal to the length of @('l'), then @('mv-nth')
 returns @('nil').</p>

 <p>@('(Mv-nth n l)') has a @(see guard) that @('n') is a non-negative
 integer.</p>

 <p>@('Mv-nth') is equivalent to the Common Lisp function @(tsee nth) (although
 without the guard condition that the list is a @(tsee true-listp)), but is
 used by ACL2 to access the nth value returned by a multiply valued expression.
 For example, the following are logically equivalent:</p>

 @({
  (mv-let (erp val state)
          (read-object ch state)
          (value (list erp val)))
 })

 <p>and</p>

 @({
  (let ((erp (mv-nth 0 (read-object ch state)))
        (val (mv-nth 1 (read-object ch state)))
        (state (mv-nth 2 (read-object ch state))))
    (value (list erp val)))
 })

 <p>To see the ACL2 definition of @('mv-nth'), see @(see pf).</p>

 <p>If @('EXPR') is an expression that is multiply valued, then the form
 @('(mv-nth n EXPR)') is illegal both in definitions and in forms submitted
 directly to the ACL2 loop.  Indeed, @('EXPR') cannot be passed as an argument
 to any function (@('mv-nth') or otherwise) in such an evaluation context.  The
 reason is that ACL2 code compiled for execution does not actually create a
 list for multiple value return; for example, the @('read-object') call above
 logically returns a list of length 3, but when evaluated, it instead stores
 its three returned values without constructing a list.  In such cases you can
 use @('mv-nth') to access the corresponding list by using @('mv-list'),
 writing @('(mv-nth n (mv-list k EXPR))') for suitable @('k'), where
 @('mv-list') converts a multiple value result into the corresponding list; see
 @(see mv-list).</p>")

(defxdoc mv?
  :parents (mv acl2-built-ins)
  :short "Return one or more values"
  :long "<p>@('Mv?') is designed to work with @('mv?-let'), generalizing how
 @(tsee mv) works with @(tsee mv-let) by allowing the binding of a single
 variable.  For example, the following form is legal.</p>

 @({
  (mv?-let (y)
           (mv? (f x))
           (declare (type integer y))
           (g x y z))
 })

 <p>The expression above is equivalent to the following expression, because
 @('(mv? form)') expands to @('form') for any expression, @('form').</p>

 @({
  (let ((y (f x)))
    (declare (type integer y))
    (g x y z))
 })

 <p>Logically, @('(mv? x)') is the same as @('x'), while @('(mv? v1 v2 ...)')
 is the same as @('(list v1 v2 ...)').  Also see @(see mv) and see @(see
 mv?-let).</p>")

(defxdoc mv?-let
  :parents (mv acl2-built-ins)
  :short "Calling possibly multi-valued ACL2 functions"
  :long "<p>@('Mv?-let') is a macro that extends the macro @(tsee mv-let) by
 allowing a single variable to be bound.  Thus, the syntax is the same as that
 of @(tsee mv-let) except that @('mv?-let') is permitted to bind a single
 variable to a form that produces a single value.  The macros @('mv?-let') and
 @(tsee mv?)  are provided to facilitate the writing of macros that traffic in
 expressions that could return one or more (multiple) values.</p>

 <p>For example, the form</p>

 @({
  (mv?-let (y)
           (f x)
           (declare (type integer y))
           (g x y z))
 })

 <p>is equivalent to the following form.</p>

 @({
  (let ((y (f x)))
    (declare (type integer y))
    (g x y z))
 })

 <p>Calls of @('mv?-let') and of @(tsee mv-let) are equivalent when the first
 argument contains at least two variables; see @(see mv-let) for documentation.
 In the case of binding a single variable, the general form is</p>

 @({
  (mv?-let (var)
           term
           (declare ...) ... (declare ...)
           body)
 })

 <p>and this is equivalent to the following form (see @(see let)).</p>

 @({
  (let ((var term))
    (declare ...) ... (declare ...)
    body)
 })

 <p>Also see @(see mv?).</p>")

(defxdoc |Modeling in ACL2|
  :parents (|Pages Written Especially for the Tours|)
  :short "Modeling in ACL2"
  :long "<p><see topic='@(url |Running Models|)'><img
  src='res/tours/flying.gif'></img></see></p>

 <p><img src='res/tours/computing-machine-a.gif'></img></p>

 <p>Below we define <b>mc(s,n)</b> to be the function that <b>single-step</b>s
 <b>n</b> times from a given starting state, <b>s</b>.  In Common Lisp,
 ``mc(s,n)'' is written @('(mc s n)').</p>

 <code>
 <b>(defun mc (s n)</b>                     ; To step <b>s</b> <b>n</b> times:
  <b>(if (zp n)</b>                         ; If <b>n</b> is 0
      <b>s</b>                              ;    then return <b>s</b>
      <b>(mc (single-step s) (- n 1))))</b> ;    else step <b>single-step(s)</b>
                                                       <b>n-1</b> times.
 </code>

 <p>This is an example of a formal model in ACL2.</p>

 <p><see topic='@(url |Running Models|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |Models in Engineering|
  :parents (|Pages Written Especially for the Tours|)
  :short "Models in Engineering"
  :long "<p><img src='res/tours/bridge.gif'></img></p>

 <p>Frequently, engineers use mathematical models.  Use of such models
 frequently lead to</p>

 <p><b>better designs</b>,</p>

 <p><b>faster completion of acceptable products</b>, and</p>

 <p><b>reduced overall cost</b>,</p>

 <p>because models allow the trained user to study the design before it is
 built and analyze its properties.  Usually, testing and analyzing a model is
 cheaper and faster than fabricating and refabricating the product.</p>

 <p><img src='res/tours/bridge-analysis.gif'></img></p>")

(defxdoc |Models of Computer Hardware and Software|
  :parents (|Pages Written Especially for the Tours|)
  :short "Models of Computer Hardware and Software"
  :long "<p><see topic='@(url |A Typical State|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p><img src='res/tours/computing-machine.gif'></img></p>

 <p>Computing machines, whether hardware or software or some combination, are
 frequently modeled as ``state machines.''</p>

 <p>To so model a computing machine we must represent its <b>states</b> as
 objects in our mathematical framework.</p>

 <p><b>Transitions</b> are functions or relations on state objects.</p>

 <p>In what language shall we define these objects, functions, and
 relations?</p>

 <p>The mathematical languages we were taught in high school</p>

 <p><b>algebra</b>,</p>

 <p><b>geometry</b>,</p>

 <p><b>trigonometry</b>, and</p>

 <p><b>calculus</b></p>

 <p>are often inappropriate for modeling digital systems.  They primarily let
 us talk about numbers and continuous functions.</p>

 <p>To see what kind of expressive power we need, take a closer look at what a
 typical state contains.</p>

 <p><see topic='@(url |A Typical State|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc name
  :parents (events)
  :short "Syntactic rules on logical names"
  :long "@({
  Examples                 Counter-Examples

  PRIMEP               91         (not a symbolp)
  F-AC-23              :CHK-LIST  (in KEYWORD package)
  1AX                  *PACKAGE*  (in the Lisp Package)
  |Prime Number|       1E3        (not a symbolp)
 })

 <p>Many different ACL2 entities have names, e.g., functions, macros,
 variables, constants, packages, theorems, @(see theories), etc.  Package names
 are strings.  All other names are symbols and may not be in the
 @('\"KEYWORD\"') package.  Moreover, names of functions, macros, constrained
 functions, and constants, other than those that are predefined, must not be in
 the ``main Lisp package'' (which is (@('\"LISP\"') or @('\"COMMON-LISP\"'),
 according to whether we are following CLTL1 or CLTL2).  An analogous
 restriction on variables is given below.</p>

 <p>@('T'), @('nil'), and all names above except those that begin with
 ampersand (&amp;) are names of variables or constants.  @('T'), @('nil'), and
 those names beginning and ending with star (*) are constants.  All other such
 names are variables.</p>

 <p>Note that names that start with ampersand, such as @('&rest'), may be
 lambda list keywords and are reserved for such use whether or not they are in
 the CLTL constant @('lambda-list-keywords').  (See pg 82 of CLTL2.)  That is,
 these may not be used as variables.  Unlike constants, variables may be in the
 main Lisp package as long as they are in the original list of imports from
 that package to ACL2, the list
 @('*common-lisp-symbols-from-main-lisp-package*'), and do not belong to a list
 of symbols that are potentially ``global.''  This latter list is the value of
 @('*common-lisp-specials-and-constants*').</p>

 <p>Our restrictions pertaining to the main Lisp package take into account that
 some symbols, e.g., @('lambda-list-keywords') and @('boole-c2'), are
 ``special.''  Permitting them to be bound could have harmful effects.  In
 addition, the Common Lisp language does not allow certain manipulations with
 many symbols of that package.  So, we stay away from them, except for allowing
 certain variables as indicated above.</p>")

(defxdoc nat-listp
  :parents (numbers lists acl2-built-ins)
  :short "Recognizer for a true list of natural  numbers"
  :long "<p>The predicate @('nat-listp') tests whether its argument is a true
 list of natural numbers.</p>

 @(def nat-listp)")

(defxdoc natp
  :parents (numbers acl2-built-ins)
  :short "A recognizer for the natural numbers"
  :long "<p>The natural numbers is the set of all non-negative integers,
 @('{0,1,2,3,...}').  @('Natp') returns @('t') if and only its argument is a
 natural number, and @('nil') otherwise.</p>

 <p>The community book @(see arithmetic/natp-posp) has some lightweight rules
 for reasoning about @('posp') and @('natp'), and is included in the @(see
 arithmetic-1) library.  For a somewhat heavier and more comprehensive
 alternative, you may wish to instead see the @(see arith-equivs) book.</p>

 @(def natp)")

(defxdoc near-misses
  :parents (debugging)
  :short "Approximate event name matches"
  :long "@({
 General Form:

 (near-misses name)
 })

 <p>where @('name') is a symbol.  Community books @('\"xdoc/spellcheck\"') and
 @('\"system/event-names\"') are used automatically (by temporarily including
 them) to compute a list of names of @(see events) that approximate the given
 name.  Example:</p>

 @({
 ACL2 !>(near-misses nt)
 (NOT NTH)
 ACL2 !>
 })")

(defxdoc nested-stobjs

; WARNING: This documentation contains examples from community book
; books/system/tests/nested-stobj-tests.lisp.  If you change those examples
; here, change them also in that book.

  :parents (stobj)
  :short "Using @(see stobj)s that contain stobjs"
  :long "<p>For this topic we assume that you already understand the basics of
 single-threaded objects in ACL2.  See @(see stobj), and in particular, see
 @(see defstobj).  The latter topic mentions briefly that a stobj field can
 itself be a stobj or an array of stobjs.  That discussion is the subject of
 the present @(see documentation) topic.</p>

 <p>Our presentation is in four sections.  First we augment the documentation
 for @(tsee defstobj) by explaining how stobjs may be specified for fields in a
 new stobj definition.  Then we explain an aliasing problem, which accounts for
 a prohibition against making direct calls to accessors and updaters involving
 stobj fields of stobjs.  Next, we introduce an ACL2 primitive, @('stobj-let'),
 which provides the only way to read and write stobj components of stobjs.  The
 final section provides precise documentation for @('stobj-let').</p>

 <p>See also ACL2 community book @('demos/modeling/nested-stobj-toy-isa.lisp')
 for a worked example, which applies nested stobj structures to the problem of
 defining interpreters.  A variety of small additional examples may be found in
 ACL2 community book @('books/system/tests/nested-stobj-tests.lisp').  For
 further discussion, you are welcome to read the ``Essay on Nested Stobjs'', a
 long comment in ACL2 source file @('other-events.lisp').  However, this
 documentation topic is intended to be self-contained for those familiar with
 @(see stobj)s.</p>

 <h3>SECTION: Extension of @(tsee defstobj) to permit @(see stobj)s within
 stobjs</h3>

 <p>Recall that the @(':type') keyword of a @(tsee defstobj) field descriptor
 can be a ``type-indicator'' that specifies the type of the field as a
 type-spec (see @(see type-spec)).  For example, the following specifies an
 integer field and a field that is an array of bytes.</p>

 @({
    (defstobj st
      (int-field :type integer :initially 0)
      (ar-field :type (array unsigned-byte (10)) :initially 0))
 })

 <p>But the @(':type') of a stobj field descriptor may instead be based on a
 stobj.  For example, the following sequence of three @(see events) is legal.
 The first field descriptor of @('top'), named @('sub1-field'), illustrates one
 new kind of value for @(':type'): the name of a previously-introduced stobj,
 which here is @('sub1'). The second field descriptor of @('top'), named
 @('sub2-ar-field'), illustrates the other new kind of value for @(':type'): an
 array whose elements are specified by the name of a previously-introduced
 stobj, in this case, the stobj @('sub2').</p>

 @({
    (defstobj sub1 fld1)
    (defstobj sub2 fld2)
    (defstobj top
      (sub1-field :type sub1)
      (sub2-ar-field :type (array sub2 (10))))
 })

 <p>The @(':initially') keyword is illegal for fields whose @(':type') is a
 stobj or an array of stobjs.  Each such initial value is provided by a
 corresponding call of the stobj creator for that stobj.  In particular, in the
 case of an array of stobjs, the stobj creator is called once for each element
 of the array, so that the array elements are distinct.  For example, each
 element of @('sub2-ar-field') in the example above is initially provided by a
 separate call of @('create-sub2').  Each initial element is thus unique, and
 in particular is distinct from the initial global value of the stobj.
 Similarly, the initial global stobj for @('sub1') is distinct from the initial
 @('sub1-field') field of the global stobj for @('top'), as these result from
 separate calls of @('create-sub1').</p>

 <p>When a stobj is used in a field of another stobj, we may refer to the
 former field as a ``child stobj'' and the latter stobj as a ``parent stobj''.
 So in the example above, @('sub1-field') is a child stobj of type @('sub1')
 for parent stobj @('top'), and @('sub2-ar-field') is an array of child stobjs
 of type @('sub2') for parent stobj @('top').  A child stobj has the same
 structural shape as the global stobj of its type, but as explained above,
 these are distinct structures.  We follow standard terminology by saying
 ``isomorphic'' to indicate the same structural shape.  So for example, (the
 value of) @('sub1-field') is isomorphic to @('sub1'), though these are
 distinct structures.</p>

 <p>ACL2 enforces the following restriction, which can allow for greater
 efficiency in the raw Lisp code generated for @('stobj-let') forms, as per the
 discussion below about clearing memoization tables.  If the parent stobj is
 introduced by @(tsee defstobj) using keyword argument @(':non-memoizable t'),
 then this is required to have been the case for every child stobj as well.</p>

 <h3>SECTION: An aliasing problem</h3>

 <p>Before introducing @('stobj-let') below, we provide motivation for this
 ACL2 primitive.</p>

 <p>Consider the following @(see events).</p>

 @({
    (defstobj child fld)
    (defstobj parent
      (fld2 :type child))
 })

 <p>Now suppose we could evaluate the following code, to be run immediately
 after admitting the two @(tsee defstobj) events above.</p>

 @({
    (let* ((child (fld2 parent))
           (child (update-fld 3 child)))
      (mv child parent))
 })

 <p>Now logically there is no change to @('parent'): @('parent') is passed
 through unchanged.  We can indeed prove that fact!</p>

 @({
    (thm (equal (mv-nth 1
                        (let* ((child (fld2 parent))
                               (child (update-fld 3 child)))
                          (mv child parent)))
                parent))
 })

 <p>But recall that stobjs are updated with destructive assignments.  That is,
 we really are updating @('(fld2 parent)') to be the new value of @('child'),
 whether this is explained logically or not.  Thus, evaluation of the above
 @(tsee let*) form does in fact change the actual global stobj,
 @('parent').</p>

 <p>(Aside: Here is an explanation involving raw Lisp, for those who might find
 this useful.  We escape to raw Lisp and execute the following; note that
 @('*the-live-parent*') is the Lisp variable representing the global value of
 @('parent').</p>

 @({
  (let ((parent *the-live-parent*))
    (let* ((child (fld2 parent))
           (child (update-fld 4 child)))
      (mv child parent)))
 })

 <p>Then, in raw Lisp, @('(fld (fld2 *the-live-parent*))') evaluates to @('4'),
 illustrating the destructive update.  End of Aside.)</p>

 <p>Such aliasing can permit a change to a child stobj to cause a
 logically-inexplicable change to the parent stobj.  Similarly, unfettered
 accessing of stobj fields can result in logically inexplicable changes to the
 child stobj when the parent stobj is changed.  Thus, ACL2 disallows direct
 calls of stobj accessors and updaters for fields whose @(':type') is a stobj
 or an array of stobjs.  Instead, ACL2 provides @('stobj-let') for reading and
 writing such fields in a sound manner.</p>

 <h3>SECTION: Accessing and updating stobj fields of stobjs using
 @('stobj-let')</h3>

 <p>ACL2 provides a primitive, @('stobj-let'), to access and update stobj
 fields of stobjs, in a manner that avoids the aliasing problem discussed
 above.  In this section we provide an informal introduction to @('stobj-let'),
 using examples, to be followed in the next section by precise
 documentation.</p>

 <p>We begin by returning to a slight variant of the example above.</p>

 @({
    (defstobj child fld)
    (defstobj parent
      (fld2 :type child)
      fld3)
 })

 <p>The following form returns the result of updating the @('fld2') field of
 @('parent'), which is a stobj isomorphic to @('child'), to have a value of 3.
 Below we explain the terms ``bindings'', ``producer variables'', ``producer'',
 and ``consumer'', as well as how to understand this form.</p>

 @({
    (stobj-let
     ((child (fld2 parent)))  ; bindings
     (child)                  ; producer variable(s)
     (update-fld 3 child)     ; producer
     (update-fld3 'a parent)) ; consumer
 })

 <p>The four lines under ``@('stobj-let')'' just above can be understood as
 follows.</p>

 <ul>
 <li>Bindings:<br/>
     <blockquote>Bind @('child') to @('(fld2 parent)').</blockquote></li>
 <li>Producer variable(s) and producer:<br/>
     <blockquote>Then bind the variable, @('child'), to the value of
     the producer, @('(update-fld 3 child)').</blockquote></li>
 <li>Implicit update of parent:<br/>
     <blockquote>Update @('fld2') of @('parent') with the producer variable,
     @('child').</blockquote></li>
 <li>Consumer:<br/>
     <blockquote>Finally, return @('(update-fld3 'a
     parent)').</blockquote></li>
 </ul>

 <p>Thus, the logical expansion of the @('stobj-let') form above is the
 following expression, though this is approximate (see below).</p>

 @({
    (let ((child (fld2 parent))) ; bindings
      (let ((child (update-fld 3 child))) ; bind producer vars to producer
        (let ((parent (update-fld2 child parent))) ; implicit update of parent
          (update-fld3 'a parent))))
 })

 <p>The bindings always bind distinct names to child stobjs of a unique parent
 stobj, where the child stobj corresponds to the @(':type') associated with the
 indicated accessor in the @(tsee defstobj) form for the parent stobj.  Thus in
 this case, for the unique binding, variable @('child') is bound to the stobj
 of `type' @('child') for accessor @('fld2') of the parent stobj, @('parent').
 We refer to @('child') from the bindings as a ``stobj-let-bound variable''.
 Note also that the ``implicit extra step'' mentioned above is generated by
 macroexpansion of @('stobj-let'); it logically updates the parent with new
 child values, just before calling the consumer.  Implementation note for those
 using @(see memoization): destructive updating in raw Lisp lets us omit this
 implicit extra step, though the raw Lisp code generated for @('stobj-let')
 will clear the memoization table for every function taking the parent stobj as
 an input, if any child stobj bound in the bindings is among the producer
 variables &mdash; unless the parent stobj was introduced by @(tsee defstobj)
 using keyword argument @(':non-memoizable t').</p>

 <p>The form above is equivalent to the form displayed just below, which
 differs only in specifying an explicit stobj updater corresponding to the
 stobj accessor, @('fld2').  Here we show the default updater name, whose name
 has @('\"UPDATE-\"') prepended to the name of the accessor.  But if the
 @(':RENAMING') field of the @('defstobj') event specified a different updater
 name corresponding to @('fld2'), then that would need to be included where we
 have added @('update-fld2') below.</p>

 @({
    (stobj-let
     ((child (fld2 parent) update-fld2)) ; bindings, including updater(s)
     (child)                  ; producer variables
     (update-fld 3 child)     ; producer
     (update-fld3 'a parent)) ; consumer
 })

 <p>You can experiment using @(':')@(tsee trans1) to see the single-step
 macroexpansion of a @('stobj-let') form in the logic.  For example, here is
 how that works for a @('stobj-let') form that binds three fields and updates
 two of them.  Notice that because more than one field is updated, an @(tsee
 mv-let) form is generated to bind the two fields to their values returned by
 the producer, rather than a @(tsee let) form as previously generated.  First,
 let's introduce some events.</p>

 @({
  (defstobj child1 child1-fld)
  (defstobj child2 child2-fld)
  (defstobj child3 child3-fld)
  (defstobj mom
    (fld1 :type child1)
    (fld2 :type child2)
    (fld3 :type child3))
  ; Silly stub:
  (defun update-last-op (op mom)
    (declare (xargs :stobjs mom))
    (declare (ignore op))
    mom)
  (defun new-mom (mom)
    (declare (xargs :stobjs mom))
    (stobj-let
     ((child1 (fld1 mom))
      (child2 (fld2 mom))
      (child3 (fld3 mom)))
     (child1 child3)
     (let* ((child1 (update-child1-fld 'one child1))
            (child3 (update-child3-fld 'three child3)))
       (mv child1 child3))
     (update-last-op 'my-compute mom)))
 })

 <p>Now let's look at the single-step macroexpansion of the above
 @('stobj-let') form.</p>

 @({
  ACL2 !>:trans1 (stobj-let
                  ((child1 (fld1 mom))
                   (child2 (fld2 mom))
                   (child3 (fld3 mom)))
                  (child1 child3)
                  (let* ((child1 (update-child1-fld 'one child1))
                         (child3 (update-child3-fld 'three child3)))
                    (mv child1 child3))
                  (update-last-op 'my-compute mom))
   (PROGN$
    (LET
     ((CHILD1 (FLD1 MOM))
      (CHILD2 (FLD2 MOM))
      (CHILD3 (FLD3 MOM)))
     (DECLARE (IGNORABLE CHILD1 CHILD2 CHILD3))
     (MV-LET
        (CHILD1 CHILD3)
        (CHECK-VARS-NOT-FREE (MOM)
                             (LET* ((CHILD1 (UPDATE-CHILD1-FLD 'ONE CHILD1))
                                    (CHILD3 (UPDATE-CHILD3-FLD 'THREE CHILD3)))
                                   (MV CHILD1 CHILD3)))
        (LET* ((MOM (UPDATE-FLD1 CHILD1 MOM))
               (MOM (UPDATE-FLD3 CHILD3 MOM)))
              (CHECK-VARS-NOT-FREE (CHILD1 CHILD2 CHILD3)
                                   (UPDATE-LAST-OP 'MY-COMPUTE MOM))))))
  ACL2 !>
 })

 <p>If you try to evaluate a @('stobj-let') form directly in the top-level
 loop, rather than from within a function body, you will get an error.  The
 example above illustrates how @('stobj-let') may be used in function bodies;
 here is another example, presented using an edited log.</p>

 @({
    ACL2 !>(defstobj child fld)

    Summary
    Form:  ( DEFSTOBJ CHILD ...)
    Rules: NIL
    Time:  0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
     CHILD
    ACL2 !>(defstobj parent
             (fld2 :type child)
             fld3)

    Summary
    Form:  ( DEFSTOBJ PARENT ...)
    Rules: NIL
    Time:  0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
     PARENT
    ACL2 !>(defun f (parent)
             (declare (xargs :stobjs parent))
             (stobj-let
              ((child (fld2 parent)))   ; bindings
              (child)                   ; producer variables
              (update-fld 3 child)      ; producer
              (update-fld3 'a parent))) ; consumer
    [[output omitted]]
     F
    ACL2 !>(f parent)
    <parent>
    ACL2 !>(defun check-f (parent)
             ; returns the value of the field of the child stobj
             (declare (xargs :stobjs parent))
             (stobj-let
              ((child (fld2 parent))) ; bindings
              (val)                   ; producer variables
              (fld child)             ; producer
              val))                   ; consumer
    [[output omitted]]
     CHECK-F
    ACL2 !>(check-f parent)
    3
    ACL2 !>
 })

 <p>Notice that the second function defined above, @('check-f'), uses a
 @('stobj-let') form that returns an ordinary value: it reads a value from a
 child stobj, but does not write to the child stobj, as indicated by the lack
 of a child stobj among the producer variables.  So for that @('stobj-let')
 form, there is no implicit extra step.</p>

 <p>We labeled a @('stobj-let') expansion above as ``approximate'' for two
 reasons, which we give here informally.  (Now you know how to apply
 @(':')@(tsee trans1) to that @('stobj-let') call to see the precise
 expansion.)  First, @('stobj-let') declares the stobj-let-bound variables to
 be @('ignorable') for the top @('let') bindings.  Second, and more
 importantly, @('stobj-let') imposes the following restrictions on the producer
 and consumer, to avoid the aliasing problem: it disallows references to the
 parent stobj in the producer and it also disallows references to any bound
 stobj (i.e., bound in the bindings) in the consumer.</p>

 <p>We conclude this section with examples based on a slight variation of the
 nested stobj example from the first section above.  These events can also be
 found in ACL2 community book @('books/system/tests/nested-stobj-tests.lisp'),
 immediately under the following comment:</p>

 @({
  ; As promised in :doc stobj-let, we begin with an example from that :doc.
 })

 <p>Note that some lemmas were needed in order to complete the @(see guard)
 proof for the function @('update-top'), which may be found in the above file;
 they are omitted below.</p>

 <p>First we introduce three stobjs.</p>

 @({
    (defstobj kid1 fld1)
    (defstobj kid2 fld2)
    (defstobj mom
      (kid1-field :type kid1)
      (kid2-ar-field :type (array kid2 (5)))
      last-op)
 })

 <p>The next function takes a given index and a @('mom') stobj, and swaps the
 value stored in the stobj in @('mom')'s @('kid2-ar-field') array at that index
 with the value stored in the stobj in @('mom')'s @('kid1-field') field.</p>

 @({
    (defun mom-swap-fields (index mom)
      (declare (xargs :stobjs mom
                      :guard (and (natp index)
                                  (< index (kid2-ar-field-length mom)))))
      (stobj-let
       ((kid1 (kid1-field mom))
        (kid2 (kid2-ar-fieldi index mom)))
       (kid1 kid2)
       (let* ((val1 (fld1 kid1))
              (val2 (fld2 kid2))
              (kid1 (update-fld1 val2 kid1))
              (kid2 (update-fld2 val1 kid2)))
         (mv kid1 kid2))
       (update-last-op 'swap mom)))
 })

 <p>Function @('mom.kid1-fld1') stores a given value in the given @('mom')'s
 @('kid1-fld1') field.</p>

 @({
    (defun mom.kid1-fld1 (val mom)
      (declare (xargs :stobjs mom))
      (stobj-let
       ((kid1 (kid1-field mom)))
       (kid1)
       (update-fld1 val kid1)
       (update-last-op val mom)))
 })

 <p>We next combine the two functions above, according to an @('op') argument,
 as indicated by the following definition.</p>

 @({
    (defun update-mom (op mom)
      (declare (xargs :stobjs mom))
      (cond ((and (consp op)
                  (eq (car op) 'swap)
                  (natp (cdr op))
                  (< (cdr op) (kid2-ar-field-length mom)))
             (mom-swap-fields (cdr op) mom))
            (t (mom.kid1-fld1 op mom))))
 })

 <p>The following checker function uses a @('stobj-let') form like the ones
 above, a major difference being that the producer variable is not a stobj,
 since the producer does not modify any stobjs.</p>

 @({
    (defun check-update-mom (index val1 val2 last-op mom)
        (declare (xargs :stobjs mom
                        :mode :program
                        :guard
                        (or (null index)
                            (and (natp index)
                                 (< index (kid2-ar-field-length mom))))))
        (and (equal (last-op mom) last-op)
             (stobj-let
              ((kid1 (kid1-field mom))
               (kid2 (kid2-ar-fieldi index mom)))
              (val) ; producer variables
              (and (equal val1 (fld1 kid1))
                   (equal val2 (fld2 kid2)))
              val)))
 })

 <p>Now let us run our update function to populate some fields within the
 @('mom') stobj.</p>

 @({
    (let* ((mom ; set mom to (3 (x0 x1 x2 x3 x4))
             (update-mom 3 mom))
            (mom ; set mom to (x1 (x0 3 x2 x3 x4))
             (update-mom '(swap . 1) mom))
            (mom ; set mom to (7 (x0 3 x2 x3 x4))
             (update-mom 7 mom))
            (mom ; set mom to (x0 (7 3 x2 x3 x4))
             (update-mom '(swap . 0) mom))
            (mom ; set mom to (5 (7 3 x2 x3 x4))
             (update-mom 5 mom))
            (mom ; set mom to (7 (5 3 x2 x3 x4))
             (update-mom '(swap . 0) mom)))
       mom)
 })

 <p>Are the above values of 7, 5, and 3 as expected, with a last operation
 being a swap?  Yes!</p>

 @({
    ACL2 !>(and (check-update-mom 0 7 5 'swap mom)
                (check-update-mom 1 7 3 'swap mom))
    T
    ACL2 !>
 })

 <p>Notice that above, we never tried to access two different entries of the
 array.  This can be done, but we need to bind two different stobjs to those
 fields.  Fortunately, congruent stobjs make this possible; see @(see
 defstobj), in particular the discussion of congruent stobjs.  Since we want to
 bind two stobjs to values in the array that are isomorphic to the stobj
 @('kid2'), we introduce a stobj congruent to @('kid2').</p>

 @({
    (defstobj kid2a fld2a :congruent-to kid2)
 })

 <p>Then we can define our swapping function as follows.  The @(see guard)
 proof obligation includes the requirement that the two indices be distinct,
 again to avoid an aliasing problem.</p>

 @({
    (defun mom-swap-indices (i1 i2 mom)
      (declare (xargs :stobjs mom
                      :guard (and (natp i1)
                                  (< i1 (kid2-ar-field-length mom))
                                  (natp i2)
                                  (< i2 (kid2-ar-field-length mom))
                                  (not (equal i1 i2)))))
      (stobj-let
       ((kid2 (kid2-ar-fieldi i1 mom))
        (kid2a (kid2-ar-fieldi i2 mom)))
       (kid2 kid2a)
       (let* ((val2 (fld2 kid2))
              (val2a (fld2 kid2a))
              (kid2 (update-fld2 val2a kid2))
              (kid2a (update-fld2 val2 kid2a)))
         (mv kid2 kid2a))
       mom))
 })

 <p>The aforementioned community book,
 @('books/system/tests/nested-stobj-tests.lisp'), contains a corresponding
 checker immediately following this definition.</p>

 <h3>SECTION: Precise documentation for @('stobj-let')</h3>

 @({
  General Form:
  (stobj-let
   BINDINGS
   PRODUCER-VARIABLES
   PRODUCER
   CONSUMER)
 })

 <p>where @('PRODUCER-VARIABLES') is a non-empty true list of legal variable
 names without duplicates, @('PRODUCER') and @('CONSUMER') are expressions, and
 @('BINDINGS') is a list subject to the following requirements.</p>

 <p>@('BINDINGS') is a non-empty true list of tuples, each of which has the
 form @('(VAR ACCESSOR)') or @('(VAR ACCESSOR UPDATER)').  There is a stobj
 name, @('ST'), previously introduced by @(tsee defstobj) (not @(tsee
 defabsstobj)), such that each @('accessor') is of the form @('(ACC ST)') or
 @('(ACCi I ST)'), with the same stobj name (@('ST')) for each binding.  Each
 of these accessors and (if supplied) updaters is a stobj accessor for the same
 stobj, which is typically @('ST') but may be a stobj congruent to @('ST').  In
 the case @('(ACC ST)'), @('ACC') is the accessor for a non-array field.  In
 the case @('(ACCi I ST)'), @('ACCi') is the accessor for an array field and
 @('I') is either a variable, a natural number, a list @('(quote N)') where
 @('N') is a natural number, or a symbol introduced by @(tsee defconst).  If
 @('UPDATER') is supplied, then it is a symbol that is the name of the stobj
 updater for the field of @('ST') accessed by @('ACCESSOR').  If @('UPDATER')
 is not supplied, then for the discussion below we consider it to be,
 implicitly, the symbol in the same package as the function symbol of
 @('ACCESSOR') (i.e., @('ACC') or @('ACCi')), obtained by prepending the string
 @('\"UPDATE-\"') to the @(tsee symbol-name) of that function symbol.  Finally,
 @('ACCESSOR') has a @(see signature) specifying a return value that is either
 @('VAL') or is a stobj that is congruent to @('VAL'). (This means that only
 stobjs may be bound in these bindings.)</p>

 <p>If the conditions above are met, then the General Form expands to the one
 of the following expressions, depending on whether the list
 @('PRODUCER-VARIABLES') has one member or more than one member, respectively.
 (But see below for extra code that may be inserted if there are stobj array
 accesses in @('BINDINGS').)  Here we write @('STOBJ-LET-BOUND-VARS') for the
 list of variables @('VAR') discussed above, i.e., for @('(strip-cars
 BINDINGS)').  And, we write @('UPDATES') for the result of mapping through
 @('PRODUCER-VARIABLES') and, for each variable @('VAR') that has a binding
 @('(VAR ACCESSOR UPDATER)') in @('BINDINGS') (where @('UPDATER') may be
 implicit, as discussed above), collect into @('UPDATES') the tuple @('(ST
 (UPDATER VAR ST))').</p>

 <p>For @('PRODUCER-VARIABLES') = @('(PRODUCER-VAR)'):</p>

 @({
    (let BINDINGS
      (declare (ignorable . STOBJ-LET-BOUND-VARIABLES))
      (let ((PRODUCER-VAR PRODUCER))
        (let* UPDATES
          CONSUMER)))
 })

 <p>Otherwise:</p>

 @({
    (let BINDINGS
      (declare (ignorable . STOBJ-LET-BOUND-VARIABLES))
      (mv-let PRODUCER-VARS
              PRODUCER
              (let* UPDATES
                CONSUMER)))
 })

 <p>Moreover, ACL2 places restrictions on the resulting expression: @('ST')
 must not occur free in @('PRODUCER'), and every variable in
 @('STOBJ-LET-BOUND-VARIABLES') must not occur free in @('CONSUMER').</p>

 <p>@('Stobj-let') forms can be evaluated using ordinary objects in theorem
 contexts, much as any form.  They can also, of course, appear in function
 bodies.  However, a @('stobj-let') form cannot be evaluated directly in the
 top-level loop or other top-level contexts for execution (such as during
 @(tsee make-event) expansion).</p>

 <p>Finally, let @('FORM') denote the form displayed above (either case).  We
 explain how @('FORM') is actually replaced by an expression of the form
 @('(PROGN$ ... FORM)').  This expression generates an extra @(see guard) proof
 obligation, which guarantees that no aliasing occurs from binding two
 stobj-let-bound variables to the same array access.  So fix a stobj array
 accessor @('ACCi') for which some stobj is bound to @('(ACCi I ST)') in
 @('BINDINGS'); we define an expression @('ACCi-CHECK') as follows.  Collect up
 all such index expressions @('I'), where if @('I') is of the form @('(quote
 N)') then replace @('I') by @('N').  If the resulting list of index
 expressions for @('ACCi') consists solely of distinct numbers, or if it is of
 length 1, then no extra check is generated for @('ACCi').  Otherwise, let
 @('ACCi-CHECK') be the form @('(chk-no-duplicatesp (list I1 ... Ik))'), where
 @('I1'), ..., @('Ik') are the index expressions for @('ACCi').  Note:
 @('chk-no-duplicatesp') is a function that returns nil, but has a @(see guard)
 that its argument is an @(tsee eqlable-listp) that satisfies @(tsee
 no-duplicatesp).  Finally, @('FORM') is replaced by @('(PROGN$ CHK1 ... CHKn
 FORM)'), where each @('ACCi-CHECK') generates a @('CHKm') of the form
 @('(with-guard-checking t ACCi-CHECK)').  The use of @(tsee
 with-guard-checking) guarantees that the check will always be performed, even
 in code that is not guard-verified and even when using @(see
 program-wrapper)s.</p>")

(defxdoc never-memoize
  :parents (memoize)
  :short "Mark a function as unsafe to memoize."
  :long "<p>Logically, this function just returns @('nil').  But execution of
 @('(never-memoize fn)') records that @('fn') must never be memoized, so that
 any attempt to memoize @('fn') will fail.</p>

 <p>Any function can be marked as unsafe to memoize; in fact, @('fn') need not
 even be defined at the time it is marked.</p>

 <p>This is useful for prohibiting the memoization of functions that are known
 to involve destructive functions like @('nreverse').</p>")

(defxdoc nfix
  :parents (numbers acl2-built-ins)
  :short "Coerce to a natural number"
  :long "<p>@('Nfix') simply returns any natural number argument unchanged,
 returning @('0') on an argument that is not a natural number.  Also see @(see
 ifix), see @(see rfix), see @(see realfix), and see @(see fix) for analogous
 functions that coerce to an integer, a rational number, a real, and a number,
 respectively.</p>

 <p>@('Nfix') has a @(see guard) of @('t').</p>

 @(def nfix)")

(defxdoc nil-goal
  :parents (debugging)
  :short "How to proceed when the prover generates a goal of @('NIL')"
  :long "<p>Failed proofs generally conclude with lists of key
 checkpoints.  (See @(see set-gag-mode) or @(see
 introduction-to-key-checkpoints) for an introduction to the notion of ``key
 checkpoint''.)  These lists may sometimes be annotated as follows.</p>

 @({
  [NOTE: A goal of NIL was generated.  See :DOC nil-goal.]
 })

 <p>This @(see documentation) topic gives some ideas about how to think about
 the situation described by that message, that is: some goal has reduced to
 @('NIL').</p>

 <p>Suppose that you see the above NOTE.  If you look at the proof log, you
 will see a message saying that a goal of @('NIL') has been generated.  This
 may indicate that the original goal is not a theorem, since most of the
 prover's activity is typically to replace a goal by an equivalent conjunction
 of its child subgoals.  However, if some ancestor of the @('NIL') goal has
 undergone a process other than simplification or destructor elimination
 &mdash; that is, fertilization (heuristic use of equalities), generalization,
 or elimination of irrelevance &mdash; then it is quite possible that the
 prover got to the @('NIL') goal by replacing a goal by a stronger (and perhaps
 false) conjunction of child subgoals.</p>

 <p>Let's dig a bit deeper by considering two cases for production of a
 @('NIL') subgoal.  First consider the case that the subgoal is a key
 checkpoint at the top level or under a top-level induction &mdash; that is, a
 key checkpoint listed in the proof summary.  In that case, the original
 conjecture is very likely not a theorem.  Otherwise, if you are using @(see
 gag-mode) (which is the case by default), then you may need to issue the
 command @(':')@(tsee pso) (``Print Saved Output'') to see whether the goal was
 strengthened from one that was originally a theorem; but here is what may be a
 better idea.  Instead, it may be best to focus on the key checkpoints printed
 in the summary to see if they suggest useful @(see rewrite) rules to
 prove.</p>

 <p>If some @('NIL') subgoal is under a key checkpoint at the top level or
 under a top-level induction, then as discussed above, the original conjecture
 is probably not a theorem.  Therefore, in that case, ACL2 always prints a
 @('NIL') subgoal first in a list of checkpoints printed in the summary, so
 that a @('NIL') subgoal comes quickly to your attention.</p>")

(defxdoc ninth
  :parents (nth acl2-built-ins)
  :short "Ninth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc no-duplicatesp
  :parents (lists acl2-built-ins)
  :short "Check for duplicates in a list"
  :long "@({
  General Forms:
  (no-duplicatesp x)
  (no-duplicatesp x :test 'eql)   ; same as above (eql as equality test)
  (no-duplicatesp x :test 'eq)    ; same, but eq is equality test
  (no-duplicatesp x :test 'equal) ; same, but equal is equality test
 })

 <p>@('(no-duplicatesp lst)') is true if and only if no member of @('lst')
 occurs twice in @('lst').  The optional keyword, @(':TEST'), has no effect
 logically, but provides the test (default @(tsee eql)) used for comparing
 elements of @('lst').</p>

 <p>The @(see guard) for a call of @('no-duplicatesp') depends on the test.  In
 all cases, the argument must satisfy @(tsee true-listp).  If the test is
 @(tsee eql), then the argument must satisfy @(tsee eqlable-listp).  If the
 test is @(tsee eq), then the argument must satisfy @(tsee symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('no-duplicatesp') and its variants:</p>

 <blockquote><p>@('(no-duplicatesp-eq x lst)') is equivalent to
 @('(no-duplicatesp x lst :test 'eq)');</p>

 <p>@('(no-duplicatesp-equal x lst)') is equivalent to @('(no-duplicatesp x lst
 :test 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('no-duplicatesp-equal').</p>

 @(def no-duplicatesp-equal)")

(defxdoc non-exec
  :parents (guard acl2-built-ins)
  :short "Mark code as non-executable"
  :long "<p>@('Non-exec') is a macro such that logically, @('(non-exec x)') is
 equal to @('x').  However, the argument to a call of @('non-exec') need not
 obey the usual syntactic restrictions for executable code, and indeed,
 evaluation of a call of @('non-exec') will result in an error.  Moreover, for
 any form occurring in the body of a function (see @(see defun)) that is a call
 of @('non-exec'), no guard proof obligations are generated for that form.</p>

 <p>The following example, although rather contrived, illustrates the use of
 @('non-exec').  One can imagine a less contrived example that efficiently
 computes return values for a small number of fixed inputs and, for other
 inputs, returns something logically ``consistent'' with those return
 values.</p>

 @({
  (defun double (x)
    (case x
      (1 2)
      (2 4)
      (3 6)
      (otherwise (non-exec (* 2 x)))))
 })

 <p>We can prove that @('double') is compliant with Common Lisp (see @(see
 guard)) and that it always computes @('(* 2 x)').</p>

 @({
  (verify-guards double)
  (thm (equal (double x) (* 2 x)))
 })

 <p>We can evaluate double on the specified arguments.  But a call of
 @('non-exec') results in an error message that reports the form that was
 supplied to @('non-exec').</p>

 @({
  ACL2 !>(double 3)
  6
  ACL2 !>(double 10)

  ACL2 Error in TOP-LEVEL:  ACL2 has been instructed to cause an error
  because of an attempt to evaluate the following form (see :DOC non-
  exec):

    (* 2 X).

  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

  ACL2 !>
 })

 <p>During proofs, the error is silent; it is ``caught'' by the proof mechanism
 and generally results in the introduction of a call of @(tsee hide) during a
 proof.</p>

 <p>Also see @(see defun-nx) for a utility that makes every call of a function
 non-executable, rather than a specified form.  The following examples contrast
 @('non-exec') with @(tsee defun-nx), in particular illustrating the role of
 @(tsee non-exec) in avoiding guard proof obligations.</p>

 @({
  ; Guard verification fails:
  (defun-nx f1 (x)
    (declare (xargs :guard t))
    (car x))

  ; Guard verification succeeds after changing the guard above:
  (defun-nx f1 (x)
    (declare (xargs :guard (consp x)))
    (car x))

  ; Guard verification succeeds:
  (defun f2 (x)
    (declare (xargs :guard t))
    (non-exec (car x)))

  ; Evaluating (g1) prints \"Hello\" before signaling an error.
  (defun g1 ()
    (f1 (cw \"Hello\")))

  ; Evaluating (g2) does not print before signaling an error.
  (defun g2 ()
    (non-exec (cw \"Hello\")))

  ; Evaluating (h1) gives a guard violation for taking reciprocal of 0.
  (defun h1 ()
    (f1 (/ 1 0)))

  ; Evaluating (h2) does not take a reciprocal, hence there is no guard
  ; violation for that; we just get the error expected from using non-exec.
  (defun h2 ()
    (non-exec (/ 0)))
 })")

(defxdoc non-linear-arithmetic
  :parents (linear)
  :short "Non-linear Arithmetic"
  :long "<p>This documentation topic is divided into two parts.  We first
 discuss the practical aspect of how to use the non-linear arithmetic extension
 to ACL2, and then the theory behind it.  We assume that the reader is familiar
 with the material in @(tsee linear-arithmetic) and that on @(':')@(tsee
 linear) rules.</p>

 <p>We begin our discussion of how to use non-linear arithmetic with a simple
 example.  Assume that we wish to prove:</p>

 @({
  (thm
   (implies (and (rationalp x)
                 (rationalp y)
                 (rationalp z)
                 (< 0 y)
                 (< x (* y z)))
            (< (floor x y) z)))
 })

 <p>Note that @('(floor x y) <= (/ x y)').  Note also that if we divide both
 sides of @('x < (* y z)') by @('y'), since @('0 < y'), we obtain @('(/ x y) <
 z').  By chaining these two inequalities together, we get the inequality we
 desired to prove.</p>

 <p>We now proceed with our example session:</p>

 <code>
 (skip-proofs
  (progn

 ; Since the truth of this theorem depends on the linear properties
 ; of floor, we will need the linear lemma:

    (defthm floor-bounds-1
        (implies (and (rationalp x)
                      (rationalp y))
                 (and (&lt; (+ (/ x y) -1)
                         (floor x y))
                      (&lt;= (floor x y)
                          (/ x y))))
        :rule-classes ((:linear :trigger-terms ((floor x y)))))

 ; We now disable floor, so that the linear lemma will be used.

    (in-theory (disable floor))

 ; We create five rewrite rules which we will use during non-linear
 ; arithmetic.  The necessity for these is due to one of the differences in
 ; ACL2's behavior when non-linear arithmetic is turned on.  Although
 ; the conclusions of linear lemmas have always been rewritten before
 ; they are used, now, when non-linear arithmetic is turned on, the
 ; conclusions are rewritten under a different theory than under ``normal''
 ; rewriting.  This theory is also used in other, similar, circumstances
 ; described below.

    (defthm |arith (* -1 x)|
        (equal (* -1 x)
               (- x)))

    (defthm |arith (* 1 x)|
        (equal (* 1 x)
               (fix x)))

    (defthm |arith (* x (/ x) y)|
        (equal (* x (/ x) y)
               (if (equal (fix x) 0)
                   0
                   (fix y))))

    (defthm |arith (* y x)|
        (equal (* y x)
               (* x y)))

    (defthm |arith (fix x)|
        (implies (acl2-numberp x)
                 (equal (fix x)
                        x))))
  )  ; End skip-proofs.

 ; We disable the above rewrite rules from normal use.

 (in-theory (disable |arith (* -1 x)|
                     |arith (* 1 x)|
                     |arith (* x (/ x) y)|
                     |arith (* y x)|
                     |arith (fix x)|))

 ; We create an arithmetic-theory.  Note that we must give a quoted
 ; constant for the theory &mdash; none of the normal @(tsee theory-functions)
 ; are applicable to in-arithmetic-theory.

 (in-arithmetic-theory '(|arith (* -1 x)|
                         |arith (* 1 x)|
                         |arith (* x (/ x) y)|
                         |arith (* y x)|
                         |arith (fix x)|))

 ; We turn non-linear arithmetic on.

 (set-non-linearp t)

 ; We can now go ahead and prove our theorem.

 (thm
  (implies (and (rationalp x)
                (rationalp y)
                (rationalp z)
                (&lt; 0 y)
                (&lt; x (* y z)))
           (&lt; (floor x y) z)))
 </code>

 <p>The above example illustrates the two practical requirements for using
 non-linear arithmetic in ACL2.  First, one must set up an arithmetic-theory.
 Usually, one would not set up an arithmetic-theory on one's own but would
 instead load a library book or books which do so.  Second, one must turn the
 non-linear arithmetic extension on.  This one must do explicitly &mdash; no
 book can do this for you.</p>

 <p>For a brief discussion of why this is so, even though @('(set-non-linearp
 t)') is an embeddable event, see @(see acl2-defaults-table) (in particular,
 the final paragraph).  (Note that @('(set-non-linearp t)') modifies the
 @('acl2-defaults-table').)  Also see @(see set-non-linearp), see @(see
 embedded-event-form), and see @(see events).</p>

 <p>You can also enable non-linear arithmetic with the hint @(':nonlinearp t').
 See @(see hints).  We, in fact, recommend the use of a hint which will enable
 nonlinear arithmetic only when the goal has stabilized under rewriting.  Using
 @(tsee default-hints) can make this easier.</p>

 @({
  (defun nonlinearp-default-hint (stable-under-simplificationp hist pspv)
    (cond (stable-under-simplificationp
           (if (not (access rewrite-constant
                            (access prove-spec-var pspv :rewrite-constant)
                            :nonlinearp))
               '(:computed-hint-replacement t :nonlinearp t)
             nil))
          ((access rewrite-constant
                   (access prove-spec-var pspv :rewrite-constant)
                   :nonlinearp)
           (if (not (equal (caar hist) 'SETTLED-DOWN-CLAUSE))
               '(:computed-hint-replacement t :nonlinearp nil)
             nil))
          (t nil)))

  (set-default-hints '((nonlinearp-default-hint stable-under-simplificationp
                                                hist pspv)))
 })

 <p>This has proven to be a helpful strategy which allows faster proof
 times.</p>

 <p>We now proceed to briefly describe the theory behind the non-linear
 extension to ACL2.  In @(tsee linear-arithmetic) it was stated that,
 ``[L]inear polynomial inequalities can be combined by cross-multiplication and
 addition to permit the deduction of a third inequality....''  That is, if</p>

 @({
  0 < poly1,
  0 < poly2,
 })

 <p>and @('c') and @('d') are positive rational constants, then</p>

 @({
  0 < c*poly1 + d*poly2.
 })

 <p>Similarly, given the above,</p>

 @({
  0 < poly1*poly2.
 })

 <p>In the linear arithmetic case, we are taking advantage of the facts that
 multiplication by a positive rational constant does not change the sign of a
 polynomial and that the sum of two positive polynomials is itself positive.
 In the non-linear arithmetic case, we are using the fact that the product of
 two positive polynomials is itself positive.</p>

 <p>For example, suppose we have the three assumptions:</p>

 @({
  p1:  3*x*y + 7*a < 4
  p2:            3 < 2*x  or p2': 0 < -3 + 2*x
  p3:            1 < y    or p3': 0 < -1 + y,
 })

 <p>and we wish to prove that @('a < 0').  As described elsewhere (see @(see
 linear-arithmetic)), we proceed by assuming the negation of our goal:</p>

 @({
  p4:            0 <= a,
 })

 <p>and looking for a contradiction.</p>

 <p>There are no cancellations which can be performed by linear arithmetic in
 the above situation.  (Recall that two polynomials are canceled against each
 other only when they have the same largest unknown.)  However, @('p1') has a
 product as its largest unknown, and for each of the factors of that product
 there is a poly that has that factor as a largest unknown.  When non-linear
 arithmetic is enabled, ACL2 will therefore multiply @('p1'') and @('p2'')
 obtaining</p>

 @({
  p5:            0 < 3 + -2*x + -3*y + 2*x*y.
 })

 <p>The addition of this polynomial will allow cancellation to continue and, in
 this case, we will prove our goal.  Thus, just as ACL2 adds two polynomials
 together when they have the same largest unknown of opposite signs in order to
 create a new ``smaller'' polynomial; so ACL2 multiplies polynomials together
 when the product of their largest unknowns is itself the largest unknown of
 another polynomial.  As the use of @(':')@(tsee linear) lemmas to further seed
 the arithmetic database may allow cancellation to proceed, so may the use of
 non-linear arithmetic.</p>

 <p>This multiplication of polynomials is the motivation for an
 arithmetic-theory distinct from than the normal one.  Because this may be done
 so often, and because the individual factors have presumably already been
 rewritten, it is important that this be done in an efficient way.  The use of
 a small, specialized, theory helps avoid the repeated application of rewrite
 rules to already stabilized terms.</p>")

(defxdoc nonnegative-integer-quotient
  :parents (numbers acl2-built-ins)
  :short "Natural number division function"
  :long "@({
  Example Forms:
  (nonnegative-integer-quotient 14 3) ; equals 4
  (nonnegative-integer-quotient 15 3) ; equals 5
 })

 <p>@('(nonnegative-integer-quotient i j)') returns the integer quotient of the
 integers @('i') and (non-zero) @('j'), i.e., the largest @('k') such that
 @('(* j k)') is less than or equal to @('i').  Also see @(see floor), see
 @(see ceiling) and see @(see truncate), which are derived from this function
 and apply to rational numbers.</p>

 <p>The @(see guard) of @('(nonnegative-integer-quotient i j)') requires that
 @('i') is a nonnegative integer and @('j') is a positive integer.</p>

 @(def nonnegative-integer-quotient)")

(defxdoc normalize
  :parents (xargs)
  :short "Storing simplified @(see definition) bodies and @(see guard)s"
  :long "<p>By default, when you submit a @(tsee defun) form, the body is
 simplified for certain later uses.  This simplification is sometimes called
 ``normalization''; the ACL2 system function that accomplishes this task is
 @('normalize').  Consider the following examples, where we make two
 definitions and then show their bodies using @(':')@(tsee pf)..</p>

 @({
 ACL2 !>(defun f1 (x y)
          (cons (implies x y) (integerp 3)))
 [.. output omitted ..]
  F1
 ACL2 !>(defun f2 (x y)
          (declare (xargs :normalize nil))
          (cons (implies x y) (integerp 3)))
 [.. output omitted ..]
  F2
 ACL2 !>:pf f1
 (EQUAL (F1 X Y) (IF X (IF Y '(T . T) '(NIL . T)) '(T . T)))
 ACL2 !>:pf f2
 (EQUAL (F2 X Y) (CONS (IMPLIES X Y) (INTEGERP 3)))
 ACL2 !>
 })

 <p>We see that the body of @('f1') has undergone the default simplification
 (with @('normalize')), while the body of @('f2') has not because of the @(tsee
 xargs) in its @('defun') form.</p>

 <p>The example above illustrates that normalization consists of the following
 three parts:</p>

 <ul>

 <li>propagation upward of @('if') tests;</li>

 <li>potential simplification with @(see type-set) reasoning; and</li>

 <li>the expansion of calls of a few built-in functions (like @(tsee
 implies)).</li>

 </ul>

 <p>We have seen an example where @(see type-set) reasoning can be expensive.
 So when ACL2 normalizes @(see definition) bodies and @(see guard)s, it
 establishes a @(see backchain-limit) for @(see type-set) reasoning of 1,
 unless that limit is currently 0.  (The global default is to have no
 limit.)</p>

 <p>Also see the @(see community-books) utility @(tsee
 install-not-normalized).</p>")

(defxdoc normed
  :parents (hons)
  :short "Normed objects are ACL2 Objects that are \"canonical\" or \"unique\"
 in a certain sense."
  :long "<p>In Common Lisp, we can tell whether an ACL2 object is <b>normed</b>
 or not, but there is no way for an ordinary ACL2 function to see whether an
 object is normed.  Hence, whether or not an object is normed is an
 implementation-level concept.</p>

 <p>The fundamental property of normed objects is that if A and B are both
 normed, then @('(equal A B)') holds if and only if @('(eql A B)') holds.  For
 strings and conses, @('(eql A B)') holds only when @('(eq A B)'), so any
 normed conses or strings are @(tsee equal) precisely when they are @(tsee eq).
 The potential benefits of having normed objects include: constant-time
 equality comparisons, reduced memory usage, fast association lists, and
 function memoization.</p>

 <p>Note that in our implementation, all symbols, characters, and numbers are
 automatically normed, and whenever a cons is normed its car and cdr must also
 be normed.</p>

 <p>The Meaning of Normed in Common Lisp.</p>

 <p>Recall that the ACL2 Objects are certain \"good\" Common Lisp symbols,
 characters, strings, and numbers, and the conses which can be recursively
 formed from these good atoms.</p>

 <p>Not all properties of these objects are visible in the ACL2 logic.  An
 example of an invisible property is the pointer identity of an object.  For
 example, suppose we write the following.</p>

 @({
   (defconst *x* (cons 1 2))
   (defconst *y* (cons 1 2))
 })

 <p>In Common Lisp, @(tsee cons) is guaranteed to provide a new pair that is
 distinct from any previously created pair, so we know that *x* and *y* will be
 distinct objects and we will be able to tell them apart from one another using
 @('eq').  But this difference is not visible in the ACL2 logic, and no ACL2
 function can tell *x* apart from *y*.</p>

 <p>The normed-ness of an object is a similarly invisible property.  In Common
 Lisp, invisible to ACL2, we maintain a data structure called a \"Hons Space\"
 that records which objects are normed.  So, being normed is not an intrinsic
 property of an object, but instead is determined by whether the object is
 mentioned in this Hons Space.</p>

 <p>Notes about Garbage Collection.</p>

 <p>The Hons Space includes tables with pointers to every normed cons and
 string.  One consequence of this is that normed objects cannot be reclaimed by
 Lisp's ordinary garbage collector, even after they have become unreachable
 from the perspective of an ACL2 program.</p>

 <p>For CCL and GCL users only, @(tsee hons-wash) is a special kind of garbage
 collection that allows normed conses to be reclaimed.  For other Lisps, the
 only option is to occasionally, manually clear out these Hons Space tables
 with @(tsee hons-clear).</p>")

(defxdoc not
  :parents (basics acl2-built-ins)
  :short "Logical negation"
  :long "<p>@('Not') is the ACL2 negation function.  The negation of @('nil')
 is @('t') and the negation of anything else is @('nil').</p>

 <p>@('Not') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def not)")

(defxdoc note-1-1
  :parents (release-notes)
  :short "Acl2 Version 1.1 Notes"
  :long "<p>The new features are extensively documented.  The relevant topics
 are:</p>

 <p>It is especially important to read all of of the @(see documentation) for
 @(see books) before trying to use books.  However, the new @(':more')
 keyword command is so handy for reading long @(see documentation) strings that
 we recommend you start with @(':')@(tsee doc) more if reading at the terminal.
 Some documentation has been written for @(see guard)s which you might find
 interesting.</p>")

(defxdoc note-1-2
  :parents (release-notes)
  :short "Acl2 Version 1.2 Notes"
  :long "<p>Hacker mode has been eliminated and @(see programming) mode has
 been added.  @(see Programming) mode is unsound but does syntax checking and
 permits redefinitions of names.  See @(':')@(tsee doc) @('load-mode') and
 @(':')@(tsee doc) @('g-mode').</p>

 <p>The arguments to @(tsee ld) have changed.  @(tsee Ld) is now much more
 sophisticated.  See @(see ld).</p>

 <p>For those occasions on which you wish to look at a large list structure
 that you are afraid to print, try @('(walkabout x state)'), where @('x') is an
 Acl2 expression that evaluates to the structure in question.  I am afraid
 there is no @(see documentation) yet, but it is similar in spirit to the
 Interlisp structure editor.  You are standing on an object and commands move
 you around in it.  E.g., 1 moves you to its first element, 2 to its second,
 etc.; 0 moves you up to its parent; @('nx') and @('bk') move you to its next
 sibling and previous sibling; @('pp') prettyprints it; @(tsee q) exits
 returning @('nil'); @(tsee =) exits returning the thing you're standing on;
 @('(= symb)') assigns the thing you're standing on to the @(see state) global
 variable @('symb').</p>

 <p>Several new @(see hints) have been implemented, including @(':by') and
 @(':do-not').  The old @(':do-not-generalize') has been scrapped in favor of
 such new @(see hints) as @(':do-not') @('(generalize elim)').  @(':By') lets
 you say ``this goal is subsumed by'' a given lemma instance.  The @(':by')
 hint also lets you say ``this goal can't be proved yet but skip it and see how
 the rest of the proof goes.'' See @(see hints).</p>")

(defxdoc note-1-3
  :parents (release-notes)
  :short "Acl2 Version 1.3 Notes"
  :long "<p>@(see Programming) mode has been eliminated.  Instead, all
 functions have a ``color'' which indicates what can be done with the function.
 For example, @(':red') functions can be executed but have no axioms describing
 them.  Thus, @(':red') functions can be introduced after passing a simple
 syntactic check and they can be redefined without undoing.  But nothing of
 consequence can be proved about them.  At the other extreme are @(':gold')
 functions which can be executed and which also have passed both the
 termination and the @(see guard) verification proofs.  The color of a function
 can be specified with the new @(tsee xargs) keyword, @(':color'), which, if
 omitted defaults to the global setting of @('ld-color').  @('Ld-color')
 replaces @('load-mode').  Setting @('ld-color') to @(':red') causes behavior
 similar to the old @(':g-mode').  Setting @('ld-color') to @(':gold') causes
 behavior similar to the old @(':v-mode').  It is possible to prototype your
 system in @(':red') and then convert @(':red') functions to :@('blue')
 individually by calling @(tsee verify-termination) on them.  They can then be
 converted to @(':gold') with @(tsee verify-guards).  This allows us to
 undertake to verify the termination and @(see guard)s of system functions.
 See @(':')@(tsee doc) color for an introduction to the use of colors.</p>

 <p>Type prescription rules have been added.  Recall that in Nqthm, some @(tsee
 rewrite) rules were actually stored as ``@(see type-prescription)s.''  Such
 rules allow the user to inform Nqthm's primitive type mechanism as to the
 kinds of shells returned by a function.  Earlier versions of Acl2 did not have
 an analogous kind of rule because Acl2's type mechanism is complicated by
 @(see guard)s.  Version 1.3 supports @(tsee type-prescription) rules.  See
 @(see type-prescription).</p>

 <p>Three more new @(see rule-classes) implement congruence-based rewriting.
 It is possible to identify a binary relation as an equivalence relation (see
 @(see equivalence)), to show that one equivalence relation refines another
 (see @(see refinement)) and to show that a given equivalence relation is
 maintained when rewriting a given function call, e.g., @('(fn ...xk...)'), by
 maintaining another equivalence relation while rewriting the @('k')th argument
 (see @(see congruence)).  If @('r') has been shown to be an @(see equivalence)
 relation and then @('(implies hyps (r (foo x) (bar x)))') is proved as a
 @(':')@(tsee rewrite) rule, then instances of @('(foo x)') will be replaced by
 corresponding instances of @('(bar x)') provided the instance occurs in a slot
 where the maintenance of @('r-equivalence') is known to be sufficient and
 @('hyps') can be established as usual.</p>

 <p>In Version 1.2, @(see rule-classes) were simple keywords, e.g.,
 @(':')@(tsee rewrite) or @(':')@(tsee elim).  In Version 1.3, @(see
 rule-classes) have been elaborated to allow you to specify how the theorem
 ought to be used as a rule.  That is, the new @(see rule-classes) allows you
 to separate the mathematical statement of the formula from its interpretation
 as a rule.  See @(see rule-classes).</p>

 <p>Rules used to be named by symbols, e.g., @(tsee car) and @('car-cons') were
 the names of rules.  Unfortunately, this was ambiguous because there are three
 rules associated with function symbols: the symbolic definition, the
 executable-counterpart, and the @(see type-prescription); many different rules
 might be associated with theorems, depending on the rule classes.  In Version
 1.3 rules are named by ``@(see rune)s'' (which is just short hand for ``rule
 names'').  Example @(see rune)s are @('(:definition car)'),
 @('(:executable-counterpart car)'), and @('(:type-prescription car . 1)').
 Every rule added by an event has a different name and you can @(see enable)
 and @(see disable) them independently.  See @(see rune) and see @(see
 theories).</p>

 <p>The identity function @(tsee force), of one argument, has been added and
 given a special interpretation by the functions responsible for establishing
 hypotheses in backchaining: When the system fails to establish some hypothesis
 of the form @('(force term)'), it simply assumes it is true and goes on,
 delaying until later the establishment of term.  In particular, pushes a new
 subgoal to prove term in the current context.  When that subgoal is attacked,
 all of the resources of the theorem prover, not just rewriting, are brought to
 bear.  Thus, for example, if you wish to prove the rule <tt>(implies
 (good-statep s) (equal (exec s n) s'))</tt> and it is your expectation that
 every time @('exec') appears its first argument is a @('good-statep') then you
 might write the rule as <tt>(implies (force (good-statep s)) (equal (exec s n)
 s'))</tt>.  This rule is essentially an unconditional rewrite of @('(exec s
 n)') to @('s'') that spawns the new goal @('(good-statep s)').  See @(see
 force).  Because you can now specify independently how a theorem is used as a
 rule, you need not write the @(tsee force) in the actual theorem proved.  See
 @(see rule-classes).</p>

 <p>Version 1.3 supports a facility similar to Nqthm's @(tsee break-lemma).
 See @(see break-rewrite).  You can install ``@(see monitor)s'' on @(see rune)s
 that will cause interactive breaks under certain conditions.</p>

 <p>Acl2 also provides ``@(see wormhole)s'' which allow you to write functions
 that cause interaction with the user but which do not require that you have
 access to @(tsee state).  See @(see wormhole).</p>

 <p>The rewriter now automatically backchains to stronger recognizers.  There
 is no user hook to this feature but it may simplify some proofs with which
 older versions of Acl2 had trouble.  For example, if the rewriter is trying to
 prove @('(rationalp (foo a b c))') it is now smart enough to try lemmas that
 match with @('(integerp (foo a b c))').</p>")

(defxdoc note-1-4
  :parents (release-notes)
  :short "Acl2 Version 1.4 Notes"
  :long "<p>Once again @(tsee ld) only takes one required argument, as the
 @('bind-flg') has been deleted.</p>

 <p>Three commands have been added in the spirit of @(':')@(tsee pe).
 @(':')@(tsee Pe!) is similar to @(':')@(tsee pe) but it prints all @(see
 events) with the given name, rather than just the most recent.  The command
 @(':')@(tsee pf) prints the corollary formula corresponding to a name or @(see
 rune).  The command @(':')@(tsee pl) (print lemmas) prints rules whose top
 function symbol is the given name.  See @(see pe!), see @(see pf), and see
 @(see pl).</p>

 <p>Book naming conventions have been changed somewhat.  The once-required
 @('.lisp') extension is now prohibited!  Directories are supported, including
 a notion of ``connected book directory''.  See @(see book-name).  Also, the
 second argument of @(tsee certify-book) is now optional, defaulting to
 @('0').</p>

 <p>@(see Compilation) is now supported inside the Acl2 loop.  See @(see comp)
 and see @(see set-compile-fns).</p>

 <p>The default color is now part of the Acl2 @(see world); see @(':')@(tsee
 doc) @('default-color').  @('Ld-color') is no longer an @(tsee ld) special.
 Instead, colors are @(see events); see the documentation for @('red'),
 @('pink'), @('blue'), and @('gold').</p>

 <p>A @(see table) exists for controlling whether Acl2 prints comments when it
 @(see force)s hypotheses of rules; see @(':')@(tsee doc) @('force-table').
 Also, it is now possible to turn off the forcing of assumptions by disabling
 the definition of @(see force); see @(see force).</p>

 <p>The event @('defconstant') is no longer supported, but a very similar
 event, @(tsee defconst), has been provided in its place.  See @(see
 defconst).</p>

 <p>The event for defining @(see congruence) relations is now @(tsee defcong)
 (formerly, @('defcon')).</p>

 <p>Patterns are now allowed in @(':expand') @(see hints).  See the
 documentation for @(':expand') inside the documentation for @(see hints).</p>

 <p>We have improved the way we report rules used by the simplifier.  All @(see
 rune)s of the same type are reported together in the running commentary
 associated with each goal, so that for example, executable-counterparts are
 listed separately from definitions, and rewrite rules are listed separately
 from @(see linear) rules.  The preprocessor now mentions ``simple'' rules; see
 @(see simple).</p>

 <p>The mechanism for printing warning messages for new rewrite rules, related
 to subsumption, now avoids worrying about nonrecursive function symbols when
 those symbols are @(see disable)d.  These messages have also been eliminated
 for the case where the old rule is a @(':')@(tsee definition) rule.</p>

 <p>Backquote has been modified so that it can usually provide predictable
 results when used on the left side of a rewrite rule.</p>

 <p>Time statistics are now printed even when an event fails.</p>

 <p>The Acl2 trace package has been modified so that it prints using the values
 of the Lisp globals @('*print-level*') and @('*print-length*')
 (respectively).</p>

 <p>@(see Table) has been modified so that the @(':clear') option lets you
 replace the entire @(see table) with one that satisfies the @('val') and key
 guards (if any); see @(see table).</p>

 <p>We have relaxed the translation rules for @(':measure') @(see hints) to
 @(tsee defun), so that the the same rules apply to these terms that apply to
 terms in @(tsee defthm) @(see events).  In particular, in @(':measure') @(see
 hints) @(tsee mv) is treated just like @(tsee list), and @(tsee state)
 receives no special handling.</p>

 <p>The @(see loop-stopper) test has been relaxed.  The old test required that
 every new argument be strictly less than the corresponding old argument in a
 certain @(see term-order).  The new test uses a lexicographic order on term
 lists instead.  For example, consider the following rewrite rule.</p>

 @({
    (equal
     (variable-update var1
                      val1 (variable-update var2 val2 vs))
     (variable-update var2
                      val2 (variable-update var1 val1 vs)))
 })

 <p>This rule is permutative.  Now imagine that we want to apply this rule to
 the term</p>

 @({
    (variable-update u y (variable-update u x vs)).
 })

 <p>Since the actual corresponding to both @('var1') and @('var2') is @('u'),
 which is not strictly less than itself in the @(see term-order), this rule
 would fail to be applied in this situation when using the old test.  However,
 since the pair @('(u x)') is lexicographically less than the pair @('(u y)')
 with respect to our @(see term-order), the rule is in fact applied using our
 new test.</p>

 <p>Messages about @(see events) now contain a space after certain left
 parentheses, in order to assist emacs users.  For example, the event</p>

 @({
    (defthm abc (equal (+ (len x) 0) (len x)))
 })

 <p>leads to a summary containing the line</p>

 @({
    Form:  ( DEFTHM ABC ...)
 })

 <p>and hence, if you search backwards for ``@('(defthm abc')'', you won't stop
 at this message.</p>

 <p>More tautology checking is done during a proof; in fact, no goal printed to
 the screen, except for the results of applying @(':use') and @(':by') @(see
 hints) or the top-level goals from an induction proof, are known to Acl2 to be
 tautologies.</p>

 <p>The @(tsee ld-query-control-alist) may now be used to suppress printing of
 queries; see @(see ld-query-control-alist).</p>

 <p>Warning messages are printed with short summary strings, for example the
 string ``@('Use')'' in the following message.</p>

 @({
    Acl2 Warning [Use] in DEFTHM:  It is unusual to :USE an enabled
    :REWRITE or :DEFINITION rule, so you may want to consider
    disabling FOO.
 })

 <p>At the end of the event, just before the time is printed, all such summary
 strings are printed out.</p>

 <p>The keyword command @(':u') has been introduced as an abbreviation for
 @(':')@(tsee ubt) @(':')@(tsee max).  Printing of query messages is suppressed
 by @(':u').</p>

 <p>The keyword @(':cheat') is no longer supported by any event form.</p>

 <p>Some irrelevant formals are detected; see @(see irrelevant-formals).</p>

 <p>A bug in the application of metafunctions was fixed: now if the output of a
 metafunction is equal to its input, the application of the metafunction is
 deemed unsuccessful and the next metafunction is tried.</p>

 <p>An example has been added to the documentation for @(see equivalence) to
 suggest how to make use of @(see equivalence) relations in rewriting.</p>

 <p>The following Common Lisp functions have been added to Acl2: @(tsee
 alpha-char-p), @(tsee upper-case-p), @(tsee lower-case-p), @(tsee
 char-upcase), @(tsee char-downcase), @(tsee string-downcase), @(tsee
 string-upcase), and @('digit-charp-p').</p>

 <p>A documentation section called @(tsee proof-builder) has been added for the
 interactive facility, whose documentation has been slightly improved.  See in
 particular the documentation for @(see proof-builder), @(tsee verify), and
 @(see macro-command).</p>

 <p>A number of @(see events) that had been inadvertently disallowed in @(see
 books) are now permitted in @(see books).  These are: @(tsee defcong),
 @('defcor'), @(tsee defequiv), @(tsee defrefinement), @(tsee defstub), and
 @(tsee verify-termination).</p>")

(defxdoc note-1-5
  :parents (release-notes)
  :short "Acl2 Version 1.5 Notes"
  :long "<p>Acl2 now allows ``complex rationals,'' which are complex numbers
 whose real parts are rationals and whose imaginary parts are non-zero
 rationals.  See @(see complex).</p>

 <p>A new way of handling @(tsee force)d hypotheses has been implemented.
 Rather than cause a case split at the time the @(tsee force) occurs, we
 complete the main proof and then embark on one or more ``forcing rounds'' in
 which we try to prove the @(see force)d hypotheses.  See @(see forcing-round).
 To allow us to compare the new handling of @(tsee force) with the old, Version
 1.5 implements both and uses a flag in @(tsee state) to determine which method
 should be used.  Do @('(assign old-style-forcing t)') if you want @(tsee
 force) to be handled as it was in Version 1.4.  However, we expect to
 eliminate the old-style forcing eventually because we think the new style is
 more effective.  To see the difference between the two approaches to forcing,
 try proving the associativity of @(see append) under both settings of
 @('old-style-forcing').  To get the new behavior invoke:</p>

 @({
  (thm (implies (and (true-listp a) (true-listp b))
                (equal (append (append a b) c)
                       (append a (append b c)))))
 })

 <p>Then @('(assign old-style-forcing t)') and invoke the @('thm') @(see
 command) above again.</p>

 <p>A new @(':cases') @(see hints) allows proof by cases.  See @(see
 hints).</p>

 <p>@(tsee Include-book) and @(tsee encapsulate) now restore the @(tsee
 acl2-defaults-table) when they complete.  See @(see include-book) and see
 @(see encapsulate).</p>

 <p>The @(see guard)s on many Acl2 primitives defined in @('axioms.lisp') have
 been weakened to permit them to be used in accordance with lisp custom and
 tradition.</p>

 <p>It is possible to attach heuristic filters to @(':')@(tsee rewrite) rules
 to limit their applicability.  See @(see syntaxp).</p>

 <p>A tutorial has been added (but as of Version_3.6.1 it has become
 obsolete).</p>

 <p>@(see Events) now print the Summary paragraph listing @(see rune)s used,
 time, etc., whether they succeed or fail.  The format of the ``@(see failure)
 banner'' has been changed but still has multiple asterisks in it.  @('Thm')
 also prints a Summary, whether it succeeds or fails; but @('thm') is not an
 event.</p>

 <p>A new event form @(tsee skip-proofs) has been added; see @(see
 skip-proofs).</p>

 <p>A user-specific customization facility has been added in the form of a book
 that is automatically included, if it exists on the current directory.  See
 @(see acl2-customization).</p>

 <p>A facility for conditional metalemmas has been implemented; see @(see
 meta).</p>

 <p>The acceptable values for @(tsee ld-skip-proofsp) have changed.  In the old
 version (Version 1.4), a value of @('t') meant that proofs and @(tsee local)
 @(see events) are to be skipped.  In Version 1.5, a value of @('t') means
 proofs (but not @(tsee local) @(see events)) are to be skipped.  A value of
 @(''')@(tsee include-book) means proofs and @(tsee local) @(see events) are to
 be skipped.  There are two other, more obscure, acceptable values.  See @(see
 ld-skip-proofsp).</p>

 <p>In order to turn off the forcing of assumptions, one should now @(see
 disable) the @(':')@(tsee executable-counterpart) of @(tsee force) (rather
 than the @(':')@(tsee definition) of @(tsee force), as in the previous
 release); see @(see force).</p>

 <p>The macros @(tsee enable-forcing) and @(tsee disable-forcing) make it
 convenient to @(see enable) or @(see disable) forcing.  See @(see
 enable-forcing) and see @(see disable-forcing).</p>

 <p>The new commands @(':')@(tsee pr) and @(':')@(tsee pr!) print the rules
 created by an event or command.  See @(see pr) and see @(see pr!).</p>

 <p>The new @(see history) @(see command)s @(':')@(tsee puff) and @(':')@(tsee
 puff*) will replace a compound @(see command) such as an @(tsee encapsulate)
 or @(tsee include-book) by the sequence of @(see events) in it.  That is, they
 ``@(see puff) up'' or ``lift'' the subevents of a @(see command) to the @(see
 command) level, eliminating the formerly superior @(see command) and
 lengthening the @(see history).  This is useful if you want to ``partially
 undo'' an @(tsee encapsulate) or book or other compound @(see command) so you
 can experiment.  See @(see puff) and see @(see puff*).</p>

 <p>Theory expressions now are allowed to use the free variable @(tsee world)
 and prohibited from using the free variable @(tsee state).  See @(see
 theories), although it is essentially the same as before except it mentions
 @(tsee world) instead of @(tsee state).  See @(see world) for a discussion of
 the Acl2 logical @(see world).  Allowing @(tsee in-theory) @(see events) to be
 state-sensitive violated an important invariant about how @(see books)
 behaved.</p>

 <p>@(tsee Table) keys and values now are allowed to use the free variable
 @(tsee world) and prohibited from using the free variable @(tsee state).  See
 the note above about theory expressions for some explanation.</p>

 <p>The macro for minus, @(tsee -), used to expand @('(- x 3)') to @('(+ x
 -3)') and now expands it to @('(+ -3 x)') instead.  The old macro, if used in
 the left-hand sides of rewrite rules, produced inapplicable rules because the
 constant occurs in the second argument of the @(tsee +), but potential target
 terms generally had the constant in the first argument position because of the
 effect of @('commutativity-of-+').</p>

 <p>A new class of rule, @(':linear-alias') rules, allows one to implement the
 nqthm package and similar hacks in which a @(see disable)d function is to be
 known equivalent to an arithmetic function.</p>

 <p>A new class of rule, @(':built-in-clause') rules, allows one to extend the
 set of clauses proved silently by @(tsee defun) during measure and @(see
 guard) processing.  See @(see built-in-clause).</p>

 <p>The new command @(tsee pcb!) is like @(tsee pcb) but sketches the @(see
 command) and then prints its subsidiary @(see events) in full.  See @(see
 pcb!).</p>

 <p>@(':')@(tsee Rewrite) class rules may now specify the @(':')@(tsee
 loop-stopper) field.  See @(see rule-classes) and see @(see loop-stopper).</p>

 <p>The rules for how @(see loop-stopper)s control permutative rewrite rules
 have been changed.  One effect of this change is that now when the built-in
 commutativity rules for @(tsee +) are used, the terms @('a') and @('(- a)')
 are permuted into adjacency.  For example, @('(+ a b (- a))') is now
 normalized by the commutativity rules to @('(+ a (- a) b)'); in Version 1.4,
 @('b') was considered syntactically smaller than @('(- a)') and so @('(+ a b
 (- a))') is considered to be in normal form.  Now it is possible to arrange
 for unary functions be be considered ``invisible'' when they are used in
 certain contexts.  By default, @(tsee unary--) is considered invisible when
 its application appears in the argument list of @(tsee binary-+).  See @(see
 loop-stopper) and see :DOC set-invisible-fns-table.</p>

 <p>Extensive documentation has been provided on the topic of Acl2's ``term
 ordering.''  See @(see term-order).</p>

 <p>Calls of @(tsee ld) now default @(tsee ld-error-action) to @(':return')
 rather than to the current setting.</p>

 <p>The @(see command) descriptor @(':x') has been introduced and is synonymous
 with @(':')@(tsee max), the most recently executed @(see command).  @(see
 History) @(see command)s such as @(':')@(tsee pbt) print a @(':x') beside the
 most recent @(see command), simply to indicate that it <b>is</b> the most
 recent one.</p>

 <p>The @(see command) descriptor @(':x-23') is synonymous with @('(:x -23)').
 More generally, every symbol in the keyword package whose first character is
 @('#\\x') and whose remaining @(see characters) parse as a negative integer is
 appropriately understood.  This allows @(':')@(tsee pbt) @(':x-10') where
 @(':')@(tsee pbt) @('(:max -10)') or @(':')@(tsee pbt) @('(:here -10)') were
 previously used.  The old forms are still legal.</p>

 <p>The order of the arguments to @(tsee defcong) has been changed.</p>

 <p>The simplifier now reports the use of unspecified built-in type information
 about the primitives with the phrase ``primitive type reasoning.''  This
 phrase may sometimes occur in situations where ``propositional calculus'' was
 formerly credited with the proof.</p>

 <p>The function @(tsee pairlis) has been replaced in the code by a new
 function @(tsee pairlis$), because Common Lisp does not adequately specify its
 @(tsee pairlis) function.</p>

 <p>Some new Common Lisp functions have been added, including @(tsee logtest),
 @(tsee logcount), @(tsee integer-length), @(tsee make-list), @(tsee
 remove-duplicates), @(tsee string), and @(tsee concatenate).  The source file
 @('/slocal/src/acl2/axioms.lisp') is the ultimate reference regarding Common
 Lisp functions in Acl2.</p>

 <p>The functions @(tsee defuns) and @(tsee theory-invariant) have been
 documented.  See @(see defuns) and see @(see theory-invariant).</p>

 <p>A few symbols have been added to the list @('*acl2-exports*').</p>

 <p>A new key has been implemented for the @(tsee acl2-defaults-table),
 @(':irrelevant-formals-ok').  See @(see set-irrelevant-formals-ok).</p>

 <p>The connected book directory, @(tsee cbd), must be nonempty and begin and
 end with a slash.  It is set (and displayed) automatically upon your first
 entry to @(tsee lp).  You may change the setting with @(tsee set-cbd).  See
 @(see cbd).</p>

 <p>@(':')@(tsee oops) will undo the last @(':')@(tsee ubt).  See @(see
 oops).</p>

 <p>Documentation has been written about the ordinals.  See :DOC
 @('e0-ordinalp') and see :DOC @('e0-ord-<').  [Note added later: Starting with
 Version_2.8, instead see @(see o-p) and see @(see o<).</p>

 <p>The color @(see events) &mdash; (red), (pink), (blue), and (gold) &mdash;
 may no longer be enclosed inside calls of @(tsee local), for soundness
 reasons.  In fact, neither may any event that sets the @(tsee
 acl2-defaults-table).  See @(see embedded-event-form).</p>

 <p>See @(see ld-keyword-aliases) for an example of how to change the exit
 keyword from @(':')@(tsee q) to something else.</p>

 <p>The attempt to install a @(see monitor) on @(':')@(tsee rewrite) rules
 stored as simple abbreviations now causes an error because the application of
 abbreviations is not tracked.</p>

 <p>A new message is sometimes printed by the theorem prover, indicating that a
 given simplification is ``specious'' because the subgoals it produces include
 the input goal.  In Version 1.4 this was detected but not reported, causing
 behavior some users found bizarre.  See @(see specious-simplification).</p>

 <p>@(':')@(tsee Definition) rules are no longer always required to specify the
 @(':clique') and @(':controller-alist') fields; those fields can be defaulted
 to system-determined values in many common instances.  See @(see
 definition).</p>

 <p>A warning is printed if a macro form with keyword arguments is given
 duplicate keyword values.  Execute @('(thm t :doc nil :doc \"ignored\")') and
 read the warning printed.</p>

 <p>A new restriction has been placed on @(tsee encapsulate).  Non-@(tsee
 local) recursive definitions inside the @(tsee encapsulate) may not use, in
 their tests and recursive calls, the constrained functions introduced by the
 @(tsee encapsulate).  See @(see subversive-recursions).  (Note added in
 Version 2.3: Subversive recursions were first recognized by us here in Version
 1.5, but our code for recognizing them was faulty and the bug was not fixed
 until Version 2.3.)</p>

 <p>The @(see events) @(tsee defequiv), @(tsee defcong), @(tsee defrefinement),
 and @(tsee defevaluator) have been reimplemented so that they are just macros
 that expand into appropriate @(tsee defthm) or @(tsee encapsulate) @(see
 events); they are no longer primitive @(see events).  See the @(see
 documentation) of each affected event.</p>

 <p>The @('defcor') event, which was a shorthand for a @(tsee defthm) that
 established a @(see corollary) of a named, previously proved event, has been
 eliminated because its implementation relied on a technique we have decided to
 ban from our code.  If you want the effect of a @('defcor') in Version 1.5 you
 must submit the corresponding @(tsee defthm) with a @(':by') hint naming the
 previously proved event.</p>

 <p>Error reporting has been improved for inappropriate @(tsee in-theory) @(see
 hints) and @(see events), and for syntax errors in rule classes, and for
 non-existent filename arguments to @(tsee ld).</p>

 <p>Technical Note: We now maintain the Third Invariant on @('type-alists'), as
 described in the Essay on the Invariants on Type-alists, and Canonicality.
 This change will affect some proofs, for example, by causing a to rewrite more
 quickly to @('c') when @('(equiv a b)') and @('(equiv b c)') are both known
 and @('c') is the canonical representative of the three.</p>")

(defxdoc note-1-6
  :parents (release-notes)
  :short "Acl2 Version 1.6 Notes"
  :long "<p>A new key has been implemented for the @(tsee acl2-defaults-table),
 @(':ignore-ok').  See @(see set-ignore-ok).</p>

 <p>It is now legal to have color @(see events), such as @('(red)'), in the
 @(see portcullis) of a book.  More generally, it is legal to set the @(tsee
 acl2-defaults-table) in the @(see portcullis) of a book.  For example, if you
 execute @(':red') and then certify a book, the event @('(red)') will show up
 in the @(see portcullis) of that book, and hence the definitions in that book
 will all be red (except when overridden by appropriate declarations or @(see
 events)).  When that book is included, then as always, its @(see portcullis)
 must first be ``raised,'' and that will cause the default color to become red
 before the @(see events) in the book are executed.  As always, the value of
 @(tsee acl2-defaults-table) immediately after execution of an @(tsee
 include-book), @(tsee certify-book), or @(tsee encapsulate) form will be the
 same as it was immediately before execution (and hence, so will the default
 color).  See @(see portcullis) and, for more about books, see @(see
 books).</p>

 <p>A theory @(tsee ground-zero) has been defined to contain exactly those
 rules that are @(see enable)d when Acl2 starts up.  See @(see
 ground-zero).</p>

 <p>The function @(tsee nth) is now @(see enable)d, correcting an oversight
 from Version 1.5.</p>

 <p>Customization files no longer need to meet the syntactic restrictions put
 on @(see books); rather, they can contain arbitrary Acl2 forms.  See @(see
 acl2-customization).</p>

 <p>Structured directory names and structured file names are supported; see
 especially the documentation for @(see pathname), @(see book-name), and @(tsee
 cbd).</p>

 <p>Acl2 now works with some Common Lisp implementations other than akcl,
 including Lucid, Allegro, and MCL.</p>

 <p>A facility has been added for displaying proof trees, especially using
 emacs; see @(see proof-tree).</p>

 <p>There is a considerable amount of new @(see documentation), in particular
 for the printing functions @(tsee fmt), @(tsee fmt1), and @(tsee fms), and for
 the notion of Acl2 term (see @(see term)).</p>

 <p>It is possible to introduce new well-founded relations, to specify which
 relation should be used by @(tsee defun), and to set a default relation.  See
 @(see well-founded-relation-rule).</p>

 <p>It is possible to make functions suggest new inductions.  See @(see
 induction).</p>

 <p>It is possible to change how Acl2 expresses @(see type-set) information; in
 particular, this affects what clauses are proved when @(see force)d
 assumptions are generated.  See @(see type-set-inverter).</p>

 <p>A new restriction has been added to @(tsee defpkg), having to do with
 undoing.  If you undo a @(tsee defpkg) and define the same package name again,
 the imports list must be identical to the previous imports or else an
 explanatory error will occur.  See @(see
 package-reincarnation-import-restrictions).</p>

 <p>@(tsee Theory-invariant) and @(tsee set-irrelevant-formals-ok) are now
 embedded event forms.</p>

 <p>The command @(':')@(tsee good-bye) may now be used to quit entirely out of
 Lisp, thus losing your work forever.  This command works in akcl but may not
 work in every Common Lisp.</p>

 <p>A theory @(tsee ground-zero) has been added that contains exactly the @(see
 enable)d rules in the @(see startup) theory.  See @(see ground-zero).</p>

 <p>@('Define-pc-macro') and @('define-pc-atomic-macro') now automatically
 define @(':red') functions.  (It used to be necessary, in general, to change
 color to @(':red') before invoking these.)</p>

 <p>For a proof of the well-foundedness of @('e0-ord-<') on the
 @('e0-ordinalp')s, see @(see proof-of-well-foundedness).  [Note added later:
 Starting with Version_2.8, @(tsee o<) and @(tsee o-p) replace @('e0-ord-<')
 and @('e0-ordinalp'), respectively.]</p>

 <p>Free variables are now handled properly for hypotheses of @(':')@(tsee
 type-prescription) rules.</p>

 <p>When the system is loaded or saved, @(tsee state) is now bound to
 @('*the-live-state*').</p>

 <p>@(tsee Certify-book) has been modified so that when it compiles a file, it
 loads that object file.</p>

 <p>@(tsee Defstub) has been modified so that it works when the color is hot
 (@(':red') or @(':pink')).</p>

 <p>Several basic, but not particularly commonly used, @(see events) have been
 added or changed.  The obscure axiom @('symbol-name-intern') has been
 modified.  The definition of @('firstn') has been changed.  @(tsee Butlast) is
 now defined.  The definition of @(tsee integer-length) has been modified.  The
 left-hand side of the rewrite rule @('rational-implies2') has been changed
 from @('(* (numerator x) (/ (denominator x)))') to @('(* (/ (denominator x))
 (numerator x))'), in order to respect the fact that @(tsee unary-/) is
 invisible with respect to @(tsee binary-*).  See @(see loop-stopper).</p>

 <p>The `preprocess' process in the waterfall (see @(see hints) for a
 discussion of the @(':do-not') hint) has been changed so that it works to
 avoid case-splitting.  The `simplify' process refuses to force (see @(see
 force)) when there are @(tsee if) terms, including @(tsee and) and @(tsee or)
 terms, in the goal being simplified.</p>

 <p>The function @('apply') is no longer introduced automatically by
 translation of user input to internal form when functions are called on
 inappropriate explicit values, e.g., @('(car 3)').</p>

 <p>The choice of which variable to use as the measured variable in a recursive
 definition has been very slightly changed.</p>")

(defxdoc note-1-7
  :parents (release-notes)
  :short "ACL2 Version 1.7 (released October 1994) Notes"
  :long "<p>@(tsee Include-book) now takes (optionally) an additional keyword
 argument, indicating whether a compiled file is to be loaded.  The default
 behavior is unchanged, except that a warning is printed when a compiled file
 is not loaded.  See @(see include-book).</p>

 <p>A markup language for @(see documentation) strings has been
 implemented, and many of the source files have been marked up using this
 language (thanks largely to the efforts of Laura Lawless).  See markup.
 Moreover, there are translators that we have used to provide versions of the
 ACL2 @(see documentation) in info (for use in emacs), html (for Mosaic), and
 tex (for hardcopy) formats.</p>

 <p>A new event @('defdoc') has been implemented.  It is like @(tsee deflabel),
 but allows redefinition of @(see doc) strings and has other advantages.  See
 @('defdoc').</p>

 <p>We used to ignore corollaries when collecting up the axioms introduced
 about constrained functions.  That bug has been fixed.  We thank John Cowles
 for bringing this bug to our attention.</p>

 <p>The macro @(tsee defstub) now allows a @(':')@(tsee doc) keyword argument,
 so that @(see documentation) may be attached to the name being introduced.</p>

 <p>A new command @(tsee nqthm-to-acl2) has been added to help Nqthm users to
 make the transition to ACL2.  See @(see nqthm-to-acl2), which also includes a
 complete listing of the relevant tables.</p>

 <p>Many function names, especially of the form ``foo@('-lst')'', have been
 changed in order to support the following convention, for any ``foo'':</p>

 <p>@('(foo-listp lst)') represents the notion @('(for x in lst always foop
 x)').</p>

 <p>A complete list of these changes may be found at the end of this note.  All
 of them except @('symbolp-listp') and @('list-of-symbolp-listp') have the
 string ``@('-lst')'' in their names.  Note also that @('keyword-listp') has
 been renamed @(tsee keyword-value-listp).</p>

 <p>Accumulated persistence has been implemented.  It is not connected to
 @(':')@(tsee brr) or rule monitoring.  See @(see accumulated-persistence).</p>

 <p>@(':Trigger-terms') has been added for @(':')@(tsee linear) rule classes,
 so you can hang a @(see linear) rule under any addend you want.  See @(see
 linear), which has been improved and expanded.</p>

 <p>ACL2 now accepts @('256') @(see characters) and includes the Common Lisp
 functions @(tsee code-char) and @(tsee char-code).  However, ACL2 controls the
 lisp reader so that @('#\\c') may only be used when @('c') is a single
 standard character or one of @('Newline'), @('Space'), @('Page'), @('Rubout'),
 @('Tab').  If you want to enter other @(see characters) use @(tsee code-char),
 e.g., @('(coerce (list (code-char 7) (code-char 240) #a) 'string)').  See
 @(see characters).  Note: our current handling of @(see characters) makes the
 set of theorems different under Macintosh Common Lisp (MCL) than under other
 Common Lisps.  We hope to rectify this situation before the final release of
 ACL2.</p>

 <p>A new @(see table), @(tsee macro-aliases-table), has been implemented, that
 associates macro names with function names.  So for example, since @(tsee
 append) is associated with @(tsee binary-append), the form @('(disable
 append)') it is interpreted as though it were @('(disable binary-append)').
 See @(see macro-aliases-table), see @(see add-macro-alias) and see @(see
 remove-macro-alias).</p>

 <p>The implementation of conditional metalemmas has been modified so that the
 metafunction is applied before the hypothesis metafunction is applied.  See
 @(see meta).</p>

 <p>The Common Lisp functions @(tsee acons) and @(tsee endp) have been defined
 in the ACL2 logic.</p>

 <p>We have added the symbol @(tsee declare) to the list @('*acl2-exports*'),
 and hence to the package @('\"ACL2-USER\"').</p>

 <p>A new hint, @(':restrict'), has been implemented.  See @(see hints).</p>

 <p>It used to be that if @(':')@(tsee ubt) were given a number that is greater
 than the largest current @(see command) number, it treated that number the
 same as @(':')@(tsee max).  Now, an error is caused.</p>

 <p>The @(see table) @(':force-table') has been eliminated.</p>

 <p>A command @(':')@(tsee disabledp) (and macro @(tsee disabledp)) has been
 added; see @(see disabledp).</p>

 <p>@(see Compilation) via @(':')@(tsee set-compile-fns) is now suppressed
 during @(tsee include-book).  In fact, whenever the @(see state) global
 variable @(tsee ld-skip-proofsp) has value @(''')@(tsee include-book).</p>

 <p>Here are some less important changes, additions, and so on.</p>

 <p>Unlike previous releases, we have not proved all the theorems in
 @('axioms.lisp'); instead we have simply assumed them.  We have deferred such
 proofs because we anticipate a fairly major changed in Version 1.8 in how we
 deal with @(see guard)s.</p>

 <p>We used to (accidentally) prohibit the ``redefinition'' of a @(see table)
 as a function.  That is no longer the case.</p>

 <p>The check for whether a @(see corollary) follows tautologically has been
 sped up, at the cost of making the check less ``smart'' in the following
 sense: no longer do we expand primitive functions such as @(tsee implies)
 before checking this propositional implication.</p>

 <p>The @(see command) @(tsee ubt!) has been modified so that it never causes
 or reports an error.  See @(see ubt!).</p>

 <p>ACL2 now works in Harlequin LispWorks.</p>

 <p>The user can now specify the @(':trigger-terms') for @(':')@(tsee linear)
 rules.  See @(see linear).</p>

 <p>The name of the system is now ``ACL2''; no longer is it ``Acl2''.</p>

 <p>The raw lisp counterpart of @(tsee theory-invariant) is now defined to be a
 no-op as is consistent with the idea that it is just a call of @(tsee
 table).</p>

 <p>A bug was fixed that caused @(see proof-builder) @(see instructions) to be
 executed when @(tsee ld-skip-proofsp) was @('t').</p>

 <p>The function @(tsee rassoc) has been added, along with a corresponding
 function used in its @(see guard), @('r-eqlable-alistp').</p>

 <p>The @(tsee in-theory) event and hint now print a warning not only when
 certain ``primitive'' @(':')@(tsee definition) rules are @(see disable)d, but
 also when certain ``primitive'' @(':')@(tsee executable-counterpart) rules are
 @(see disable)d.</p>

 <p>The modified version of @('trace') provided by ACL2, for use in raw Lisp,
 has been modified so that the lisp special variable @('*trace-alist*') is
 consulted.  This alist associates, using @(tsee eq), values with their print
 representations.  For example, initially @('*trace-alist*') is a one-element
 list containing the pair @('(cons state '|*the-live-state*|)').</p>

 <p>The system now prints an observation when a form is skipped because the
 default color is @(':red') or @(':pink').  (Technically: @('when-cool') has
 been modified.)</p>

 <p>Additional protection exists when you submit a form to raw Common Lisp that
 should only be submitted inside the ACL2 read-eval-print loop.</p>

 <p>Here is a complete list of the changes in function names described near the
 top of this note, roughly of the form</p>

 @({
  foo-lst --> foo-listp
 })

 <p>meaning: the name ``@('foo-lst')'' has been changed to
 ``@('foo-listp').''</p>

 @({
  symbolp-listp    --> symbol-listp
  list-of-symbolp-listp  --> symbol-list-listp
                         {for consistency with change to symbol-listp}
  rational-lst     --> rational-listp
                       {which in fact was already defined as well}
  integer-lst      --> integer-listp
  character-lst    --> character-listp
  stringp-lst      --> string-listp
  32-bit-integer-lst   --> 32-bit-integer-listp
  typed-io-lst     --> typed-io-listp
  open-channel-lst --> open-channel-listp
  readable-files-lst   --> readable-files-listp
  written-file-lst --> written-file-listp
  read-file-lst    --> read-file-listp
  writeable-file-lst   --> writable-file-listp
                       {note change in spelling of ``writable''}
  writeable-file-lst1  --> writable-file-listp1
  pseudo-termp-lst     --> pseudo-term-listp
  hot-termp-lst --> hot-term-listp {by analogy with pseudo-term-listp}
  weak-termp-lst   --> weak-term-listp
  weak-termp-lst-lst   --> weak-termp-list-listp
  ts-builder-case-lstp -> ts-builder-case-listp
  quotep-lst       --> quote-listp
  termp-lst        --> term-listp
  instr-lst        --> instr-listp
  spliced-instr-lst    --> spliced-instr-listp
  rewrite-fncallp-lst  --> rewrite-fncallp-listp
  every-occurrence-equiv-hittablep1-lst -->
              every-occurrence-equiv-hittablep1-listp
  some-occurrence-equiv-hittablep1-lst  -->
              some-occurrence-equiv-hittablep1-listp
              {by analogy with the preceding, even though it's a
               ``some'' instead of ``all'' predicate]
  almost-quotep1-lst   --> almost-quotep1-listp
  ffnnames-subsetp-lst --> ffnnames-subsetp-listp
  boolean-lstp     --> boolean-listp
  subst-expr1-lst-okp  --> subst-expr1-ok-listp
 })")

(defxdoc note-1-8
  :parents (release-notes)
  :short "ACL2 Version 1.8 (May, 1995) Notes"
  :long "<p>See @(see note-1-8-update) for yet more recent changes.</p>

 <p>@(see Guard)s have been eliminated from the ACL2 logic.  A summary is
 contained in this brief note.  Also see @(see defun-mode) and see @(see
 set-guard-checking).</p>

 <p>@(see Guard)s may be included in @(see defuns) as usual but are ignored
 from the perspective of admission to the logic: functions must terminate on
 all arguments.</p>

 <p>As in Nqthm, primitive functions, e.g., @(tsee +) and @(tsee car),
 logically default unexpected arguments to convenient values.  Thus, @('(+ 'abc
 3)') is @('3') and @('(car 'abc)') is @('nil').  See @(see programming), and
 see the @(see documentation) for the individual primitive functions.</p>

 <p>In contrast to earlier versions of ACL2, Version 1.8 logical functions are
 executed at Nqthm speeds even when @(see guard)s have not been verified.  In
 versions before 1.8, such functions were interpreted by ACL2.</p>

 <p>Colors have been eliminated.  Two ``@(see defun-mode)s'' are supported,
 @(':')@(tsee program) and @(':')@(tsee logic).  Roughly speaking, @(':')@(tsee
 program) does what @(':red') used to do, namely, allow you to prototype
 functions for execution without any proof burdens.  @(':')@(tsee Logic) mode
 does what @(':blue') used to do, namely, allow you to add a new definitional
 axiom to the logic.  A global @(see default-defun-mode) is comparable to the
 old default color.  The system comes up in @(':')@(tsee logic) mode.  To
 change the global @(see defun-mode), type @(':')@(tsee program) or
 @(':')@(tsee logic) at the top-level.  To specify the @(see defun-mode) of a
 @(tsee defun) locally use</p>

 <code> @('(declare (xargs :mode mode))').  </code>

 <p>The @(see prompt) has changed.  The initial @(see prompt), indicating
 @(':')@(tsee logic) mode, is</p>

 @({
  ACL2 !>
 })

 <p>If you change to @(':')@(tsee program) mode the @(see prompt) becomes</p>

 @({
  ACL2 p!>
 })

 <p>@(see Guard)s can be seen as having either of two roles: (a) they are a
 specification device allowing you to characterize the kinds of inputs a
 function ``should'' have, or (b) they are an efficiency device allowing
 logically defined functions to be executed directly in Common Lisp.  If a
 @(see guard) is specified, as with @(tsee xargs) @(':')@(tsee guard), then it
 is ``verified'' at defun-time (unless you also specify @(tsee xargs)
 @(':verify-guards nil')).  @(see Guard) verification means what it always has:
 the input @(see guard) is shown to imply the @(see guard)s on all subroutines
 in the body.  If the @(see guard)s of a function are verified, then a call of
 the function on inputs satisfying the @(see guard) can be computed directly by
 Common Lisp.  Thus, verifying the @(see guard)s on your functions will allow
 them to execute more efficiently.  But it does not affect their logical
 behavior and since you will automatically get Nqthm speeds on unverified
 logical definitions, most users will probably use @(see guard)s either as a
 specification device or only use them when execution efficiency is extremely
 important.</p>

 <p>Given the presence of @(see guard)s in the system, two issues are
 unavoidable.  Are @(see guard)s verified as part of the @(tsee defun) process?
 And are @(see guard)s checked when terms are evaluated?  We answer both of
 those questions below.</p>

 <p>Roughly speaking, in its initial @(see state) the system will try to verify
 the @(see guard)s of a @(tsee defun) if a @(':')@(tsee guard) is supplied in
 the @(tsee xargs) and will not try otherwise.  However, @(see guard)
 verification in @(tsee defun) can be inhibited ``locally'' by supplying the
 @(tsee xargs) @(':')@(tsee verify-guards) @('nil').  ``Global'' inhibition can
 be obtained via the @(':')@(tsee set-verify-guards-eagerness).  If you do not
 use the @(':')@(tsee guard) @(tsee xargs), you will not need to think about
 @(see guard) verification.</p>

 <p>We now turn to the evaluation of expressions.  Even if your functions
 contain no @(see guard)s, the primitive functions do and hence you have the
 choice: when you submit an expression for evaluation do you mean for @(see
 guard)s to be checked at runtime or not?  Put another way, do you mean for the
 expression to be evaluated in Common Lisp (if possible) or in the 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,
 should @('(car 'abc)') cause a @(see guard) violation error or return
 @('nil')?</p>

 <p>The top-level ACL2 loop has a variable which controls which sense of
 execution is provided.  To turn ``@(see guard) checking on,'' by which we mean
 that @(see guard)s are checked at runtime, execute the top-level form
 @(':set-guard-checking t').  To turn it off, do @(':set-guard-checking nil').
 The status of this variable is reflected in the @(see prompt).</p>

 @({
  ACL2 !>
 })

 <p>means @(see guard) checking is on and</p>

 @({
  ACL2 >
 })

 <p>means @(see 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</p>

 @({
  ACL2 !>(car 'abc)
 })

 <p>will signal an error, while</p>

 @({
  ACL2 >(car 'abc)
 })

 <p>will return @('nil').</p>

 <p>Note that whether or not @(see guard)s are checked at runtime is
 independent of whether you are operating in @(':')@(tsee program) mode or
 @(':')@(tsee logic) mode and whether theorems are being proved or not.
 (Although it must be added that functions defined in @(':')@(tsee program)
 mode cannot help but check their @(see guard)s because no logical definition
 exists.)</p>

 <p>Version 1.8 permits the verification of the @(see guard)s of theorems, thus
 insuring that all instances of the theorem will evaluate without error in
 Common Lisp.  To verify the @(see guard)s of a theorem named @('name') execute
 the event</p>

 @({
  (verify-guards name).
 })

 <p>If a theorem's @(see guard)s have been verified, the theorem is guaranteed
 to evaluate without error to non-@('nil') in Common Lisp (provided resource
 errors do not arise).</p>

 <p>Caveat about @(tsee verify-guards): @(tsee implies) is a function symbol,
 so in the term @('(implies p q)'), @('p') cannot be assumed true when @('q')
 is evaluated; they are both evaluated ``outside.''  Hence, you cannot
 generally verify the @(see guard)s on a theorem if @(tsee implies) is used to
 state the hypotheses.  Use @(tsee if) instead.  In a future version of ACL2,
 @(tsee implies) will likely be a macro.</p>

 <p>See sum-list-example.lisp for a nice example of the use of Version 1.8.
 This is roughly the same as the documentation for @(see guard-example).</p>

 <p>We have removed the capability to do ``old-style-forcing'' as existed
 before Version 1.5.  See @(see note-1-5).</p>

 <p>NOTE: Some low level details have, of course, changed.  One such change is
 that there are no longer two distinct type prescriptions stored when a
 function is admitted with its @(see guard)s verified.  So for example, the
 type prescription @(see rune) for @(tsee binary-append) is now</p>

 @({
  (:type-prescription binary-append)
 })

 <p>while in Versions 1.7 and earlier, there were two such @(see rune)s:</p>

 @({
  (:type-prescription binary-append . 1)
  (:type-prescription binary-append . 2)
 })

 <p>Nqthm-style forcing on @(see linear) arithmetic assumptions is no longer
 executed when forcing is @(see disable)d.</p>

 <p>Functional instantiation now benefits from a trick also used in Nqthm: once
 a @(see constraint) generated by a @(':functional-instance') lemma instance
 (see @(see lemma-instance)) has been proved on behalf of a successful event,
 it will not have to be re-proved on behalf of a later event.</p>

 <p>@(tsee 1+) and @(tsee 1-) are now macros in the logic, not functions.
 Hence, for example, it is ``safe'' to use them on left-hand sides of rewrite
 rules, without invoking the common warning about the presence of nonrecursive
 function symbols.</p>

 <p>A new @(see documentation) section @(see file-reading-example) illustrates
 how to process forms in a file.</p>

 <p>A new @(see proof-builder) command @('forwardchain') has been added; see
 @(see acl2-pc::forwardchain).</p>

 <p>It is now possible to use quantifiers.  See @(see defun-sk) and see @(see
 defchoose).</p>

 <p>There is a new event @(tsee set-inhibit-warnings), which allows the user to
 turn off warnings of various types.  see @(see set-inhibit-warnings).</p>

 <p>An unsoundness relating @(tsee encapsulate) and @(':functional-instance')
 @(see hints) has been remedied, with a few small effects visible at the user
 level.  The main observable effect is that @(tsee defaxiom) and non-local
 @(tsee include-book) @(see events) are no longer allowed in the scope of any
 @(tsee encapsulate) event that has a non-empty @(see signature).</p>

 <p>When @(tsee certify-book) is called, we now require that the default @(see
 defun-mode) (see @(see default-defun-mode)) be @(':')@(tsee logic).  On a
 related note, the default @(see defun-mode) is irrelevant to @(tsee
 include-book); the mode is always set to @(':')@(tsee logic) initially, though
 it may be changed within the book and reverts to its original value at the
 conclusion of the @(tsee include-book).  A bug in @(tsee include-book)
 prevented it from acting this way even though the @(see documentation) said
 otherwise.</p>

 <p>The @(see documentation) has been substantially improved.  A new section
 ``Programming'' contains @(see documentation) of many useful functions
 provided by ACL2; see @(see programming).  Also, the @(see documentation) has
 been ``marked up'' extensively.  Thus in particular, users of Mosaic will find
 many links in the @(see documentation).</p>

 <p>The symbols @(tsee force), @(tsee mv-nth), and @('acl2-count') have been
 added to the list @('*acl2-exports*').</p>

 <p>We now permit most names from the main Lisp package to be used as names,
 except for names that define functions, macros, or constants.  See @(see
 name).</p>

 <p>We have changed the list of imports from the Common Lisp package to ACL2,
 i.e., the list @('*common-lisp-symbols-from-main-lisp-package*'), to be
 exactly those external symbols of the Common Lisp package as specified by the
 draft Common Lisp standard.  In order to accommodate this change, we have
 renamed some ACL2 functions as shown below, but these and other ramifications
 of this change should be transparent to most ACL2 users.</p>

 @({
  warning      --> warning$
  print-object --> print-object$
 })

 <p>Proof trees are no longer enabled by default.  To start them up,
 @(':')@(tsee start-proof-tree).</p>

 <p>We have added the capability of building smaller images.  The easiest way
 to do this on a Unix (trademark of AT&amp;T) system is: @('make small').</p>

 <p>Here we will put some less important changes, additions, and so on.</p>

 <p>We have added definitions for the Common Lisp function @(tsee position)
 (for the test @(tsee eql)), as well as corresponding versions @(tsee
 position-equal) and @(tsee position-eq) that use tests @(tsee equal) and
 @(tsee eq), respectively.  See @(see position), see @(see position-equal), and
 see @(see position-eq).</p>

 <p>The @(tsee defthm) event @('rational-listp-implies-rationalp-car') no
 longer exists.</p>

 <p>We fixed a bug in the hint mechanism that applied @(':by'), @(':cases'),
 and @(':use') @(see hints) to the first induction goal when the prover
 reverted to proving the original goal by induction.</p>

 <p>We fixed a bug in the handling of @('(set-irrelevant-formals-ok
 :warn)').</p>

 <p>In support of removing the old-style forcing capability, we deleted the
 initialization of @(see state) global @('old-style-forcing') and deleted the
 definitions of @('recover-assumptions'), @('recover-assumptions-from-goal'),
 @('remove-assumptions1'), @('remove-assumptions'), and
 @('split-on-assumptions'), and we renamed @('split-on-assumptions1') to
 @('split-on-assumptions').</p>

 <p>The special value @(''none') in the @(see proof-builder) commands
 @('claim') and @(tsee =) has been replaced by @(':none').</p>

 <p>A bug in the handling of @(see hints) by subgoals has been fixed.  For
 example, formerly a @(':do-not') hint could be ``erased'' by a @(':use') hint
 on a subgoal.  Thanks go to Art Flatau for noticing the bug.</p>

 <p>The functions @('weak-termp') and @('weak-term-listp') have been deleted,
 and their calls have been replaced by corresponding calls of @(tsee
 pseudo-termp) and @('pseudo-term-listp').  The notion of @(tsee pseudo-termp)
 has been slightly strengthened by requiring that terms of the form @('(quote
 ...)') have length 2.</p>

 <p>Performance has been improved in various ways.  At the prover level,
 backchaining through the recognizer alist has been eliminated in order to
 significantly speed up ACL2's rewriter.  Among the other prover changes (of
 which there are several, all technical): we no longer clausify the input term
 when a proof is interrupted in favor of inducting on the input term.  At the
 @(see IO) level, we have improved performance somewhat by suitable
 declarations and proclamations.  These include technical modifications to the
 macros @(tsee mv) and @(tsee mv-let), and introduction of a macro @('the-mv')
 analogous to the macro @(tsee the) but for forms returning multiple
 values.</p>

 <p>The function @('spaces') now takes an extra argument, the current
 column.</p>

 <p>A bug in the @(see proof-builder) @('equiv') command was fixed.</p>

 <p>The function @('intersectp') has been deleted, because it was essentially
 duplicated by the function @(tsee intersectp-equal).</p>

 <p>We now proclaim functions in AKCL and GCL before compiling @(see books).
 This should result in somewhat increased speed.</p>

 <p>The function @('repeat') has been eliminated; use @(tsee make-list)
 instead.</p>

 <p>The @(see proof-builder) command @('expand') has been fixed so that it
 eliminates @(tsee let) (lambda) expressions when one would expect it to.</p>

 <p>A new primitive function, @(tsee mv-nth), has been introduced.  @(tsee
 Mv-nth) is equivalent to @(tsee nth) and is used in place of @(tsee nth) in
 the translation of @(tsee mv-let) expressions.  This allows the user to
 control the simplification of @(tsee mv-let) expressions without affecting how
 @(tsee nth) is treated.  In that spirit, the rewriter has been modified so
 that certain @(tsee mv-nth) expressions, namely those produced in the
 translation of @('(mv-let (a b c)(mv x y z) p)'), are given special
 treatment.</p>

 <p>A minor bug in @('untranslate') has been fixed, which for example will fix
 the printing of conjunctions.</p>

 <p>@('Translate') now takes a @('logicp') argument, which indicates whether it
 enforces the restriction that @(':')@(tsee program) mode functions do not
 occur in the result.</p>

 <p>The modified version of @('trace') provided by ACL2, for use in raw Lisp,
 has been modified so that the lisp special variable @('*trace-alist*') has a
 slightly different functionality.  This alist associates, using @(tsee eq),
 symbols with the print representations of their values.  For example,
 initially @('*trace-alist*') is a one-element list containing the pair
 @('(cons 'state '|*the-live-state*|)').  Thus, one may cons the pair @('(cons
 '*foo* \"It's a FOO!\")') on to @('*trace-alist*'); then until @('*foo*') is
 defined, this change will have no effect, but after for example</p>

 @({
  (defconst *foo* 17)
 })

 <p>then @('trace') will print @('17') as @('\"It's a FOO!\"').</p>

 <p>@('Trace') also traces the corresponding logic function.</p>

 <p>@(see Proof-tree) display has been improved slightly in the case of
 successful proofs and certain event failures.</p>

 <p>The function @('positive-integer-log2') has been deleted.</p>

 <p>The macro @(tsee skip-proofs) now prints a warning message when it is
 encountered in the context of an @(tsee encapsulate) event or a book.  See
 @(see skip-proofs).</p>

 <p>Some functions related to @('the-fn') and @('wormhole1') now have @(see
 defun-mode) @(':')@(tsee program), but this change is almost certain to be
 inconsequential to all users.</p>")

(defxdoc note-1-8-update
  :parents (release-notes)
  :short "ACL2 Version 1.8 (Summer, 1995) Notes"
  :long "<p>ACL2 can now use Ordered Binary Decision Diagram technology.  See
 @(see bdd).  There is also a @(see proof-builder) @('bdd') command.</p>

 <p>ACL2 is now more respectful of the intention of the function @(tsee hide).
 In particular, it is more careful not to dive inside any call of @(tsee hide)
 during equality substitution and case splitting.</p>

 <p>The @(tsee ld) special (see @(see ld)) @(tsee ld-pre-eval-print) may now be
 used to turn off printing of input forms during processing of @(tsee
 encapsulate) and @(tsee certify-book) forms, by setting it to the value
 @(':never'), i.e., @('(set-ld-pre-eval-print :never state)').  See @(see
 ld-pre-eval-print).</p>

 <p>The TUTORIAL documentation section (now obsolete) has, with much help from
 Bill Young, been substantially improved to a bona fide introduction.</p>

 <p>The term pretty-printer has been modified to introduce @('(<= X Y)') as an
 abbreviation for @('(not (< Y X))').</p>

 <p>Forward chaining and linear arithmetic now both benefit from the evaluation
 of ground subterms.</p>

 <p>A new macro @(tsee set-inhibit-output-lst) has been defined.  This should
 be used when setting the @(see state) global @('inhibit-output-lst'); see
 @(see set-inhibit-output-lst) and see @(see proof-tree).</p>

 <p>The test for redundancy in definitions includes the @(see guard) and type
 declarations.  See @(see redundant-events).</p>

 <p>See @(see generalized-booleans) for a discussion of a potential soundness
 problem for ACL2 related to the question: Which Common Lisp functions are
 known to return Boolean values?</p>

 <p>Here we will put some less important changes, additions, and so on.</p>

 <p>A bug has been fixed so that now, execution of @(':comp t') (see @(see
 comp)) correctly handles non-standard characters.</p>

 <p>A bug in @(tsee digit-char-p) has been fixed, so that the ``default'' is
 @('nil') rather than @('0').</p>

 <p>@(tsee True-listp) now tests the final @(tsee cdr) against @('nil') using
 @(tsee eq) instead of @(tsee equal), for improved efficiency.  The logical
 meaning is, however, unchanged.</p>

 <p>@(tsee Put-assoc-equal) has been added to the logic (it used to have
 @(':')@(tsee defun-mode) @(':')@(tsee program), and has been documented.</p>")

(defxdoc note-1-9
  :parents (release-notes)
  :short "ACL2 Version 1.9 (Fall, 1996) Notes"
  :long "<p>By default, when the system is started it is illegal to use the
 variable @(tsee STATE) as a formal parameter of a function definition.  The
 aim is to prevent novice users from stumbling into the Byzantine syntactic
 restrictions on that variable symbol.  Use</p>

 @({
  :set-state-ok t
 })

 <p>or, equivalently,</p>

 @({
  (set-state-ok t)
 })

 <p>to switch back to the old default mode.  See @(see set-state-ok)</p>

 <p>@('Set-state-ok') is an event that affects the ACL2 defaults table (see
 @(see acl2-defaults-table)).  Recall that when books are included, the
 defaults table is restored to its pre-inclusion state.  Thus, while a
 @('set-state-ok') form will permit the book to define a @('state')-using
 function, it will not permit the user of the book to make such a definition.
 We recommend putting @('(set-state-ok t)') in any book that defines a
 @('state') using function.</p>

 <p>Books certified under Version 1.8 must be recertified under Version 1.9.
 See :DOC version.</p>

 <p>The simplifier has been made to look out for built-in clauses, whereas in
 past versions such clauses were only noticed by the ``preprocessor'' at the
 top of the waterfall.  THIS CHANGE MAY PREVENT OLD SCRIPTS FROM REPLAYING!
 The undesirable side-effect is caused by the fact that @(':HINTS') require you
 to refer to clauses by their exact name (see @(see goal-spec)) and because the
 new simplifier proves more clauses than before, the goals produced have
 different names.  Thus, if a script uses @(':HINTS') that refer to clauses
 other than \"Goal\", e.g., \"Subgoal 1.3\" then the hint may be applied to a
 different subgoal than originally intended.</p>

 <p>The use of built-in-clauses has been made more efficient.  If a set of
 clauses arise often in a piece of work, it might be advantageous to build them
 in even if that results in a large set (hundreds?) of built-in clauses.  See
 @(see built-in-clause)</p>

 <p>Wormholes can now be used in :logic mode functions. See @(see wormhole)</p>

 <p>It is now possible to provide ``computed hints.''  For example, have you
 ever wished to say ``in all goals with a name like this, :use that'' or ``if
 this term is in the subgoal, then :use that''?  Well, see @(see
 computed-hints) and the extraordinarily long example in see @(see
 using-computed-hints).</p>

 <p>@('Hide') terms may be rewritten with :rewrite rules about @('hide').  See
 @(see hide), where we also now explain why @('hide') terms are sometimes
 introduced into your proof attempts.</p>

 <p>A bug that sometimes caused the ``non-lazy IF'' hard error message was
 fixed.</p>

 <p>A bug that sometimes caused a hard error in forward chaining was fixed.</p>

 <p>A bug in print-rules (:pr) was fixed.</p>

 <p>We report the use of :executable-counterparts in the evaluation of SYNTAXP
 forms.</p>

 <p>Some documentation errors were fixed.</p>

 <p>A bug in parent-tree tracking in add-literal-and-pt was fixed.</p>

 <p>A bug in ok$, go$ and eval$ was fixed.</p>

 <p>Clausify now optimizes (mv-nth 'k (list x0 ... xk ... xn)) to xk.</p>")

(defxdoc note-2-0
  :parents (release-notes)
  :short "ACL2 Version 2.0 (July, 1997) Notes"
  :long "<p>This is the first version of ACL2 released under the copyright of
 the University of Texas (UT).  Future releases of ACL2 will be made from UT
 rather than Computational Logic, Inc. (CLI).  Version 2.0 is just Version 1.9
 as released by CLI, with a few bugs fixed.</p>

 <p>A bug causing an infinite loop was fixed in functional instantiation.  The
 bug manifested itself when two conditions occurred simultaneously: First, the
 functional substitution replaces a function symbol, e.g., @('FOO'), with a
 @('LAMBDA') expression containing a free variable (a variable not among in the
 @('LAMBDA') formals).  And, second, in one of the constraints being
 instantiated there is a call of the function symbol @('FOO') within the scope
 of another @('LAMBDA') expression.  Unless you used such a functional
 substitution, this bug fix will not affect you.</p>

 <p>Less important notes:</p>

 <p>The implementation of @('PRINC$') was changed so that it was no longer
 sensitive to the external setting of @('*print-base*') and other Common Lisp
 special variables.</p>

 <p>Typographical errors were fixed in the documentation.</p>")

(defxdoc note-2-1
  :parents (release-notes)
  :short "ACL2 Version  2.1 (December, 1997) Notes"
  :long "<p>The identity function @(tsee case-split) has been added.  It is
 similar to @(tsee force) but causes an immediate split of the top-level goal
 on whether the indicated hypothesis is true.</p>

 <p>Less important notes:</p>

 <p>Minor bugs in the documentation were fixed.</p>")

(defxdoc note-2-2
  :parents (release-notes)
  :short "ACL2 Version  2.2 (August, 1998) Notes"
  :long "<p>Important changes:</p>

 <p>A bug was fixed in the compile command, @(':comp').  The compiled code
 produced by @(':comp') in previous versions could be wildly incorrect because
 of a confusion between the printer and the reader regarding what was the
 current Lisp @('*package*').  This bug could manifest itself only if you used
 the @(':comp') command to compile previously uncompiled functions while the
 current package was different from @('\"ACL2\"').  What happened in that
 situation depended upon what symbols were imported into your current package.
 The most likely behavior is that the compiler would break or complain or the
 resulting compiled code would call functions that did not exist.</p>

 <p>There have been no other important changes to the code.</p>

 <p>However, this release contains some useful new books, notably those on the
 @('books') subdirectories @('cli-misc') and @('ihs').  Both have @('README')
 files.  The @('ihs') books provide support for integer hardware
 specifications.  These books were crucial to Bishop Brock's successful
 modeling of the Motorola CAP.  We thank Bishop for producing them and we thank
 all those who worked so hard to get these books released.  We highly recommend
 the @('ihs') books to those modeling ALUs and other arithmetic components of
 microprocessors or programming languages.</p>

 <p>In previous versions of ACL2, the arithmetic books, found on
 @('books/arithmetic/'), included the addition of several unproved axioms
 stating properties of the rationals that we believed could be derived from our
 ``official'' axioms but which we had not mechanically proved.  The axioms were
 found in the book @('rationals-with-axioms.lisp'), which was then used in the
 uppermost arithmetic books @('top.lisp') and @('top-with-meta.lisp').  John
 Cowles has now provided us with ACL2 proofs of those ``axioms'' and so in this
 release you will find both @('rationals-with-axioms.lisp') and
 @('rationals-with-axioms-proved.lisp').  The former is provided for
 compatibility's sake.  The latter is identical but contains @('defthm')s where
 the former contains @('defaxiom')s.  The top-most books have been rebuilt
 using ``@('-axioms-proved')'' book.  Thanks John.</p>

 <p>Less important notes:</p>

 <p>Bishop Brock found a bug in @('translated-acl2-unwind-protectp4').  Jun
 Sawada reported a bug in linear arithmetic that caused us not to prove certain
 trivial theorems concluding with @('(not (equal i j))').  We have fixed
 both.</p>

 <p>We now prohibit definitions that call certain event commands such as
 @('DEFTHM') and @('TABLE') because our Common Lisp implementations of them
 differ from their ACL2 meanings (so that compiled books can be loaded
 correctly and efficiently).</p>

 <p>Minor bugs in the documentation were fixed.</p>")

(defxdoc note-2-3
  :parents (release-notes)
  :short "ACL2 Version  2.3 (October, 1998) Notes"
  :long "<p>Important changes:</p>

 <p>Versions of ACL2 preceding this one contain a subtle soundness bug!  We
 found a flaw in our detection of @(see subversive-recursions).  The bug
 allowed some subversive recursions to slip through undetected.</p>

 <p>We believe it would have been difficult to have exploited this flaw
 inadvertently.  In particular, the following five conditions are necessary.
 <br></br> <br></br>

 (1) Introduce a constrained function, say @('f'), via an @('encapsulate').
 <br></br> <br></br>

 (2) In the same encapsulation, define a clique of mutually recursive
 functions.  This clique must be non-@('local') and in @(':logic') mode.
 <br></br> <br></br>

 (3) In that mutually recursive clique, use the constrained function
 @('f') (perhaps indirectly) so that the termination argument for the clique
 depends on properties of the <i>witness</i> for @('f').  Thus, @('f') or some
 other function dependent upon @('f'), must be used in an argument in a
 recursive call or in a term governing a recursive call.  Furthermore, the use
 of @('f') must be such that the termination proof cannot be done without
 exploiting properties of the witness for @('f').  Other uses of the
 constrained functions in the clique are ok.  <br></br> <br></br>

 (4) Fail to include the exploited properties of @('f') among the constraints
 of the encapsulation.  <br></br> <br></br>

 (5) Later, outside the encapsulation, explicitly use a functional
 instantiation in which @('f') is replaced by a function not enjoying the
 crucial properties.  <br></br> <br></br>

 See @(see subversive-recursions) for details.</p>

 <p>Less important notes:</p>

 <p>We have begun to write some introductory tutorial material for those who
 wish to learn to program in ACL2.  Most of this material is HTML-based.  See
 the Hyper-Card on the ACL2 home page.</p>

 <p>The documentation of @(tsee verify-guards) was improved to explain why one
 might wish to verify the ``guards'' of a @('defthm') event.  The missing
 documentation was noticed by John Cowles.</p>

 <p>A bug was fixed in cross fertilization.  The bug caused the system to
 report that it had substituted one term for another when in fact no
 substitution occurred.  The bug was noticed by Bill McCune.</p>")

(defxdoc note-2-4
  :parents (release-notes)
  :short "ACL2 Version  2.4 (August, 1999) Notes"
  :long "<p>Important changes:</p>

 <p>We corrected a soundness bug in Version 2.3 related to the handling of
 @(tsee immediate-force-modep).  The bad behavior was noticed by Robert Krug.
 Thanks!</p>

 <p>We corrected a bug that permitted @(tsee verify-guards) to accept a
 function even though a subfunction had not yet had its guards verified.
 Thanks to John Cowles for noticing this.</p>

 <p>User defined single-threaded objects are now supported.  See @(see
 stobj).</p>

 <p>Less important notes:</p>

 <p>We corrected a bug that prevented the intended expansion of some recursive
 function calls.</p>

 <p>We changed the handling of the primitive function @(tsee ILLEGAL), which is
 logically defined to be @('nil') but which is programmed to signal an error,
 so that when it is evaluated as part of a proof, it does not signal an error.
 The old handling of the function prevented some guard proofs involving @(tsee
 THE) or @(tsee LET)s with internal declarations.</p>

 <p>We corrected a bug that permitted some @('LOCAL') @('DEFAXIOM') events to
 slip into certified books.</p>

 <p>We corrected a bug that prevented the correct undoing of certain
 @('DEFPKG') forms.</p>

 <p>Changes were made to support CMU Lisp.  Pete Manolios helped with these
 changes.</p>

 <p>Changes were made to make the make files more compatible with Allegro
 Common Lisp.  Jun Sawada, who has been a great help with keeping ACL2 up and
 running at UT on various platforms, was especially helpful.  Thanks Jun.</p>")

(defxdoc note-2-5
  :parents (release-notes)
  :short "ACL2 Version  2.5 (June, 2000) Notes"
  :long "<p>Important Changes:</p>

 <p>Concurrent with the release of ACL2 Version 2.5 is the publication of two
 books about ACL2.  See the ``Books and Papers about ACL2 and Its
 Applications'' on the ACL2 Home Page.</p>

 <p>The @('books') subdirectory now contains many new certifiable books,
 including solutions to the exercises in the two published books and full
 scripts for the case studies.  See @('books/README.html').</p>

 <p>Improved Unix @('Makefile') support for book certification has also been
 written.  See @('books/README.html').</p>

 <p>The list of symbols in @('*acl2-exports*') has been considerably expanded.
 If you have packages built by importing @('*acl2-exports*') you might want to
 look carefully at the new value of that constant.  The new value includes all
 @(':logic') mode functions as of Version 2.5, as well as all documented macros
 and all built-in theorem names.</p>

 <p>@(tsee Include-book) and @(tsee certify-book) were modified to have some
 additional keyword arguments.  It is possible to certify a book containing
 @(tsee defaxiom) and/or @(tsee skip-proofs) events and get warning messages or
 errors signaled, according to the settings of these new flags.  In addition,
 it is possible to specify in @('include-book') whether the book must be
 certified (under penalty of error if not).  The default values of these new
 arguments cause warnings to be printed rather than errors signaled.</p>

 <p>The above change involved altering the form of certificate files.  When
 books certified under previous versions are included, more warnings will be
 generated because these books are considered possibly to contain @('defaxiom')
 and/or @('skip-proofs') events.</p>

 <p>We anticipate further changes to this aspect of books and consider the
 current mechanisms (for controlling whether warnings or errors are signaled)
 just a prototype.  See also the discussion below of ``soundness related''
 warnings.  Your suggestions are welcome.</p>

 <p>A discrepancy between ACL2 and Common Lisp was fixed, having to do with
 @('declare ignore').  In past versions of ACL2, a formal parameter of a
 @('defun') was considered ignored if it was not used in the body, the guard or
 the measure of the @('defun').  That meant that a variable used only in the
 guard could not be declared ignored in ACL2; but some Common Lisp compilers
 would complain because the variable was not used in the body.  Now, ACL2
 considers a variable ignored if it is not used in the body.</p>

 <p>ACL2 can now be built in releases 5.0 and later of Allegro Common Lisp.
 (Other releases of Allegro Common Lisp and of other lisps continue to be
 supported as well.)  This includes Allegro Common Lisp running on Windows 98
 platforms.  John Cowles helped us do some testing and answered questions for
 us.  Thanks John!</p>

 <p>We incorporated Ruben Gamboa's changes to allow the building of a variant,
 ACL2(r), of ACL2, in which the user can reason about the real numbers using
 non-standard analysis.  See @(see real).  Note that ACL2(r) and ACL2 have
 different underlying theories, and books certified in one system may not be
 included in the other.  For backward compatibility and to ensure a smooth
 transition, ACL2 is built by default, not ACL2(r).  This is a compile-time
 switch; see the makefile for instructions.  There should be no changes to ACL2
 resulting from the capability of building ACL2(r) from the same sources.  Also
 see @(see acknowledgments) for more on the history of ACL2(r).</p>

 <p>A large number of bugs (some affecting soundness) were fixed, and many
 small new features were added.  See below.</p>

 <p>Less Important Changes:</p>

 <p>Some warnings are now considered ``soundness related,'' namely, those that
 advise you that an uncertified book has been included or that a book
 containing @('DEFAXIOM') or @('SKIP-PROOFS') events.  (Technically,
 @('DEFAXIOM')s do not imperil soundness in the proof- theoretic sense, though
 they may imperil the validity of theorems.  But you should know when a book has
 added an axiom to your logic!)  In previous versions of ACL2, all warnings
 were inhibited if the token @('warning') was included in the argument to
 @(tsee set-inhibit-output-lst).  Now, soundness related warnings are printed
 even if @('warning')s have been inhibited.  To inhibit all warnings, supply
 the token @('warning!') to @('set-inhibit-output-lst').</p>

 <p>Several bugs in @(tsee defstobj) were fixed, relating to the possibility
 that some of the subfunctions introduced by the @('defstobj') were already
 defined.</p>

 <p>@(':')@(tsee Puff) no longer tries to expand @(tsee defstobj) events.
 Previously, the attempt would cause a hard error.</p>

 <p>A soundness bug was fixed.  The bug might have been exercised if you had an
 alternative definition (implies hyps (equiv (fn ...) body)) in which equiv is
 an equivalence relation other than EQUAL.  In this case, calls of fn might
 have been expanded to body in places that were not equiv-hittable.</p>

 <p>An obscure soundness bug was fixed.  The bug was exercised only if you had
 a metafunction with a computed hypothesis (i.e., a ``meta hypothesis
 function''), the hypothesis contained a free variable, i.e., a variable not
 involved in the term being rewritten, and the free variable occurred in the
 output of the metafunction.  The possibility of this bug was brought to our
 attention by Robert Krug.</p>

 <p>We fixed a bug in the handling of @('hide') related to the question of
 whether a variable symbol occurs in a term.  The old code did not find the
 variable and could cause the system to throw away a hypothesis about it on the
 grounds that it was never mentioned.  Rob Sumners helped discover this
 problem.</p>

 <p>The handling of @(':')@(tsee elim) rules was generalized, permitting
 arbitrary known equivalence relations instead of merely @('equal') in the
 concluding equality.</p>

 <p>The printing of runes (rule names; see @(see rune)) used has been made
 \"deterministic,\" both in proof output and in proof attempt summaries, by
 sorting the runes before printing.</p>

 <p>The handling of free variables has been improved for hypotheses such as
 @('(< 0 X)'), and more generally, any hypotheses involving a comparison with
 @('0') (even for example @('(< X 1)') where @('X') is known to be an integer,
 which is handled as @('(<= X 0)')).  Thanks to Robert Krug for bringing
 relevant examples to our attention.</p>

 <p>A new value, @(':comp'), has been implemented for the
 @(':load-compiled-file') keyword of @(tsee include-book).  If this value is
 supplied, then a compiled file will always be loaded, even if that requires
 creating the compiled file first.</p>

 <p>The event @('include-book') now generates a warning when a compiled file is
 expected but not found (see @(see include-book)).  Formerly, it only did so
 when executed at the top level; it failed to generate the warning when
 executed on behalf of a surrounding @('include-book') command.</p>

 <p>Certain redefinition warnings generated by Allegro Common Lisp have been
 eliminated.</p>

 <p>A new key has been implemented for the @(tsee acl2-defaults-table),
 @(':bogus-mutual-recursion-ok'), set with @(':')@(tsee
 set-bogus-mutual-recursion-ok).  Thanks to David Russinoff for pointing out
 the utility of such a key.</p>

 <p>A bug was fixed in @(tsee defun-sk) that prevented its generated events
 from being accepted when guard verification is being performed.  Thanks to
 Bill Young for bringing this problem to our attention.  A second bug was
 brought to our attention by Pete Manolios, which was causing certain @(tsee
 defun-sk) events to be rejected.  That problem has been fixed, and an
 \"Infected\" warning has also been eliminated.</p>

 <p>The command @(tsee good-bye) now works with Allegro Common Lisp.</p>

 <p>A low-level bug was fixed that could, for example, cause an error such as
 \"Error: Expected 5 args but received 4 args\" when interrupting a @('local')
 event.</p>

 <p>A bug has been fixed in the @(see proof-builder) related to definition
 expansion.  Thanks to Pete Manolios for bringing this to our attention with a
 simple example.</p>

 <p>A bug has been fixed related to the @(':')@(see bdd) hint in the presence
 of @(see equivalence) relations.  Thanks to Pete Manolios for bringing this to
 our attention with a simple example.</p>

 <p>The functions @(tsee position) and @(tsee position-equal) formerly required
 the second argument to be a true list.  In accordance with Common Lisp, we now
 also allow the second argument to be a string.  This could cause earlier
 proofs about these functions to fail unless @(tsee true-listp) is known to
 hold where necessary.</p>

 <p>Robert Krug wrote a patch, which has been incorporated, to prevent certain
 infinite loops that can arise in linear arithmetic.  Thanks, Robert!</p>

 <p>The macro @(tsee let*) no longer requires the bound variables to be
 distinct.</p>

 <p>An obscure bug was fixed related to congruence rules.  The bug would
 sometimes cause ACL2 to behave as though no rules (other than equality) were
 available for some argument positions.  Thanks to Pete Manolios for bringing
 this bug to our attention.</p>

 <p>Documentation topics have been added for @(tsee hard-error) and @(tsee
 prog2$), and the documentation for @(tsee illegal) has been improved.  Thanks
 to Rob Sumners for a useful suggestion in the examples in documentation for
 @('prog2$') and a fix in documentation for @(tsee sublis).</p>

 <p>The event form @(tsee certify-book) was made more secure, in that it can
 now catch attempts to write a book to disk during its certification.  Thanks
 to Rob Sumners for pointing out the insecurity of the existing mechanism.</p>

 <p>A Y2K problem was fixed with our applicative handling of dates.</p>

 <p>Accessors and updaters for @(tsee stobj)s have been made more efficient
 when the underlying lisp is Allegro Common Lisp, by the use of appropriate
 simple array declarations.</p>

 <p>A raw Lisp break had been possible when a certified book that had no guard
 verification was included in a session after @('(')@(tsee
 set-verify-guards-eagerness)@(' 2)').  This has been fixed.</p>

 <p>The keyword command @(':')@(tsee comp) can now be used to compile only raw
 Lisp functions, excluding executable counterparts, by supplying the argument
 @(':raw').</p>

 <p>Rewrite rule @('nth-of-character-listp') was removed from source file
 axioms.lisp since it is essentially subsumed by @('characterp-nth').</p>

 <p>Printing has been sped up.  In one example the improvement was over 50% in
 both Allegro and GCL.</p>

 <p>We now allow printing in a \"downcase\" mode, where symbols are printed in
 lower case.  All printing functions except @('print-object$') now print
 characters in lower case for a symbol when the ACL2 state global variable
 @('print-case') has value @(':downcase') and vertical bars are not necessary
 for printing that symbol.  See @(see IO) for a discussion of the macros
 @('acl2-print-case') and @('set-acl2-print-case').  The default printing
 remains unchanged, i.e., symbols are printed in upper case when vertical bars
 are not required.</p>

 <p>A low-level printing function (@('prin1$')) was modified so that it is not
 sensitive to various Common Lisp globals related to printing.  So for example,
 the function @(tsee fmt) is no longer sensitive to the value of Common Lisp
 global @('*print-case*').  (The preceding paragraph explains how to control
 the case for printing in ACL2.)</p>

 <p>The definition of @(tsee array1p) was fixed so that the
 @(':maximum-length') of an array must be strictly greater than the number
 specified in the @(':dimensions') field; they may no longer be equal.  This
 was always the intention; the documentation (see @(see arrays)) has remained
 unchanged.  The corresponding change was also made to @(tsee array2p).
 Allegro Common Lisp formerly caused an error when @(tsee compress1) was called
 on an array where the numbers above were equal; now, we get a guard violation
 instead, which is appropriate.</p>

 <p>In the context of theories, a name now represents not just the
 corresponding @(':definition') @(see rune), as it has done in earlier versions
 of ACL2, but also the corresponding @(':')@(tsee induction) rune.  See @(see
 theories) for a discussion of runic designators.  Most users will rarely, if
 ever, notice this change.  One situation where this change will make a
 difference is after executing @('(in-theory (current-theory 'foo))') followed
 by @('(in-theory (enable bar))'), where function @('bar') is introduced after
 event @('foo'), and @('bar') is recursively defined.  The latter @(tsee
 in-theory) form now enables the rune @('(:induction bar)'), which implies that
 the prover can use the induction scheme stored at definition time for
 @('bar').  Formerly, the rune @('(:induction bar)') was not enabled by
 @('(in-theory (enable bar))'), and hence the induction scheme for @('bar') was
 ignored even when explicit @(':induct') hints were supplied.</p>

 <p>You may now supply @(tsee xargs) keyword pair @(':normalize nil') in order
 to prevent certain definitions from ``hanging'' when there are many
 @('if')-subexpressions.  see @(see defun).</p>

 <p>We now translate type declarations of @('real') into guards, as we have
 already done for other types such as @('rational').  For example, @('(declare
 (type real x))') generates the @(see guard) @('(rationalp x)').  See @(see
 type-spec).</p>

 <p>The theorem prover now behaves reasonably under the combination of
 specifying a value of @('t') both for @(':')@(tsee otf-flg) and for a hint
 @(':do-not-induct').  Previously, it aborted the first time it would have
 otherwise pushed a goal for induction, but now, it will continue and wait
 until all induction subgoals have been pushed before it aborts.</p>

 <p>We changed slightly the definition of @(tsee round).  However, we believe
 that the new definition is equivalent to the old.</p>

 <p>The definition of Common Lisp function @(tsee substitute) has been
 added.</p>

 <p>The following changes have been made in the use of file names within ACL2.
 We thank Warren Hunt and John Cowles for running some tests of these changes
 on Macintosh and Windows 98 platforms (respectively).</p>

 <blockquote>

 <p>(1) Names of directories and files now use a syntax like that used for Unix
 (trademark of AT&amp;T), where directories are separated using the ``@('/')''
 character even when the operating system is not Unix or Linux.  See @(see
 pathname).  ACL2 also continues to support its notion of <i>structured
 pathnames</i> from Version 2.4 and before, but might not do so in future
 releases and hence no longer documents such syntax.</p>

 <p>(2) The command @(':')@(tsee set-cbd) may now take a relative pathname as
 an argument.</p>

 <p>(3) When the macro @(tsee ld) is given a file name as a value for @(tsee
 standard-oi), then if that file name is a relative pathname it refers to the
 result of prepending the connected book directory (see @(see pathname), see
 @(see cbd), and see @(see set-cbd)) in order to obtain an absolute pathname.
 Similarly for the @('ld') specials @(tsee standard-co) and @(tsee
 proofs-co).</p>

 </blockquote>

 <p>It is no longer necessary to issue @(':')@(tsee set-state-ok)@(' t') if you
 include a @(see stobj) declaration for @(tsee state), for example:</p>

 @({
  (declare (xargs :stobjs state))
 })

 <p>See @(see declare-stobjs).</p>

 <p>The @(see proof-builder) has been cleaned up a bit, including the
 documentation and the capability (once again) to define pc-macro commands (see
 @(see define-pc-macro)) and proof-builder meta commands (see @(see
 define-pc-meta)).</p>

 <p>Recall that events generate summaries that include a line beginning with
 ``@('Warnings:')'', which is followed (on the same line) by zero or more brief
 strings that summarize the warnings generated by that event.  Formerly, this
 warnings summary for an @(tsee encapsulate) or @(tsee include-book) event did
 not include the summary strings for warnings generated by subsidiary events.
 This has been fixed.</p>

 <p>Macro @(tsee cw) has been documented and now expands to a call of a
 @(';')@(tsee logic) mode function.  See @(see cw) for a way to print to the
 screen without having to involve the ACL2 @(tsee state).  Thanks to Rob
 Sumners for suggesting that we document this useful utility.</p>

 <p>Functions @('duplicates'), @('add-to-set-equal'), @('intersection-eq'),
 @('evens'), and @('odds') are now @(':')@(tsee logic) mode functions.</p>")

(defxdoc |NOTE-2-5(R)|

; Do not make this form conditional on #+:non-standard-analysis, because we
; want to make just one version of the documentation.

  :parents (release-notes)
  :short "ACL2 Version  2.5(r) (June, 2000) Notes"
  :long "<p>Important changes to non-standard version:</p>

 <p>Please see @(see note-2-5) for changes to Version 2.5 of ACL2.  We hope to
 write more documentation for ACL2(r) in the future.</p>")

(defxdoc note-2-6
  :parents (release-notes)
  :short "ACL2 Version  2.6 (November, 2001) Notes"
  :long "<p>Because of the large number of modifications, we have divided up
 the Version 2.6 notes into the following subtopics.</p>

 <ul>

 <li>New functionality (see @(see note-2-6-new-functionality))</li>

 <li>Changes in proof engine (see @(see note-2-6-proofs))</li>

 <li>Changes in rules and definitions (see @(see note-2-6-rules))</li>

 <li>Guard-related changes (see @(see note-2-6-guards))</li>

 <li>proof-builder changes (see @(see note-2-6-proof-builder))</li>

 <li>System-level changes (see @(see note-2-6-system))</li>

 <li>Other (minor) changes (see @(see note-2-6-other))</li>

 </ul>")

(defxdoc |NOTE-2-6(R)|
  :parents (release-notes)
  :short "ACL2 Version  2.6(r) (November, 2001) Notes"
  :long "<p>Important changes to non-standard version: None since Version
 2.5.</p>

 <p>Please see @(see note-2-6) for changes to Version 2.6 of ACL2.  We hope to
 write more documentation for ACL2(r) in the future.</p>")

(defxdoc note-2-6-guards
  :parents (note-2-6)
  :short "ACL2 Version  2.6 Notes on Guard-related Changes"
  :long "<p>When you @(tsee declare) that a function treats certain formals as
 @(':')@(tsee stobj)@('s'), the @(see guard) of the function is automatically
 extended to include the corresponding stobj-recognizer calls.  For example, if
 a definition includes @('(declare (xargs :stobjs (ST)))') then the guard of
 the function is changed by the addition of the conjunct @('(ST-P ST)').</p>

 <p>One impact of this is that if you use the built-in ACL2 @(tsee state) as a
 formal parameter of a function, @('(STATE-P STATE)') is added to the guard.
 This may introduce a guard where there was none in previous versions of the
 system.  In older versions, therefore, no attempt would be made to @(tsee
 verify-guards), while in the new version, we would attempt guard verification.
 You may wish to add @('(declare (xargs :verify-guards nil))') to such
 definitions.</p>

 <p>A related change affects users who do not use stobjs or @('state').  In
 previous versions of the system &mdash; as now &mdash; a @('type') declaration
 extended the guard you provided explicitly.  Thus, if you wrote @('(declare
 (type integer n))') then @('(INTEGERP n)') was added to your guard.  This is
 still the case and @(':stobjs') recognizers are similarly added.  But in older
 versions of the system we ``added'' the conjuncts without checking whether
 they were already present in the guard you provided.  This sometimes produced
 such guards as @('(and (integerp n) (integerp n))') where the first was
 produced by your @('type') declaration and the second was your @(':guard').
 We now eliminate redundant conjuncts; this may rearrange the order of the
 conjuncts.</p>

 <p>The guard conjectures for functions using @('stobj')s have been simplified
 somewhat by taking advantage of the syntactic restrictions checked for
 single-threaded objects.</p>

 <p>The following functions have been modified so that character and string
 arguments are restricted to standard characters.  (See @(see standard-char-p)
 and see @(see standard-char-listp).)</p>

 <blockquote>

 <p>@(tsee upper-case-p) @(tsee lower-case-p) @(tsee char-upcase) @(tsee
 char-downcase) @('string-downcase1') @(tsee string-downcase)
 @('string-upcase1') @(tsee string-upcase) @(tsee char-equal)
 @('string-equal1') @(tsee string-equal)</p>

 </blockquote>

 <p>Also, function @(tsee standard-string-alistp) replaces function
 @('string-alistp'), with concomitant changes in the guard to @(tsee
 assoc-string-equal), and in variable @('*acl2-exports*').  Also, lemma
 @('standard-string-alistp-forward-to-alistp') replaces lemma
 @('string-alistp-forward-to-alistp').  There is a new lemma
 @('standard-char-p-nth'), which has also been added to
 @('*acl2-exports*').</p>

 <p>The guard had been inadvertently omitted from the definition of the
 function @(tsee substitute) (and its subroutine @('substitute-ac')).  This
 omission has been corrected; also, the guard is slightly stronger than the
 documentation had claimed (and that has been corrected).</p>")

(defxdoc note-2-6-new-functionality
  :parents (note-2-6)
  :short "ACL2 Version  2.6 Notes on New Functionality"
  :long "<p>A fundamental change is the provision of the ``nu-rewriter'' for
 simplifying expressions composed of @('NTH'), @('UPDATE-NTH'), and
 @('UPDATE-NTH-ARRAY') applications and @('LET') expressions and other calls of
 non-recursive functions or @('LAMBDA') expressions involving those symbols.
 The nu-rewriter applies the obvious rewrite rule for @('(NTH i (UPDATE-NTH j v
 s))') and the analogous rule for @('UPDATE-NTH-ARRAY').  See nu-rewriter.  The
 nu-rewriter can be enabled with @('set-nu-rewriter-mode').</p>

 <p>A new flag has been added to the @('xargs') of @(tsee defun) permitting the
 declaration that the function is @('non-executable').  The usage is
 @('(declare (xargs :non-executable t))') and the effect is that the function
 has no executable counterpart.  On the positive side: the function is
 permitted to use single-threaded object names and functions arbitrarily, as in
 theorems rather than as in executable definitions.  Such functions are not
 permitted to declare any names @(':')@(tsee stobj)@('s') but accessors, etc.,
 may be used, just as in theorems.</p>

 <p>A new flag has been added to permit the system to abbreviate output by
 introducing @('LET*') notation identifying common subterms.  The formula being
 proved is not affected; this flag changes its displayed form only.  See @(see
 set-let*-abstractionp).</p>

 <p>A ``raw mode'' has been added, primarily for faster loading of
 applications.  see @(see set-raw-mode).</p>

 <p>Functions @(tsee alphorder) and @(tsee lexorder) have been put in
 @(':')@(tsee logic) mode.  @('Lexorder') is now a total order ordering of the
 ACL2 universe, and theorems are included to that effect.  Thanks to Pete
 Manolios for suggesting the idea and providing events to use, and to Rob
 Sumners for assistance with some modifications.  See also the new book
 @('books/misc/total-order') for an irreflexive total order.</p>

 <p>The ACL2 user can now make system calls to the host operating system.  See
 @(see sys-call) and see @(see sys-call-status).  Thanks to Rob Sumners for
 working out this idea with Pete Manolios and Robert Krug, who we also thank,
 and for working out the implementation with us.</p>

 <p>It is no longer required to use absolute @(see pathname)s in @(tsee
 include-book) forms that have been executed before a @(tsee certify-book).
 Any relative pathname strings in such contexts will be expanded into absolute
 pathnames before they are saved in the @(tsee portcullis) of the @(tsee
 certificate) of the book being certified.</p>

 <p>ACL2 can now be built on top of Allegro Common Lisp 6.0, and also on
 Windows platforms on top of Allegro Common Lisp and GCL.  Thanks to Pete
 Manolios and Vinay K. Siddhavanahalli for their help with Windows.</p>

 <p>Rob Sumners has designed and provided an initial implementation for two
 improvements to @(tsee defstobj) (also see @(see stobj)).  First, array fields
 can now be resized.  Resize and length functions are provided for array
 fields, which can be used to resize stobj array fields dynamically.  The
 recognizers for array fields have been simplified to accommodate this change,
 so that they only check that each element of the array field has the specified
 type.  Second, performance has been improved for stobjs with a large number of
 fields, by changing their Common Lisp implementation to store the fields in a
 simple vector instead of a list.</p>

 <p>Now @(see stobj)s may be bound locally; see @(see with-local-stobj).
 Thanks to Rob Sumners, who encouraged us to implement this capability, was an
 early user of it, and participated usefully in discussions on its design.</p>

 <p>New functions @(tsee fms!), @(tsee fmt!), and @(tsee fmt1!) are the same as
 their respective functions without the ``@('!'),'' except that the ``@('!')''
 functions are guaranteed to print forms that can be read back in (at a slight
 readability cost).</p>

 <p>We added @(tsee extended-metafunctions), metafunctions which allow @(tsee
 state) and context sensitive rewriting to some extent.  We thank Robert Krug
 for pushing for and on this idea.</p>

 <p>The documentation has been improved.  In particular, a new documentation
 topic provides a gentle introduction to ACL2 @(tsee arrays) &mdash; see @(see
 arrays-example) &mdash; and additional documentation has been provided for
 getting started with proof trees in emacs &mdash; see @(see proof-tree).</p>

 <p>New Makefile targets @('fasl') and @('o') have been added to the
 @('books/') directory of the distribution.  For example, you might first
 certify books using an ACL2 built on top of GCL (which creates compiled files
 with suffix @('o')).  Then, when standing in the @('books/') directory, you
 might execute the command</p>

 <blockquote>

 <p>make fasl ACL2=my-allegro-acl2</p>

 </blockquote>

 <p>which will create compiled (@('.fasl')) files for Allegro Common Lisp,
 assuming that @('my-allegro-acl2') starts up an ACL2 built on that Common
 Lisp.</p>

 <p>The macro @(tsee let*) now allows variables to be declared ignored.  See
 @(see let*) and see @(see let).</p>

 <p>The user may now control backchaining.  This feature was designed and
 primarily implemented by Robert Krug (though the authors of ACL2 are
 responsible for any errors); thanks, Robert!  See @(see backchain-limit).</p>

 <p>It is now possible to ``slow down'' the rate at which case splits are
 generated by the simplifier.  See @(see set-case-split-limitations).</p>

 <p>Accesses to @(see stobj)s using @(tsee nth) or @(tsee update-nth) are now
 displayed using symbolic constants instead of numeric indices.  For example,
 given the event</p>

 @({
  (defstobj foo a b :renaming ((b c)))
 })

 <p>then the term @('(nth 0 foo)') will be displayed (for example, during
 proofs) as @('(nth *a* foo)') while @('(nth 1 foo)') will be displayed as
 @('(nth *c* foo)').  The @(tsee defstobj) event now correspondingly introduces
 a @(tsee defconst) event for each field accessor function, introducing a
 constant whose name is obtained from the accessor's name by prefixing and
 suffixing a ``@('*'),'' as in the example above: accessor @('a') generates
 @('(defconst *a* 0)') and accessor @('c') generates @('(defconst *c* 1)'). See
 @(see nth-aliases-table) for how to extend this feature for alternate names of
 @(see stobj)s.</p>

 <p>Computed hints have been improved.  It is now possible to detect within a
 computed hint whether the goal clause is stable under simplification; it is
 also possible for a computed hint to change the list of available hints.  See
 @(see computed-hints).</p>

 <p>It is now possible to provide ``default hints'' that are appended to the
 hints explicitly provided.  See @(see set-default-hints).</p>

 <p>Using computed hints (see @(see computed-hints)) and default hints (see
 @(see set-default-hints)) it is possible to implement a book that supports
 ``priority phased simplification.''  Using this book you can assign priorities
 to your rules and cause the theorem prover to simplify each goal maximally
 under all the rules of one priority before enabling rules of the next
 priority.  See @('books/misc/priorities.lisp').</p>

 <p>The macro @(tsee defabbrev) has been improved to allow @(tsee declare)
 forms and documentation strings and to do more error-checking.  Thanks to Rob
 Sumners for designing this enhancement and providing the first implementation.
 See @(see defabbrev).</p>

 <p>Further changes were made to support CMU Lisp.  Wolfhard Buss helped with
 these changes.</p>

 <p>A new table was added that is used when printing proof output, so that
 nests of right-associated calls of a binary function are replaced by
 corresponding macro calls, as has been the case for @(tsee binary-+) and
 @(tsee +), @(tsee binary-append) and @(tsee append), and so on.  See @(see
 add-binop).</p>

 <p>Operators @(tsee logand), @(tsee logior), @(tsee logxor), and @(tsee
 logeqv) are now macros (formerly, they were functions) that call corresponding
 binary functions (e.g., @('binary-logand')) defined in source file
 @('\"axioms.lisp\"').  Thanks to Rob Sumners for this enhancement.  Proof
 output will however continue to show calls of @(tsee logand), @(tsee logior),
 @(tsee logxor), and @(tsee logeqv).</p>

 <p>Function @('(')@(tsee allocate-fixnum-range)@(' fixnum-lo fixnum-hi)') sets
 aside more \"permanent\" fixnums in GCL.</p>

 <p>ACL2 now runs under @('CLISP').  Thanks to Wolfhard Buss and Sam Steingold
 for their assistance with the port.</p>

 <p>Michael ``Bogo'' Bogomolny has created a search engine, accessible from the
 ACL2 home page.  For that purpose he modified the HTML translator to create
 one file per topic (a good idea in any case).  Thanks, Bogo!</p>

 <p>An emacs file of potential (but optional) use for ACL2 users may be found
 in @('emacs/emacs-acl2.el').  In particular, this file supports the use of
 proof trees (see @(see proof-tree)).</p>

 <p>Some @(see books) have been added or modified.  In particular, Robert Krug
 has contributed @('books/arithmetic-2/'), which provides an alternative to the
 existing collection of books about arithmetic, @('books/arithmetic/').  For a
 discussion of the distributed books see the link to @('README.html') in the
 installation instructions.</p>")

(defxdoc note-2-6-other
  :parents (note-2-6)
  :short "ACL2 Version  2.6 Notes on Other (Minor) Changes"
  :long "<p>Warning strings are now case-insensitive.  See @(see
 set-inhibit-warnings).</p>

 <p>ACL2 causes a warning when an @(see in-theory) hint or event causes a 0-ary
 function's definition to be disabled but its @(':')@(tsee
 executable-counterpart) to be enabled.</p>

 <p>A minor modification has been made to @(tsee defstobj) that can have a
 positive impact on performance in Allegro Common Lisp.  (For Lisp hackers: the
 stobj name was formerly declared special, and that was disabling Allegro's
 tail-merging routing for compilation of some recursive functions using
 stobjs.)  The downside is that stobj names can no longer be evaluated in raw
 Lisp.  However, raw Lisp is not the right place to be evaluating ACL2 forms
 anyhow; see @(see set-raw-mode).  We thank Rob Sumners for bringing this issue
 to our attention.</p>

 <p>Before Version 2.6, there has been the following problem with @(tsee
 defstub) and @(tsee encapsulate) in the case that the current package is not
 the ACL2 package.  If a @(see signature) was specified using the symbol
 @('=>'), then that symbol had have been imported into the current package from
 the ACL2 package when the current package was defined.  There are no longer
 any package restrictions on the use of @('=>').  Thanks to John Cowles for
 bringing this problem to our attention.</p>

 <p>Bugs in @(tsee defun-sk) have been fixed.  @('Defun-sk') forms introducing
 functions of no arguments were failing to be admitted, for example:
 @('(defun-sk always-p1 () (forall (x) (p1 x)))').  Thanks to John Cowles for
 bringing this problem to our attention.  Also, @('defun-sk') failed on an
 example in the documentation (see @(see tutorial4-defun-sk-example)), as
 pointed out by Matyas Sustik; this bug has been fixed as well.</p>

 <p>The trace mechanism has been fixed to handle @(see stobj)s, and to avoid
 the printing of so-called <i>enabled structures</i>.</p>

 <p>The @(tsee brr) command @(':type-alist') now produces more readable
 output.</p>

 <p>An @(tsee include-book) of an uncertified book no longer loads an
 associated compiled file.</p>

 <p>We added a few checks to make sure that the underlying lisp is suitable,
 for example checking that the reader is case-insensitive and reads in symbols
 with upper-case names where appropriate.</p>

 <p>We now warn when forcing (see @(see force)) or immediate force mode (see
 @(see immediate-force-modep)) change state between enabled and disabled.  Also
 see @(see enable-immediate-force-modep) and see @(see
 disable-immediate-force-modep) for information about these new macros, which
 may be used to control immediate force mode.</p>

 <p>We have eliminated the use of a low-level raw Lisp constant,
 @('*most-recent-multiplicity*').  Our test suite saw a speed-up of
 approximately 2% as a result for an ACL2 image built on GCL (but no
 significant speed-up for an ACL2 image built on Allegro Common Lisp).  We
 thank Rob Sumners for suggesting this improvement.</p>

 <p>Fixnum declarations are now realized as @('(signed-byte 29)') instead of
 @('(signed-byte 27)').  We check that the underlying Common Lisp recognizes
 objects of type @('(signed-byte 29)') as fixnums, with the exception of CLISP,
 which is said to have an efficient bignum implementation.</p>

 <p>A new documentation topic @(see functional-instantiation-example)
 illustrates functional instantiation.</p>

 <p>A bug has been fixed in the monitoring of runes (see @(see monitor)).
 Thanks to Dave Greve for sending an example that clearly showed the
 problem.</p>

 <p>A warning is now issued when it is detected that a @(':')@(tsee
 type-prescription) rule may not be as strong as it appears because it is not
 sufficient to prove itself by type reasoning.</p>

 <p>An error is caused for rules of class @(':')@(tsee meta) when the function
 symbol @('IF') is among the @(':trigger-fns').  (@('IF') was ignored anyhow;
 the point of this change is to avoid misleading the user.)</p>

 <p>A minor bug has been fixed in @(':')@(tsee pr), evident for example if this
 command was applied to @('IF').</p>

 <p>A minor hole in @(':')@(tsee set-bogus-mutual-recursion-ok) did not permit
 the acceptance of @(tsee mutual-recursion) forms that include constant
 function definitions.  This has been fixed.  Thanks to Eric Smith for coming
 up with a simple example illustrating the problem.</p>

 <p>The temporary files \"TMP.lisp\" and \"TMP1.lisp\" written out by
 @(':')@(tsee comp) are now written to the connected book directory (see @(see
 cbd)).</p>

 <p>Previously, the Allegro compiler was not eliminating tail recursion for
 executable counterparts of functions, because of the way one of its flags had
 been set.  As a result, calls of functions whose guards had not been verified
 could run out of stack space when this was not necessary.  This situation has
 been fixed.</p>

 <p>Executable counterparts could have slow array accesses.  This has been
 fixed (specifically, constants are no longer replaced with their values in the
 definitions of executable counterparts).</p>

 <p>Various improvements have been made to the documentation.  Thanks in
 particular to Eric Smith for pointing out a numbers of places where fixes were
 in order.</p>

 <p>File \"mcl-acl2-startup.lisp\" has been updated, thanks to feedback from
 Philippe Georgelin.</p>

 <p>Inefficiencies in GCL fixnum computations were remedied for macros @('+f')
 and @('*f').  Thanks to Rob Sumners for pointing out this issue.</p>")

(defxdoc note-2-6-proof-builder
  :parents (note-2-6)
  :short "ACL2 Version  2.6 Notes on proof-builder Changes"
  :long "<p>The proof-builder command @('='), when used with no arguments, now
 reports which hypothesis is being used.</p>

 <p>The output from @(see proof-builder) command @('type-alist') has been
 improved.</p>

 <p>A slight change has been made to the @(see proof-builder) for commands
 @('promote'), @('casesplit'), @('equiv'), and @('='), so that terms of the
 form @('(if x nil y)') are recognized as conjunctions, @('(and (not x) y)').
 Thanks to Pete Manolios for suggesting that we consider such a change.</p>

 <p>There is a new @(see proof-builder) command @('print-all-concs') that
 prints all the conclusions of the unproved goals.</p>

 <p>A new @(tsee proof-builder) command, @('runes'), has been added.  It
 reports the @(see rune)s that have participated in the interactive proof up to
 the current point.</p>")

(defxdoc note-2-6-proofs
  :parents (note-2-6)
  :short "ACL2 Version  2.6 Notes on Changes in Proof Engine"
  :long "<p>Certain optimizations are performed when converting terms to
 clausal form.  For example, @('(< 0 1)') is known to be @('t'), @('(HARD-ERROR
 ctx str alist)') is known to be @('nil'), and @('(INTEGERP n)') is known to
 imply @('(RATIONALP n)').</p>

 <p>In earlier versions of ACL2, the conversion of a term to clausal form
 expanded @('LAMBDA') applications.  That may no longer occur.  Some proofs may
 slow down (or fail) because your @('LAMBDA')-expressions are not expanded away
 when you ``expected'' them to be.</p>

 <p>Robert Krug found a soundness bug in our linear arithmetic package.  The
 bug was caused by the derivation of an equation from two inequalities without
 taking adequate precautions to ensure that both sides of the inequalities were
 numeric.  Robert also kindly provided a fix which we adopted.  Thanks
 Robert!</p>

 <p>We fixed a bug that could prevent the application of a metatheorem.</p>

 <p>A bug has been fixed that had caused bogus forcing rounds (see @(see
 forcing-round)).  The bug could occur when the hypothesis of a rule was forced
 (see @(see force)) before the prover decided to start over and prove the
 original goal by induction.  Thanks to Rob Sumners for drawing our attention
 to this problem.</p>

 <p>Some low-level fixes have been made that prevent certain infinite loops,
 based on reports by users.  We thank Yunja Choi, Matt Wilding, and Pete
 Manolios for reporting such problems.</p>

 <p>An obscure potential soundness hole has been fixed by redoing the way
 evaluation takes place in the ACL2 loop and during theorem proving.  We expect
 that users will see no difference based on this change.  (Those interested in
 the details can see the long comment ``Essay on Evaluation in ACL2'' in source
 file interface-raw.lisp.)</p>

 <p>A small change was made in computation for a heuristic that controls
 backchaining.  This will speed up proofs dramatically in a very few cases but
 should have a very small impact in general.</p>

 <p>The simplifier has been modified to avoid eliminating hypotheses of goals
 that can be established by contextual (specifically, type-set) reasoning
 alone.  We believe that this change will generally strengthen ACL2's reasoning
 engine, although on rare occasions a lemma that formerly was provable may
 require user assistance.  Thanks to Robert Krug for suggesting this change and
 providing its implementation.</p>

 <p>Case splits are now limited, by default.  This may allow some proof
 attempts to provide output where previously the prover would appear to ``go
 out to lunch.''  For a more complete discussion, including instructions for
 how users can control case splitting, see @(see
 set-case-split-limitations).</p>

 <p>A bug has been fixed in the handling of @(':')@(tsee type-prescription)
 rules by the @(see bdd) package.  Thanks to Rob Sumners for discovering this
 bug and supplying a helpful example.</p>

 <p>ACL2 may now use the built-in induction scheme for a function symbol even
 if that function symbol is disabled.  Formerly, if a function symbol was
 disabled then its induction scheme was only considered if an explicit
 induction hint was supplied, other than @(':induct t').</p>

 <p>We eliminated the rule-class @('linear-alias').  This rule class was seldom
 used and complicated the linear arithmetic decision procedure in ways that
 made it difficult to extend to handle some non-linear special cases.  The only
 use of the rule-class that we know of was in our own @('nqthm') books, which
 were an attempt to provide an embedding of the Nqthm logic and theorem prover
 into ACL2.  But that facility was also practically never used, as far as we
 know.  So both @('linear-alias') rules and the @('nqthm') books have been
 eliminated.</p>

 <p>In earlier versions of ACL2, when the @('IF')-form of @('(AND p q)') was
 assumed true &mdash; as when rewriting the @('alpha') expression in
 @('(IF (AND p q) alpha beta)') &mdash; the assumption mechanism did not deduce
 that @('p') and @('q') are true, only that their conjunction, in its
 @('IF')-form, is true.  This has long been known as a deficiency in both ACL2
 and the earlier Nqthm but it was tedious to do better when one considered the
 full range of @('IF')-forms one might encounter in the test of another
 @('IF').  Rather than code all the cases, we just waited until clausification
 got rid of them.  Robert Krug developed a pretty nice treatment of the general
 case and we added it in this version.  This also involved a surprising number
 of changes elsewhere in the system because the improved handling of
 assumptions caused the theorem prover often to ``erase'' hypotheses provided
 by @(':use') hints because it could simplify them to @('t').  Thank you
 Robert!</p>

 <p>In response to a suggestion from Robert Krug, we added @('mfc-ap') so that
 extended metafunctions can take advantage of linear arithmetic.  See @(see
 extended-metafunctions).</p>

 <p>There is less delay in printing goals.  In previous versions, a goal was
 not printed until its subgoals were created (or the goal was proved).  Now,
 the goal is printed essentially as soon as it is created.</p>

 <p>A small technical change has been made in the function @(tsee term-order),
 to give priority on the function symbol count over the weighting of constants.
 So for example, while previously the term @('(f)') preceded the constant 2,
 that is no longer the case.  If this change is noticed at all, it will
 probably be noticed in how so-called <i>permutative</i> rewrite rules are
 applied; see @(see loop-stopper).  Thanks to Robert Krug for suggesting this
 improvement and providing part of the implementation.</p>")

(defxdoc note-2-6-rules
  :parents (note-2-6)
  :short "ACL2 Version  2.6 Notes on Changes in Rules and Constants"
  :long "<p>The following symbols have been added to the list constant
 @('*common-lisp-specials-and-constants*'): @('REPLACE'), @('FILL'),
 @('CHARACTER'), @('='), @('BREAK'), and @('PRIN1').  This was done in support
 of ports to Allegro 6.0 and Windows platforms (see @(see
 note-2-6-new-functionality)).</p>

 <p>The list of symbols in @('*acl2-exports*') has been modified, for example
 to include @('show-accumulated-persistence') and the legal arguments to @(tsee
 set-inhibit-output-lst).</p>

 <p>Functions @(tsee zp) and @(tsee zip) are now handled slightly differently.
 They are are now disabled, but each comes with a @(':')@(tsee rewrite) rule
 that allows their expansion on non-variable terms, and also with a
 @(':')@(tsee compound-recognizer) rule that avoids the need for opening up
 these functions when applied to variables.  The resulting behavior should be
 very similar to the behavior of previous versions, except that case splits
 will be avoided when these functions are applied to variables.</p>

 <p>Function @(tsee standard-string-alistp) replaces function
 @('string-alistp').  For further discussion, see @(see note-2-6-guards).</p>

 <p>Rules of class @(':')@(tsee rewrite) whose conclusion is a term of the form
 @('(equal lhs rhs)') have always been stored in the expected way: @('lhs')
 rewrites to @('rhs').  This way of storing @(':rewrite') rules has been
 extended to allow @(tsee =), @(tsee eq), or @(tsee eql) in place of @(tsee
 equal).</p>

 <p>Rewrite rule @('nth-update-nth'), in source file @('axioms.lisp'), has been
 strengthened.</p>

 <p>A new rewrite rule @('equal-constant-+') has been added to the book
 @('arithmetic/equalities').  This should generally be a beneficial change, but
 existing proofs involving the arithmetic books could conceivably be
 affected.</p>

 <p>Function @(tsee symbol-package-name) and constant
 @('*main-lisp-package-name*') have undergone small changes.  This change
 should rarely be noticed by users and is discussed elsewhere; see @(see
 note-2-6-system).</p>

 <p>We mention here that proofs involving @(see stobj)s may need to be modified
 because of changes in auxiliary functions generated by @(tsee defstobj).
 (These changes were made in support of a new resizing capability, mentioned
 elsewhere in these release notes; see @(see note-2-6-new-functionality).</p>

 <p>In the distributed book directory @('books/arithmetic/'), the book
 @('rationals-with-axioms-proved.lisp') has been renamed
 @('rationals.lisp').</p>

 <p>(ACL2(r) only) Rewrite rules @('realp-+'), @('realp-*'),
 @('realp-unary--'), and @('realp-unary-/') have been added in analogy to
 existing rules @('rationalp-+'), @('rationalp-*'), @('rationalp-unary--'), and
 @('rationalp-unary-/').  Thanks to Jun Sawada for suggesting this change.</p>

 <p>The definition of @(tsee aref1) has been modified slightly.  Previously, if
 @('*my-a*') were an array then @('(aref1 'some-name *my-a* :header)') would
 evaluate to the @('cdr') of the @(tsee header) of @('*my-a*') rather than to
 its @(tsee default).  See @(see arrays).</p>

 <p>Changes have been made in the @('ihs') books, based on suggestions from Jun
 Sawada, that support its use with ACL2(r) (see @(see real)).  The primary
 change is to replace calls of @(tsee rationalp) with calls of @(tsee
 real/rationalp), which should have no effect on users of standard ACL2.</p>")

(defxdoc note-2-6-system
  :parents (note-2-6)
  :short "ACL2 Version  2.6 Notes on System-level Changes"
  :long "<p>We modified the tracking of @(tsee skip-proofs) events and the use
 of @(tsee state) global @('ld-skip-proofsp') in order to avoid some soundness
 issues.  For example, @(tsee skip-proofs) events buried in locally-included
 books are now tracked.  The ``Essay on Skip-proofs'' in source file
 @('axioms.lisp') gives several examples of dicey behavior that is no longer
 supported.</p>

 <p>We fixed a problem with some of the makefiles, so that recursive
 invocations of `make' now use the version of `make' specified on the command
 line.</p>

 <p>Files were fixed to help non-Unix/Linux users with book certification.
 Thanks to John Cowles for finding some problems and suggesting fixes to
 @('books/certify-numbers.lisp'), @('books/arithmetic/certify.lsp'), and
 @('books/cowles/certify.lsp').  We thank Scott Burson for noticing and fixing
 some other such problems.  Moreover, a bdd test was being ignored entirely in
 Version 2.5; this problem has been fixed as well.</p>

 <p>A minor change in system function save-acl2-in-allegro will allow this
 function to continue to work in Allegro CL versions starting (someday) with
 10.0.  Thanks to Art Flatau for suggesting such a fix.</p>

 <p>The @('books/case-studies/') directory has been removed.  These books are
 in support of the first (1998) ACL2 workshop, and are accessible via the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/'>ACL2 home page</a>.  Also,
 the @('books/cli-misc') directory has been renamed @('books/misc'), and the
 @('books/nqthm') directory has been removed.</p>

 <p>The notion of ACL2 version has been slightly modified to catch unsoundness
 due to implementation dependencies.  See @(see version).  Another change to
 eliminate such unsoundness is that built-in symbols now have a @(tsee
 symbol-package-name) of @('\"COMMON-LISP\"'); formerly, this string was
 @('\"LISP\"') for ACL2 images built on GCL.  See @(see symbol-package-name).
 At a low level, the (undocumented) constant @('*main-lisp-package-name*') is
 now @('\"COMMON-LISP\"'); before, it was @('\"LISP\"') for GCL.</p>")

(defxdoc note-2-7
  :parents (release-notes)
  :short "ACL2 Version  2.7 (November, 2002) Notes"
  :long "<p>The Version_2.7 notes are divided into the subtopics below.  Here
 we give only a brief summary of a few of the changes that seem most likely to
 impact existing proofs.  Not included in this brief summary, but included in
 the subtopics, are descriptions of improvements (including bug fixes and new
 functionality) that should not get in the way of existing proof efforts.</p>

 <p>In particular, please see @(see note-2-7-new-functionality) for discussion
 of a number of new features that you may find useful.</p>

 <p>Acknowledgements and elaboration, as well as other changes, can be found in
 the subtopics listed below.</p>

 <h5>Bug fixes (see @(see note-2-7-bug-fixes))</h5>

 <ul>

 <li>Three soundness bugs were fixed.  These bugs were probably rarely hit, so
 users may well not notice these changes.</li>

 <li>@(tsee Certify-book) now requires @(':skip-proofs-ok t') (respectively,
 @(':defaxioms-okp t')) if there are @(tsee skip-proofs) (respectively, @(tsee
 defaxiom)) events in the book or any included sub-books.</li>

 <li>When @(':by') hints refer to a definition, they now use the original body
 of that definition rather than the simplified (``normalized'') body.</li>

 <li>When @(tsee ld) is applied to a stringp file name, it now temporarily
 sets the connected book directory (see @(see cbd)) to the directory of that
 file while evaluating forms in that file.</li>

 </ul>

 <h5>New functionality (see @(see note-2-7-new-functionality))</h5>

 <ul>

 <li>ACL2 now works harder to apply @(':')@(tsee rewrite) and @(':')@(tsee
 linear) rules with free variables in the hypotheses.  See @(see
 note-2-7-new-functionality), in particular its first two paragraphs, for
 details.  @(see Forward-chaining) also does more with free
 variables.</li>

 </ul>

 <h5>Changes in proof engine (see @(see note-2-7-proofs))</h5>

 <ul>

 <li>Some prover heuristics have changed slightly.  Among other consequences,
 this can cause subgoal @(see hints) to change.  For example, suppose that the
 Version_2.6 proof of a particular theorem generated \"Subgoal 2\" and
 \"Subgoal 1\" while Version_2.7 only generates the second of these.  Then a
 subgoal hint attached to \"Subgoal 1\" in Version_2.6 would have to be
 attached to \"Goal'\" in Version_2.7.  (See @(see goal-spec).)  The full topic
 has details (see @(see note-2-7-proofs)).</li>

 </ul>

 <h5>Changes in rules and definitions (see @(see note-2-7-rules))</h5>

 <ul>

 <li>The package name of a generated variable has changed for @(tsee
 defcong).</li>

 </ul>

 <h5>Guard-related changes (see @(see note-2-7-guards))</h5>

 <ul>

 <li>@(tsee Guard) verification formerly succeeded in a few cases where it
 should have failed.</li>

 <li>Guards generated from type declarations now use functions
 @('signed-byte-p') and @('unsigned-byte-p'), now defined in source file
 @('axioms.lisp') and formerly defined rather similarly under
 @('books/ihs/').</li>

 </ul>

 <h5>proof-builder changes (see @(see note-2-7-proof-builder))</h5>

 <ul>

 <li>See the above doc topic.</li>

 </ul>

 <h5>System-level changes (see @(see note-2-7-system))</h5>

 <ul>

 <li>See the above doc topic.</li>

 </ul>

 <h5>Other changes (see @(see note-2-7-other))</h5>

 <ul>

 <li>A new @(tsee table), @(tsee invisible-fns-table), takes the place of the
 handling of invisible functions in the @(tsee acl2-defaults-table),</li>

 <li>The @(tsee theory-invariant) event has been modified so that the default
 action is an error rather than a warning.</li>

 <li>Proof output that reports destructor elimination no longer uses the word
 ``generalizing''.</li>

 </ul>

 <p>Again, please proceed to the subtopics for more thorough release
 notes.</p>")

(defxdoc |NOTE-2-7(R)|
  :parents (release-notes)
  :short "ACL2 Version  2.7(r) (November, 2002) Notes"
  :long "<p>In source file @('axioms.lisp'), in order for proofs to succeed,
 (@('make proofs')), the definitions of @(tsee acl2-count) and
 @('explode-atom') have been modified slightly, and lemma
 @('standard-numberp-one') [modified after Version_3.4 to become
 @('standardp-one')] has been given @(':rule-classes nil').</p>

 <p>All @(tsee skip-proofs) forms have been eliminated from the nonstd books,
 thanks to Ruben Gamboa.</p>

 <p>The directory @('books/sqrt/'), which was intended for ACL2(r), has been
 moved to @('books/nonstd/sqrt/') and added as appropriate to
 @('books/nonstd/Makefile').</p>

 <p>Please see @(see note-2-7) for changes to Version_2.7 of ACL2.</p>")

(defxdoc note-2-7-bug-fixes
  :parents (note-2-7)
  :short "ACL2 Version  2.7 Notes on Bug Fixes"
  :long "<p>Francisco J. Martin-Mateos emailed us a soundness bug (!) in our
 handling of functional instantiation (for example see @(see
 functional-instantiation-example)).  We are grateful for that email, which
 clearly illustrated the problem.  It is included just below the definition of
 @('push-clause') in ACL2 source file @('prove.lisp'), where we have fixed the
 bug.  This bug was fixed in a re-release of Version 2.6 in February, 2002.</p>

 <p>Rob Sumners emailed us a soundness bug (!) in function @('commutative-p1'),
 which is used by the ACL2 @(see bdd) package.  We are grateful for his help;
 his email gave a proof of nil and also pointed to the problem function.  This
 bug was fixed in a re-release of Version 2.6 in February, 2002.</p>

 <p>We discovered and fixed a soundness bug illustrated by the book below,
 which was certifiable in Version 2.6 and ends in a proof of @('nil').  The
 event @('(verify-guards foo)') should have been rejected, because @('foo')
 calls a function whose guards have not been verified, namely, @('bar').
 However, ACL2 did not notice the call of function @('bar') in the body of
 @('foo') because it was looking in the simplified (normalized) body of
 @('foo') rather than in the original body of @('foo').  During processing of
 the book below, the logical definition of @('zp') is used before
 @('(verify-guards foo)'), and @('(zp -3)') reduces to @('t') in the logic.
 After @('(verify-guards foo)'), ACL2 simplifies @('(foo -3)') by going into
 raw Lisp, where @('(zp -3)') is evaluated and reduces to @('nil').</p>

 @({
    (in-package \"ACL2\")
    (defun bar (x)
      (zp x))
    (defthm zp-false-on-negatives
      (implies (< x 0)
               (bar x))
      :rule-classes :type-prescription)
    (defun foo (x)
      (declare (xargs :guard (rationalp x)
                      :verify-guards nil))
      (if (< x 0)
          (if (bar x) 0 1) ; simplified body reduces this line to 0
        17))
    (defthm foo-of-minus-3-is-0
      (equal (foo -3) 0)
      :rule-classes nil)
    (verify-guards foo)
    (defthm foo-of-minus-3-is-1
      (equal (foo -3) 1)
      :rule-classes nil)
    (defthm bug
      nil
      :rule-classes nil
      :hints ((\"Goal\" :use (foo-of-minus-3-is-0 foo-of-minus-3-is-1))))
 })

 <p>The above bug exploited the fact that @(tsee zp) has a different definition
 in raw Lisp than in the logic for arguments that violate its guard).  The
 following example caused a hard error in raw Lisp, though not a soundness
 error.</p>

 @({
    (in-package \"ACL2\")
    (defun bar (x)
      (cons (car x) (car x)))
    (defun foo (x)
      (declare (xargs :guard t
                      :verify-guards nil))
      (if (bar x) x nil))
    (verify-guards foo)
    (defthm bug
      (equal (foo 3) t)
      :rule-classes nil)
 })

 <p>We have made a minor change to the notion of the <i>formula</i> of a
 function symbol, related to the change above, which however is unlikely to be
 noticeable.</p>

 <p>In order to make it harder to hit problems like the guard problem above, we
 have slightly modified the raw Lisp definition of @(tsee zp).</p>

 <p>A @(tsee break-rewrite) command, @(':ancestors'), was broken, but has been
 fixed.  Thanks to Eric Smith for bringing the problem to our attention, and to
 Robert Krug for supplying the final part of the fix.</p>

 <p>Some @(see proof-builder) commands caused errors when all goals have
 already been proved.  This has been fixed.  Thanks to Matt Wilding for
 reporting this bug.</p>

 <p>Fixed a bug in @(':')@(tsee comp).  When compiling uncompiled functions
 with very large definitions, ACL2 was inserted a backslash (@('\\')) character
 into generated files.</p>

 <p>Fixed the @(':type-alist') @(':')@(tsee brr) command (see @(see
 brr-commands)), whose output was difficult to read when typed after an
 @(':eval')..</p>

 <p>Fixed some clumsy handling of errors when including an uncertified book,
 for example, with the error message when including an uncertified book with a
 bad @(tsee deftheory) event.  Thanks to Eric Smith for pointing out this
 problem.</p>

 <p>Two modifications to @(tsee certify-book) now cause it to reflect natural
 expectations with respect to soundness.  First, it now has default values of
 @('nil') instead of @('t') for keyword arguments @(':skip-proofs-okp') and
 @(':defaxioms-okp').  Thanks to Robert Krug for suggesting this change and the
 ACL2 seminar at the University of Texas for discussing it.  Second, when
 @(':skip-proofs-okp') (respectively, @(':defaxioms-okp')) is @('nil'), either
 explicitly or by default, then @(tsee skip-proofs) commands (respectively,
 @(tsee defaxiom) events) are disallowed inside any included books, regardless
 of the keyword parameters passed to @(tsee include-book).  This had not been
 the case for previous versions of ACL2, regardless of the values of
 @(':skip-proofs-okp') or @(':defaxioms-okp') passed to @(tsee
 include-book).</p>

 <p>Improved warnings and errors for @(tsee certify-book) and @(tsee
 include-book) to mention the @(see portcullis) as a possible source of @(tsee
 skip-proofs) and @(tsee defaxiom)s.</p>

 <p>ACL2 formerly caused an error when @(see hints) in a @(':')@(tsee
 corollary) were not well-formed.  This situation could arise as follows when
 certifying a book.  A lemma FOO is proved @(tsee LOCAL)ly to the book (or, is
 present in a sub-book that is included locally).  The @(':corollary') of a
 subsequent theorem, BAR, disables that rule in a hint.  When BAR is proved,
 this is not a problem.  But @(tsee certify-book) makes a second pass after
 processing the events in a book: it essentially does an @(tsee include-book).
 During the @('include-book') pass, FOO is not known (because it was @(tsee
 local)), and therefore ACL2 fails to process the @(tsee disable) of FOO in an
 @(tsee in-theory) hint.  The fix is that during @(tsee include-book), @(see
 hints) are ignored in corollaries just as they have been for the main theorem
 (or definition).</p>

 <p>It was possible for guard verification to succeed where it should have
 failed.  We have fixed the bug (which was in source function (ironically
 named!) @('fcons-term-smart')).  Thanks to Robert Krug for sending us an
 example of bungled guard verification.  It turns out that this bug was also
 present in Version_2.6.</p>

 <p>The @(see proof-builder) command @('=') has been improved.  Formerly, it
 could fail to apply when certain @(tsee implies) terms were in the context.
 Thanks to Pete Manolios for bringing this problem to our attention.</p>

 <p>The command @(tsee add-binop) failed to work.  This has been fixed.  Thanks
 to Rob Sumners for pointing out this problem.  Also see @(see note-2-7-other)
 for a discussion of how this and another @(see table) are no longer part of
 the @(tsee acl2-defaults-table).</p>

 <p>Book certification could cause a segmentation fault in cases where the
 certification world (see @(see certify-book)) has a very large number of
 events.  This has been fixed.</p>

 <p>We now allow empty @(':use') @(see hints) and empty hints, as requested by
 Eric Smith.  Examples:</p>

 @({
  (\"Goal\" :use ())
  (\"Goal\")
 })

 <p>A large @(tsee mutual-recursion) nest could cause a stack overflow when
 executing either @(':pr FN'), @(':pr! FN'), or @(':monitor (:definition FN)
 t'), where @('FN') is in that large mutual recursion nest.  This has been
 fixed (implementation detail: function @('actual-props') has been made
 tail-recursive).  NOTE: If you just want the definition of @('FN'),
 @(':')@(tsee pf)@(' FN') can be much faster than @(':')@(tsee pr)@(' FN') if
 @('FN') is in a large @(tsee mutual-recursion).</p>

 <p>Hard Lisp errors could occur when including uncertified books.  This has
 been fixed; ACL2 now does syntax-checking formerly omitted when including
 uncertified books.</p>

 <p>Previously, the evaluation of @(tsee defstobj) and @(tsee mutual-recursion)
 forms could cause ``undefined'' warnings when the form was compiled.  This has
 been fixed.  Thanks to Eric Smith for bring a @('mutual-recursion') example to
 our attention.</p>

 <p>A bug has been fixed in the syntactic check for valid @(':')@(tsee
 loop-stopper) values.  Formerly, valid @(':loop-stopper') values were
 erroneously restricted to lists of length at most 2 (a minor problem, since
 these lists typically have length 1), and the function symbol(s) need not have
 been defined in the current ACL2 @(see world).  Thanks to Eric Smith for
 sending an example to demonstrate the latter problem.</p>

 <p>Functions definitions that are @(':non-executable') (see @(see xargs)) had
 never been recognized as redundant, but this has been fixed.  Thanks to Vernon
 Austel for pointing out this problem.</p>

 <p>Compilation using @(':')@(tsee comp) now compiles user-defined @(':')@(tsee
 program) mode functions.  Formerly only @(':')@(tsee logic) mode functions
 could be compiled using @(':comp').</p>

 <p>Handling of @(':by') hints has been improved in essentially three ways.
 The primary change is that now, when the current goal exactly matches the
 supplied lemma instance, the subsumption test will always succeeds (see @(see
 hints), in particular the discussion of @(':by')).  Second, certain proof
 failures involving @(':by') @(see hints) were failing silently, with duplicate
 messages ``As indicated by the hint, this goal is subsumed by....''  This
 could happen when the original goal was among the goals generated by applying
 the hint.  This problem has been fixed by no longer considering this proof
 step to be specious (see @(see specious-simplification)).  Third and finally,
 when the @(see lemma-instance) refers to a definition, the original body of
 that definition is used rather than the simplified (``normalized'') body.</p>

 <p>In addition to the above, we now recognize more cases of specious
 simplification (see @(see specious-simplification)).  Thanks to Eric Smith for
 bringing this issue to our attention.</p>

 <p>Fixed building of ACL2 under CLISP so that (1) the appropriate ACL2 startup
 message is printed out when ACL2 starts up, and (2) the lisp process supplied
 to make, e.g., LISP=/usr/bin/clisp, is the one written out to the saved ACL2
 file.  Thanks to Dave Greve and Noah Friedman for suggesting (2).  Also, ACL2
 now works with CLISP 2.30.  We have accommodated a change in CLISP's handling
 of streams and its package-locking mechanism, as well as certain non-standard
 characters that formerly could cause CLISP 2.30 to break, even when those
 characters are in comments.</p>

 <p>Eliminated compiler warnings for CMU Lisp.</p>

 <p>Fixed an incorrect error supplied when book certification proceeded so
 quickly that the file write dates of the book (@('.lisp') file) and the
 corresponding compiled file are equal.  Now that error only occurs if the
 compiled file has a strictly earlier write date, which probably should never
 happen.</p>

 <p>Fixed an infinite loop when executing @('make clean-books') (and hence
 `make' with targets that call @('clean-books'), namely,
 @('certify-books-fresh'), @('regression-fresh'), and
 @('regression-nonstd-fresh')), which could occur when any subdirectories of
 @('books/') are missing &mdash; even @('workshops/'), which is intended to be
 optional.  Thanks to Pete Manolios for pointing out this bug.</p>

 <p>The @(tsee include-book) command now works properly even when filenames, or
 their directories or parent directories (etc.) are links.  Thanks to Matt
 Wilding for pointing out this problem.</p>

 <p>The commands @(':')@(tsee puff) @(':')@(tsee puff*) have been fixed.
 Formerly, there was a bug when @(':puff') or @(':puff*') caused the execution
 of an @(tsee include-book) for an absolute @(see pathname), @('P'), that was
 other than the current connected book directory (see @(see cbd)).  When
 including @('P'), any subsidiary @(tsee include-book) with a relative pathname
 would be erroneously considered relative to the current @(tsee cbd) rather
 than relative to the directory of @('P').  Thanks to Pete Manolios and Matt
 Wilding for pointing out this problem.</p>

 <p>It had been possible in a ``large'' ACL2 image to call @(tsee
 verify-termination) successfully on built-in function @(tsee sys-call), with
 undesirable results.  This hole has been plugged.  Thanks to Rob Sumners for
 pointing out this problem.  The new function @(tsee gc$) must also stay in
 @(':')@(tsee program) mode.</p>

 <p>ACL2 no longer warns when certifying a book based on @(tsee local)
 functions whose @(see guard)s have not yet been verified.  Thanks to Pete
 Manolios for pointing out this issue.</p>

 <p>An occasional ``slow array warning'' had been possible during proofs.  The
 following sequence shows how to evoke that warning in previous versions.</p>

 @({
  (in-theory (disable binary-append))
  (in-theory (enable binary-append))
  (in-theory (disable binary-append))
  (ubt 2)
  (thm (equal (car (cons x y)) x))
 })

 <p>(See @(see note-2-7-other) for a discussion of a change to @(tsee
 compress1) in support of this fix; however, users should not need to read that
 discussion.)</p>

 <p>The raw Lisp code for @(tsee defchoose) had a small bug, which was only
 evidenced in CLISP implementations as far as we know.  It has been fixed.</p>

 <p>When @(tsee ld) is applied to a stringp file name, it now temporarily sets
 the connected book directory (see @(see cbd)) to the directory of that file
 while evaluating forms in that file.  To see the effect of this change,
 imagine a subdirectory @('\"sub\"') of the current directory, and imagine
 executing @('(ld \"sub/foo.lisp\")'), where file @('foo.lisp') contains the
 form @('(include-book \"bar\")').  Presumably the intention was to consider
 the file @('bar.lisp') in the same directory, @('sub/'), as @('foo.lisp').
 @('Ld') now honors that intention, but in previous versions @('\"bar.lisp\"')
 would have been a reference to a file in the current directory, not in
 @('sub/').</p>

 <p>For users of @('run-acl2') [perhaps there are none!]: A fix has been
 provided by a Debian user via Camm Maguire so that acl2-mode anyone using
 that?] will work in Xemacs, which apparently uses variable
 @('lisp-mode-shared-map') rather than @('shared-lisp-mode-map').</p>

 <p>ACL2 has, for a long time (always?), had a mechanism for avoiding
 re-proving @(see constraint)s generated by @(':functional-instance') @(see
 lemma-instance)s in @(':use') and @(':by') hints.  But this mechanism had not
 applied to defined (as opposed to constrained) functions.  This has been
 fixed.  Thanks to Francisco J. Martin-Mateos (ChesKo) for pointing out this
 problem by sending a clear example.</p>")

(defxdoc note-2-7-guards
  :parents (note-2-7)
  :short "ACL2 Version  2.7 Notes on Guard-related Changes"
  :long "<p>It was possible for guard verification to succeed where it should
 have failed.  See the discussion under @(see note-2-7-bug-fixes).</p>

 <p>There have been changes in the guards generated from type declarations for
 the following cases.  Thanks to Dave Greve and Matt Wilding for suggesting
 such changes.</p>

 @({
  (type (signed-byte n) val)
  (type (unsigned-byte n) val)
  (type (integer m n) val)
 })

 <p>The following examples illustrate the changes.</p>

 @({
  (type (signed-byte 4) x)
  ==> [old] (AND (INTEGERP X) (<= -8 X) (<= X 7))
  ==> [new] (SIGNED-BYTE-P 4 X)

  (type (unsigned-byte 4) x)
  ==> [old] (AND (INTEGERP X) (<= 0 X) (<= X 15))
  ==> [new] (UNSIGNED-BYTE-P 4 X)
 })")

(defxdoc note-2-7-new-functionality
  :parents (note-2-7)
  :short "ACL2 Version  2.7 Notes on New Functionality"
  :long "<p>ACL2 now has a more powerful technique for relieving a @(':')@(tsee
 rewrite) or @(':')@(tsee linear) rule's hypothesis that contains free
 variables.  A new @(see documentation) section has been written describing the
 handling free variables in rules; see @(see free-variables).  In brief, the
 primary change is that when a free-variable match for the current hypothesis
 fails to allow subsequent hypotheses to be relieved, then additional matches
 may be attempted until they have all been tried.  Also see @(see
 rule-classes) (discussion of @(':match-free')).  Also see @(see
 set-match-free-error), see @(see set-match-free-default), and see @(see
 add-match-free-override) for interfaces provided to the user for controlling
 the way ACL2 deals with free variables in hypotheses.  We thank Rob Sumners
 for several helpful discussions about the designs of those interfaces, as well
 as Eric Smith and Robert Krug for helpful related discussions.  Robert Krug
 also found a performance bug in a preliminary version, for which we are
 grateful.</p>

 <p>WARNING: Book certification attempts may take much longer now that, by
 default, ACL2 looks for more free variable matches (see paragraph just above).
 You can get the old behavior by inserting the form</p>

 @({
  (set-match-free-default :once)
 })

 <p>just after the initial @(tsee in-package) form.  However, rules from
 included books that have free variables can still slow down certification.
 This can be fixed by inserting</p>

 @({
  (add-match-free-override :once t)
 })

 <p>before the first event in the file that generates a proof.</p>

 <p>@(see Forward-chaining) has been made more powerful in the presence of free
 variables (see @(see free-variables)), thanks to a contribution by Erik
 Reeber.  Both before and now, when an attempt is made to relieve (prove) a
 hypothesis of a @(':forward-chaining') rule in the case that at least one
 variable in that hypothesis is not yet bound, ACL2 looks in the current
 context for an instance of that hypothesis.  If it finds one, then it binds
 the unbound variables and continues to the next hypothesis.  What is new is
 that ACL2 can now looks for multiple instances of that hypothesis.  Consider
 the following example; an explanation is below.</p>

 @({
  (encapsulate (((op * *) => *))
               (local (defun op (x y) (< x y)))
               (defthm transitivity-of-op
                 (implies (and (op x y) (op y z)) (op x z))
                 :rule-classes :forward-chaining))

  ; fails in Version_2.6; succeeds in in Version_2.7
  (thm (implies (and (op a b) (op b c) (op b e)) (op a c)))
 })

 <p>Before Version_2.7, the proof of the @('thm') above fails.  When the
 @(':forward-chaining') rule @('transitivity-of-op') binds @('x') to @('a') and
 @('y') to @('b'), it then looks for an instance of @('(op y z)') in the
 current context, with @('y') bound to @('b') but @('z') unbound.  It happens
 to find @('(op b e)') before @('(op b c)'), and it then adds @('(op a e)') to
 the context.  But starting with Version_2.7, it continues to look for
 additional instances and finds @('(op b c)') in the context as well, chaining
 forward to @('(op a c)') and thus proving the theorem.</p>

 <p>A new macro, @(tsee bind-free), provides a simple way to get much or most
 of the power of @(see meta)functions.  Thanks to Eric Smith for coming up with
 the idea and to Robert Krug for providing an implementation (which we modified
 only very slightly) and documentation. See @(see bind-free) and see @(see
 bind-free-examples).</p>

 <p>With the addition of @(tsee bind-free) (mentioned above), @(tsee syntaxp)
 has become a macro, although that change should be transparent to the user.
 More importantly, the argument of @('syntaxp') may now refer to variables
 @('mfc') and @('state'), giving @('syntaxp') some of the power of extended
 metafunctions; see @(see syntaxp) and see @(see extended-metafunctions).
 Thanks to Robert Krug for implementing that extension.  Also, the argument of
 @(tsee syntaxp) may now include calls of @(':')@(tsee program) mode functions.
 See @(see syntaxp) and see @(see syntaxp-examples) (thanks to Robert Krug for
 updating the former and creating the latter documentation).</p>

 <p>The linear-arithmetic decision procedure (see @(see linear-arithmetic)) has
 now been extended so that ACL2 can reason about non-linear arithmetic as well
 (see @(see non-linear-arithmetic) for how to turn on this feature).  We thank
 Robert Krug for the initial implementation of this, and Eric Smith for finding
 a couple of bugs in it.</p>

 <p>Some @(tsee trace) utilities have been made available in the ACL2 loop.</p>

 <ul>

 <li>Function @(tsee trace$) (and also @(tsee untrace$)) calls the
 corresponding underlying Lisp routine @('trace') (and @('untrace')), which
 however continues (as it has for some time) to be enhanced for GCL and Allegro
 CL.</li>

 <li>Macro @(tsee open-trace-file) causes trace output to go to a specified
 file.  Macro @(tsee close-trace-file) causes trace output to go to the screen
 (which is the default).</li>

 <li>Macro @('with-error-trace') (or, @('wet') for short) causes a backtrace
 to be written out for many failures, including guard violations.  See @(see
 trace), see @(see trace$), and see :DOC @('wet') [** NOTE: eliminated after
 Version 3.3].</li>

 </ul>

 <p>A new @(tsee theory), @(tsee minimal-theory) has been provided (see @(see
 theories)).  It can be particularly useful for speeding up proofs involving
 @(':use') @(see hints).</p>

 <p>New @(tsee events) @(tsee defund) and @(tsee defthmd) behave exactly like
 @(tsee defun) and @(tsee defthm), respectively, except that these new events
 disable the new name.</p>

 <p>The new macro @(tsee with-output) can be used to suppress output that would
 normally result from evaluation of a form.</p>

 <p>The form @('(')@(tsee pstack)@(')') can give the user an idea of what the
 prover has been up to during a proof, or after a user-aborted proof.
 Moreover, by evaluating @('(verbose-pstack t)') (see @(see verbose-pstack))
 one can get @(see trace)-like information about prover functions, including
 time summaries, printed to the screen during a proof.  Thanks to Bill Legato
 and Robert Krug for initiating this work and to Robert for providing some
 initial implementation.</p>

 <p>The new command @(':')@(tsee comp-gcl) is identical in functionality,
 except that it always leaves @('.c') and @('.h') files when compiling in GCL.
 Thanks to Rob Sumners and Vernon Austel for suggesting such a capability.</p>

 <p>The macro @(tsee e/d) provides a convenient way to @(tsee enable) some
 rules and @(tsee disable) others.  It was formerly in a book supplied with the
 distribution, @('books/ihs/ihs-init.lisp'), written by Bishop Brock (who we
 thank for providing this useful macro).</p>

 <p>New distributed books include those in @('books/ordinals/'),
 @('books/rtl/rel3/'), and @('books/misc/simplify-defuns.lisp') (which is
 documented in @('books/misc/simplify-defuns.txt')).</p>

 <p>The @(':expand') hint now accepts a special value, @(':LAMBDAS'), that
 tells the ACL2 rewriter to expand all lambda applications (@(tsee let)
 expressions).  See @(see hints).</p>

 <p>A new function @(tsee zpf) has been added as fast test against 0 for
 nonnegative fixnums.</p>

 <p>A new macro @(tsee gc$) allows the user to call the garbage collector of
 the underlying Common Lisp.  Thanks to Rob Sumners for suggesting this
 feature.</p>

 <p>It is now possible to @(tsee monitor) @(see simple) (abbreviation) rules.
 However, as a warning explains, they are still not considered monitored during
 preprocessing; see @(see monitor).  Thanks to Robert Krug for providing this
 improvement.</p>

 <p>The second argument of @(tsee certify-book), if supplied, formerly had to
 be either @('t') or a non-negative integer.  Now it can be the symbol @('?'),
 in the @('ACL2') package, indicating that the usual check should be suppressed
 on the number of commands that have been executed to create the world in which
 @(tsee certify-book) was called.</p>")

(defxdoc note-2-7-other
  :parents (note-2-7)
  :short "ACL2 Version  2.7 Notes on Miscellaneous Changes"
  :long "<p>Made several minor @(see documentation) improvements.  We are
 grateful to Eric Smith for suggesting (most of) these.</p>

 <p>Improved @('(show-bdd)') (see @(see bdd)) to give more useful feedback when
 there are ``leaf'' terms not known to be Boolean.</p>

 <p>Sped up processing of large mutual-recursion nests.  In one large example
 the speedup was roughly two orders of magnitude.</p>

 <p>Modified event printing so that if both @(''prove') and @(''event') are
 inhibited, then events are no longer printed on behalf of @(tsee
 certify-book), @(tsee encapsulate), or @(tsee defstobj).  Thanks to Eric Smith
 for prompting consideration of such a change.</p>

 <p>The following technical change was made to support @('with-error-trace')
 and @('wet') (see @(see note-2-7-new-functionality)), but may be of interest
 to those who do low-level programming using the ACL2 logical @(tsee world).
 The @(''unnormalized-body') property is now stored not only for functions
 defined in @(':')@(tsee logic) mode, but also for functions defined by the
 user in @(':')@(tsee program) mode.  (@(':Program') mode Functions built into
 ACL2 still have their @(''unnormalized-body') property omitted, in order to
 save space.)</p>

 <p>The handling of ``invisible'' functions for purposes of controlling
 rewriting (see @(see loop-stopper)) has been moved to a new table; see @(see
 invisible-fns-table).  Macros that access and modify this table are called
 ``@('...-invisible-fns-table')'' in place of their former names,
 ``@('...-invisible-fns-alist').''  This feature was formerly implemented in
 the @(tsee acl2-defaults-table), which prevented a book from exporting lists
 of invisible functions intended to work with the @(see rewrite) rules
 developed in the book.  Thanks to Eric Smith and Rob Sumners for suggesting
 this change.  See @(see set-invisible-fns-table) (formerly
 @('set-invisible-fns-alist')), and also see @(see add-invisible-fns) and see
 @(see remove-invisible-fns), which provides ways to incrementally add to and
 remove from this table, respectively.  The handling of printing binary
 function call nests using macros (See @(see add-binop)) has also been moved
 out of the @(tsee acl2-defaults-table) as suggested by Eric and Rob, but this
 feature didn't work anyhow (see @(see note-2-7-bug-fixes)).  Incidentally, the
 symbols @('binop-table'), @(tsee add-binop), and @(tsee remove-binop) have all
 been added to the list @('*acl2-exports*') (see @(see acl2-user)), @(tsee
 add-invisible-fns) and @(tsee remove-invisible-fns) have been added to that
 list, and @('set-invisible-fns-alist') has been replaced in that list by
 @(tsee set-invisible-fns-table).  Function @('invisible-fns-alistp') is no
 longer defined and has been removed from @('*acl2-exports*').</p>

 <p>We now enforce the stated restriction on the pairings in
 @('macro-aliases-table') (see @(see macro-aliases-table)), namely, that it
 associates names of macros with names of functions (with respect to the current
 ACL2 logical @(see world)).  We make a similar requirement on @(tsee
 invisible-fns-table).</p>

 <p>The @(tsee theory-invariant) event has been modified so that the default
 action is an error rather than a warning.  Thanks to Eric Smith for suggesting
 this change.  Also, the value returned upon successful execution of a @(tsee
 theory-invariant) event is now the key.</p>

 <p>Proof output that reports destructor elimination no longer uses the word
 ``generalizing''.  This small change may help in browsing proof output, since
 now ``generaliz'' takes you to true uses of generalization.  Thanks to Matyas
 Sustik for suggesting such a change.</p>

 <p>The command @(':')@(tsee pl) now prints an abbreviated controller-alist for
 @(';')@(tsee definition) rules.  Formerly the output from @(':pl') could be
 overwhelming when the supplied function was part of a large @(tsee
 mutual-recursion) nest.</p>

 <p>The defaults for keyword parameters of @(tsee certify-book) have changed.
 See @(see note-2-7-bug-fixes), in particular, the discussion there of two
 modifications to @('certify-book').</p>

 <p>Technical changes have been made to @(tsee compress1) and @(tsee compress2)
 that should usually be invisible to users.  The next paragraph describes them
 in detail, only for completeness (i.e., that description can be ignored by most
 users).  But first, here is an example showing an effect on users.  The slow
 array warning was not there previously.  Notice that the warning only arises
 if the event form is changed.  The solution is to be sure that redundant
 @(tsee defconst) forms are syntactically identical.</p>

 @({
  ACL2 !>(defconst *a* (compress1 'demo
                                  '((:header :dimensions (5)
                                             :maximum-length 15
                                             :default uninitialized
                                             :name demo)
                                    (1 . one)
                                    (0 . zero))))

  Summary
  Form:  ( DEFCONST *A* ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   *A*
  ACL2 !>(aref1 'demo *a* 0)
  ZERO
  ACL2 !>(defconst *a* (compress1 'demo
                                  '((:header :dimensions (5)
                                             :maximum-length 15
                                             :default uninitialized
                                             :name demo)
                                    (1 . one)
                                    (0 . zero))))

  This event is redundant.  See :DOC redundant-events.

  Summary
  Form:  ( DEFCONST *A* ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   :REDUNDANT
  ACL2 !>(aref1 'demo *a* 0)
  ZERO
  ACL2 !>(defconst *a* (compress1 'demo
                                  '((:header :dimensions (5)
                                             :maximum-length 15
                                             :default uninitialized
                                             :name demo)
                                    (0 . zero)
                                    (1 . one))))

  This event is redundant.  See :DOC redundant-events.

  Summary
  Form:  ( DEFCONST *A* ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   :REDUNDANT
  ACL2 !>(aref1 'demo *a* 0)

  **********************************************************
  Slow Array Access!  A call of AREF1 on an array named
  DEMO is being executed slowly.  See :DOC slow-array-warning
  **********************************************************

  ZERO
  ACL2 !>
 })

 <p>As before, the von Neumann structure stored in the @(''acl2-array')
 property of the array name contains the array list object in its @(tsee car).
 However, previously it was the case that @('compress1') and @('compress2') did
 not update that @('car') when its new value would be equal to its old value.
 This was done largely in support of some type-set tables defined using @(tsee
 defconst) in @('type-set-b.lisp').  The new versions of @(tsee compress1) and
 @(tsee compress2) are simpler in that no such exception is made in the case of
 equal lists, although instead the entire compression process is
 short-circuited when the input array list object is @(tsee eq) to the @('car')
 of the @(''acl2-array') property.  This change was made because the equality
 test was causing a ``slow array access'' warning to be printed in rare cases
 during proofs, as described elsewhere (see @(see note-2-7-bug-fixes)).</p>

 <p>We no longer distribute documentation specific to Lucid Emacs.  The Info
 documentation in directory @('doc/EMACS/') works well both for Gnu Emacs and
 XEmacs.</p>

 <p>A little-advertised macro, @('value'), has long been allowed for top-level
 forms in @(see books); see @(see embedded-event-form).  This has been replaced
 by a new macro, @('value-triple').  The two have the same semantics at the
 top-level of books, where @(tsee state) is ``live''.  However,
 @('value-triple') should be used at the top-level of a book, while @('value')
 should be used in function definitions (as before).  This change eliminates a
 warning put out by the Allegro Common Lisp compiler for top-level @('value')
 forms in @(see books).</p>")

(defxdoc note-2-7-proof-builder
  :parents (note-2-7)
  :short "ACL2 Version  2.7 Notes on proof-builder Changes"
  :long "<p>Output from the @(see proof-builder) can now be inhibited by
 supplying the symbol @('proof-builder') in the list given to @(see
 set-inhibit-output-lst).</p>")

(defxdoc note-2-7-proofs
  :parents (note-2-7)
  :short "ACL2 Version  2.7 Notes on Changes in Proof Engine"
  :long "<p>An improvement in the linear arithmetic heuristics has been
 provided by Robert Krug.  For information about this change, search for the
 comment in @('add-linear-lemma') (file @('rewrite.lisp')) that begins as
 follows.</p>

 @({
  ; Previous to Version_2.7, we just went ahead and used the result of
 })

 <p>Thanks, Robert!  Also thanks to Eric Smith for providing a motivating
 example.</p>

 <p>The non-linear-arithmetic addition (see @(see non-linear-arithmetic)) led
 to several small changes in the linear-arithmetic decision procedure (see
 @(see linear-arithmetic)).  Two of these changes could affect existing
 proofs.</p>

 <blockquote>

 <p>First, when we are setting up the initial arithmetic database (which we
 call the ``pot-lst''), we have always scanned it to see if there were any
 pairs of inequalities from which we could derive a previously unknown
 equality.  In some cases we added this equality to the clause and in others we
 used it to rewrite the clause, substituting one side of the equality for the
 other throughout the clause.  Previously, the heuristics that we used to
 determine whether we performed the substitution differed from those used in
 several other places in the code.  This has now been regularized, and similar
 heuristics are now used throughout the code.</p>

 <p>The second change to the linear-arithmetic decision procedure is that we
 now explicitly add inequalities derived from type reasoning to the pot-lst.
 Previously, we performed cancellations against these inequalities without
 adding them to the pot-lst.  This change results in there being more
 inequalities in the pot-lst than before, and so more chances for there to be a
 pair of inequalities from which an equality can be derived.  In effect,
 certain simple consequences of the current goal (see @(see type-set)) may now
 be added as hypotheses of the goal or used to perform equality
 substitutions.</p>

 </blockquote>

 <p>A slight improvement has been made to the way certain rewrite rules are
 stored.  It was already the case that a rewrite rule rule whose conclusion
 @('C') is not a call of a known equivalence relation (or @(tsee eq), @(tsee
 eql), or @(tsee =)) is stored as @('(iff C t)'), except that if ACL2 can
 determine (using its @(tsee type-set) mechanism) that @('C') is Boolean, then
 the rule is stored as @('(equal C t)').  The improvement is that if @('C') and
 @('C'') are Boolean, then a rule stated as <tt>(iff C C')</tt> is stored as
 <tt>(equal C C')</tt>.  Thanks to Pete Manolios for providing an example that
 led us to consider this improvement.</p>

 <p>The heuristic use of equalities (fertilization) has been modified.
 Previously, ACL2 would sometimes substitute using an equality but keep the
 equality, and then undo the substitution by using the equality again.  Now,
 when ACL2 keeps an equality after using it, it puts the equality inside a call
 of @(tsee hide).  Descendants of that goal that are unchanged by
 simplification will have this call of @(tsee hide) removed so that the
 equality can once again contribute to the proof.  This change can cause some
 proofs to succeed that otherwise would fail.  In the unlikely event that a
 proof fails that formerly succeeded, the following hint on \"Goal\" may fix
 the problem (see @(see hints)):</p>

 @({
  :expand ((:free (x) (hide x)))
 })

 <p>We have refined the heuristics employed when an @(tsee IF) form is assumed
 true or false.  Our previous attempt (see @(see note-2-6-proofs) for the
 original announcement) was not as general as we had believed.  We have also
 improved some low-level code responsible for rewriting @('IF') expressions.
 In earlier versions of ACL2, it was possible to have the truth or falsity of
 an @('IF') expression explicitly recorded in the type-alist, and yet not use
 this information during rewriting.  This problem has been corrected.  Thanks
 to Robert Krug for noticing this problem and implementing the fix.</p>

 <p>We have sped up the rewriter in some cases where there are large
 collections of mutually-recursive functions (see @(see mutual-recursion)).
 (Implementation notes: technically, we have modified the way function
 @('being-openedp') operates on the @('fnstack'), and we have modified
 @('*current-acl2-world-key-ordering*') as described in the essay above its
 definition.)</p>

 <p>@(see Forward-chaining) is now done in the preprocessing phase of proof
 attempts (see the discussion of @(':DO-NOT') &mdash; see @(see hints)).  This
 is part of a technical change, made in support of translation of type
 declarations to @(see guard)s (see @(see note-2-7-guards)).  Previously,
 whenever ACL2 checked for @(see built-in-clause)s, it then looked for a
 contradiction using @(tsee type-set) reasoning if it did not find a suitable
 built-in clause.  The change is to perform forward-chaining in such cases
 (i.e., when a built-in clause is not found).</p>

 <p>A couple of changes have been made in the generation of goals for @(see
 forcing-round)s.  Thanks to Eric Smith for bringing issues to our attention
 that led to these changes.  For one, @(see guard)s are no longer relevant in
 such goal generation.  Formerly, the addition of a guard could make a proof
 fail that otherwise succeeded.  Secondly, contextual information is now always
 kept when it involves a constrained constant, i.e., a zero-ary function
 introduced in the signature of an @(tsee encapsulate).</p>")

(defxdoc note-2-7-rules
  :parents (note-2-7)
  :short "ACL2 Version  2.7 Notes on Changes in Rules and Constants"
  :long "<p>The @(tsee defcong) macro has been slightly changed.  The
 difference is that the variable generated with suffix @('-EQUIV') will now be
 in the same package as the name of the variable from which it is generated,
 rather than always belonging to the ACL2 package.  Thanks to Hanbing Liu for
 suggesting this change.  (Note that a couple of books have been modified to
 accommodate this change, e.g., @('books/finite-set-theory/set-theory').)</p>

 <p>In Version_2.6, a change was made for rules of class @(':')@(tsee rewrite)
 whose conclusion is a term of the form @('(EQV lhs rhs)'), where @('EQV') is
 @(tsee =), @(tsee eq), or @(tsee eql): the rule was stored as though @('EQV')
 were @(tsee equal).  (See @(see note-2-6-rules).)  This change has been
 extended to rules of class @(':')@(tsee definition).</p>")

(defxdoc note-2-7-system
  :parents (note-2-7)
  :short "ACL2 Version  2.7 Notes on System-level Changes"
  :long "<p>ACL2 now runs (once again) under LispWorks, specifically, LispWorks
 4.2.0.  However, we needed a patch, which presumably will be unnecessary after
 4.2.7.  From LispWorks support:</p>

 <blockquote><p>Users with LispWorks4.2.7 should ask us at
 lisp-support@@xanalys.com for the transform-if-node patch. It will be helpful
 if they quote (Lisp Support Call #11372) when doing so. Also, they must send a
 bug form generated from their LispWorks image: instructions at
 http://www.lispworks.com/support/bug-report.html.</p></blockquote>

 <p>File @('books/Makefile-generic') has been improved so that failed attempts
 to certify a book will cause the `make' to fail.  Previously, an existing
 @('.cert') file was left in place, and that sufficed for the `make' to be
 considered a success.  Now, the old @('.cert') file is first removed when
 recertification is found to be necessary.</p>

 <p>A change has been made to source file @('acl2.lisp') to accommodate GCL
 2.4.3.  (ACL2 Version 2.6 does not work with some versions of GCL 2.4.3.)</p>

 <p>The error message has been improved when certain forms are typed to raw
 Lisp and the ACL2 loop has never been entered (with @('(')@(tsee
 LP)@(')')).</p>

 <p>The following symbols in the ACL2 package have been made untouchable,
 meaning that they are not available to the user: @('ev-fncall'), @('ev'),
 @('ev-lst'), @('ev-acl2-unwind-protect'), @('ev-fncall!'), and
 @('user-stobj-alist-safe').  The reason is that these functions can not be
 called safely except under certain restrictions.  If you want to call the ACL2
 evaluator, consider using the built-in system functions @('trans-eval') or
 simple-translate-and-eval.</p>

 <p>CLISP Version_2.30 implements a notion of ``locking'' the \"LISP\" package
 that is incompatible with building ACL2.  (CLISP Version_2.27 does not appear
 to have had this feature.)  We have gotten around this problem by unlocking
 the \"LISP\" package in ACL2 images built on such CLISPs.</p>

 <p>Automatic proclaiming for GCL, which has (for a long time) been done for
 functions in compiled books, has been improved.  Formerly, the only time a
 non-trivial output type (i.e., other than @('t')) was inferred was when
 macroexpansion produced an explicit call of @(tsee the).  Now, @(tsee if)
 expressions can also generate non-@('t') output types.  Consider the following
 example.</p>

 @({
  (defmacro the-fixnum (n)
    (list 'the '(signed-byte 29) n))
  (defmacro 1+f (x)
    (list 'the-fixnum
          (list '1+ (list 'the-fixnum x))))
  (defun foo (x)
    (declare (type (unsigned-byte 27) x))
    (if (zp x)
        0
      (1+f (foo (1-f x)))))
 })

 <p>Formerly, the @('proclaim') forms for @('foo'), before and after this
 improvement, are as shown below.</p>

 @({
  (PROCLAIM '(FTYPE (FUNCTION ((UNSIGNED-BYTE 27)) T) FOO))                ;old
  (PROCLAIM '(FTYPE (FUNCTION ((UNSIGNED-BYTE 27)) (SIGNED-BYTE 29)) FOO)) ;new
 })

 <p>Compiler info messages sent to error stream were eliminated for CMUCL.</p>")

(defxdoc note-2-8
  :parents (release-notes)
  :short "ACL2 Version  2.8 (March, 2004) Notes"
  :long "<p>BRIEF SUMMARY.</p>

 <p>The Version_2.8 notes are divided into the indicated subtopics.  Here we
 give only a brief summary of just a few of the major new features and changes
 that seem most likely to impact existing proofs.  Not included in this brief
 summary, but included in the subtopics, are descriptions of many improvements
 (including bug fixes and new functionality) that should not get in the way of
 existing proof efforts.  In the description below we also omit discussion of
 changes that will become clear by way of error messages if they affect
 you.</p>

 <p>In particular, please see @(see note-2-8-new-functionality) for discussion
 of a number of new features that you may find useful.</p>

 <p>Acknowledgements and elaboration, as well as other changes, can be found in
 the subtopics listed below.</p>

 <h5>Some of the bug fixes (see @(see note-2-8-bug-fixes))</h5>

 <ul>

 <li>Some soundness bugs were fixed.</li>

 <li>The handling of free variables in hypotheses (see @(see free-variables))
 of rewrite and linear rules had a bug that prevented some proofs from going
 through.  Now that this bug has been fixed, you may find some proofs running
 much more slowly than before.  You can use @(tsee accumulated-persistence) and
 @(tsee add-match-free-override) to remedy this situation; see @(see
 note-2-8-bug-fixes) for details.</li>

 <li>The @(see default-hints) in the current logical @(see world) are no
 longer ignored by @(tsee verify-guards).</li>

 <li>Forms violating guard-checking such as @('(defconst *silly* (car 3))')
 are now allowed in @(see books).</li>

 </ul>

 <h5>Some of the new functionality (see @(see note-2-8-new-functionality))</h5>

 <ul>

 <li>WARNING: You may find that @('control-d') (in emacs, @('control-c
 control-d')) can throw you completely out of Lisp where it had not formerly
 done so.</li>

 <li>ACL2 now starts up inside the ACL2 loop &mdash; that is, @('(')@(tsee
 LP)@(')') is executed automatically &mdash; when built on CLISP or Allegro CL.
 This was already the case for GCL and CMUCL, and it still is not true for
 LispWorks.</li>

 <li>See @(see note-2-8-ordinals) for a discussion of a significant change in
 ordinal representation, and in particular, for how to preserve existing proofs
 that depend on the previous ordinal representation.</li>

 <li>Macros @(tsee mbe) (``must be equal''), @(tsee mbt) (``must be true''),
 and @(tsee defexec) have been introduced, which allow the user to attach
 alternate executable definitions to functions.</li>

 <li>The user can now control multiple matching for free variables in
 hypotheses for @(':')@(tsee forward-chaining) rules, as has already been
 supported for @(':')@(tsee rewrite) and @(':')@(tsee linear) rules.</li>

 <li>It is no longer necessary to specify @('(set-match-free-error nil)') in
 order to avoid errors when a rule with free variables in its hypotheses is
 missing the @(':match-free') field.</li>

 <li>The form @('(break-on-error)') causes, at least for most Lisps, entry
 into the Lisp debugger whenever ACL2 causes an error.</li>

 <li>A new @(tsee table) has been provided so that advanced users can override
 the built-in @('untranslate') functionality.  See @(see
 user-defined-functions-table).</li>

 <li>The @(tsee pstack) (`process [prover] stack'') mechanism, formerly
 denoted @('checkpoints'), has been improved.  One of these improvements is to
 show actual parameters with @('(pstack t)') rather than formals.</li>

 <li>The @(tsee defstobj) event is now allowed to take an @(':inline')
 argument, which can speed up execution.</li>

 <li>Macro @(tsee cw-gstack) no longer takes arguments for the @('gstack') or
 @(tsee state).  To print terms in full rather than abbreviated: @('(cw-gstack
 :evisc-tuple nil)').</li>

 <li>The @(tsee include-book) event now has an additional (optional) keyword,
 @(':dir').  In particular, @('(include-book \"foo/bar\" :dir :system)') will
 include the indicated book after prepending the path of the built-in
 @('books/') directory.  You will probably not find @(':dir :system') to be
 useful if you move the executable image or distributed books; see @(see
 include-book), in particular its ``soundness warning''.</li>

 <li>The printing of results in raw mode (see @(see set-raw-mode)) may now be
 partially controlled by the user: see @(see add-raw-arity).</li>

 <li>For those using Unix/Linux `make': A @('cert.acl2') file can contain
 forms to be evaluated before an appropriate @(tsee certify-book) command is
 invoked automatically (not included in @('cert.acl2')).</li>

 </ul>

 <h5>Some of the changes in the proof engine (see @(see note-2-8-proofs))</h5>

 <ul>

 <li>ACL2 now prevents certain rewriting loops; see @(see
 rewrite-stack-limit).</li>

 <li>Small changes have been made to heuristics for controlling rewriting
 during proofs by induction and in handling certain ``weak'' @(see
 compound-recognizer) rules.</li>

 <li>The handling of free variables in a hypothesis of a @(see rewrite) rule
 (see @(see free-variables)) has been improved in the case that the hypothesis
 is of the form @('(equiv x y)'), where @('equiv') is a known equivalence
 relation (see @(see equivalence)).</li>

 <li>We have modified how the ACL2 simplifier handles the application of a
 defined function symbol to constant arguments, by avoiding the introduction of
 @(see hide) when evaluation fails if the term can be rewritten.</li>

 <li>The generation of \"Goal\" for recursive (and mutually-recursive)
 definitions now uses the subsumption/replacement limitation (default 500).
 See @(see case-split-limitations).</li>

 <li>Default hints now apply to hints given in definitions, not just theorems.
 See @(see default-hints).</li>

 <li>Linear arithmetic now uses the conclusions of @(tsee forward-chaining)
 rules, and @(tsee type-set) now uses a small amount of linear reasoning when
 deciding inequalities.</li>

 </ul>

 <h5>Some of the changes in rules, definitions, and constants (see @(see note-2-8-rules))</h5>

 <ul>

 <li>See the above doc topic.</li>

 </ul>

 <h5>Guard-related changes are described in see @(see note-2-8-bug-fixes)</h5>

 <h5>Some of the proof-builder changes (see @(see note-2-8-proof-builder))</h5>

 <ul>

 <li>Added new @(see proof-builder) commands @('wrap1'), @('wrap'), and
 @('wrap-induct'), to combine multiple conjuncts or goals.</li>

 <li>The @('type-alist') command now takes optional arguments that control
 whether or not the governors and/or conclusion are used in computing the
 context.</li>

 </ul>

 <h5>Some of the system-level changes (see @(see note-2-8-system))</h5>

 <ul>

 <li>ACL2 now runs on OpenMCL and on MCL 5.0.</li>

 </ul>

 <h5>Some of the other changes (see @(see note-2-8-other))</h5>

 <ul>

 <li>Emacs file @('emacs/emacs-acl2.el') has been updated (see @(see
 note-2-8-other) for details).</li>

 <li>When @(':pl') is given a term other than a symbol, it will print all
 rewrite rules that match that term.</li>

 <li>A new function, @(tsee pkg-witness), returns a symbol in the given
 package.</li>

 <li>The list constant @('*acl2-exports*') has been extended.</li>

 <li>A new release of the rtl library has been included: @('books/rtl/rel4/').
 See the @('README') file in that directory.</li>

 </ul>

 <p>Again, please proceed to the subtopics for more thorough release
 notes.</p>")

(defxdoc |NOTE-2-8(R)|
  :parents (release-notes)
  :short "ACL2 Version  2.8(r) (March, 2003) Notes"
  :long "<p>The @('Makefile') has been modified by adding a new target,
 @('clean-links').  This can be used in order to remove all soft links, which
 is useful if the directory is copied or moved to a new location or if there
 are file system changes that cause problems with link pathnames.</p>

 <p>Please also see @(see note-2-8) for changes to Version_2.8 of ACL2.</p>")

(defxdoc note-2-8-bug-fixes

; Fixes not included below, and other notes:

; The tautology checker bug mentioned in the :doc below was in call-stack.

; A bug was fixed in assign-wormhole-output [renamed assign-wormhole-status
; after v3-6-1]: er-progn replaces pprogn.

; It is no longer legal for user code to call include-book (this is disallowed
; in translate11).  See the comment in *inside-include-book-fn*.

; The missing argument in the first (er hard ...) in rewrite-fncall has been
; supplied.

; Subterm-one-way-unify has been modified in order to avoid any possibility of
; calling fargs on a quotep.

; Here is a way to exhibit the proof-builder expand bug described in the first
; paragraph of the documentation below:

;  (in-package "ACL2")
;
;  (encapsulate
;   (((foo *) => *)
;    ((bar *) => *))
;
;   (local (defun foo (x) x))
;   (local (defun bar (x) (not x)))
;
;   (defthm foo-open
;     (equal (foo x) x)
;     :rule-classes :definition)
;
;   (defthm bar-not-foo
;     (equal (bar x) (not (foo x)))
;     :rule-classes :definition))
;
;  (defthm bad (equal (foo x) (bar x))
;    :rule-classes nil
;    :instructions
;    ((:dv 1) :expand :nx :expand :top :s))
;
;  (defthm contradiction
;    nil
;    :rule-classes nil
;    :hints (("Goal" :use bad)))

; The second proof-builder bug mentioned below can be exhibited as follows:

;  (encapsulate
;   ()
;   (local
;    (defthm bug-lemma (if x (if x t nil) nil)
;      :rule-classes nil
;      :instructions ((dive 2 3) :s)))
;   (defthm bug nil
;     :rule-classes nil
;     :hints (("Goal" :use ((:instance bug-lemma (x nil)))))))

; The function ev-acl2-unwind-protect was fixed to incorporate a change made
; long ago, by J, to acl2-unwind-protect.  This function was subsequently
; replaced by ev-w-acl2-unwind-protect.

; Without the new fix based on Matyas's suggestion (see paragraph on tautology
; checker below and Qiang's example), we had to change subgoal numbers in hints
; in the following books:
; direct-incorporation-sound-iff in
;   workshops/2003/matlin-mccune/support/simp.lisp
; graph-equivp1-load-graph1 in
;   workshops/2003/greve-wilding_mbe/support/run-fpst.lisp

; Regarding the soundness bug about type-prescription rules, whose description
; below mentions local-incompatibility and refers to an example in that :doc
; topic: The full example is below.  It actually proved in every GCL image of
; ACL2 from v2-7 back to at least v2-4.  The problem goes back at least through
; v2-3 as well; evaluate :PROPS FOO to see a type-prescription record with a
; :basic-ts of nil.  Our fix is to modify add-type-prescription-rule to cause a
; hard error when destructure-type-prescription fails; previously we had
; ignored the erp return value from destructure-type-prescription.

;   (in-package "ACL2")
;
;   (defun my-natp (x)
;     (declare (xargs :guard t))
;     (and (integerp x)
;          (<= 0 x)))
;
;   (defun foo (x)
;     (nfix x))
;
;   (in-theory (disable foo (:type-prescription foo)))
;
;   (encapsulate
;    ()
;    (local (defthm my-natp-cr
;             (equal (my-natp x)
;                    (and (integerp x)
;                         (<= 0 x)))
;             :rule-classes :compound-recognizer))
;    (defthm foo-type-prescription
;      (my-natp (foo x))
;      :hints (("Goal" :in-theory (enable foo)))
;      :rule-classes ((:type-prescription :typed-term (foo x)))))
;
;   (defthm rationalp-foo
;     (rationalp (foo x))
;     :hints (("Goal" :in-theory (enable foo)))
;     :rule-classes :type-prescription)
;
;   (defthm bad-lemma
;     (equal (foo x) 1)
;     :rule-classes nil)
;
;   (defthm bad
;     nil
;     :rule-classes nil
;     :hints (("Goal" :use ((:instance bad-lemma (x 1))))))

  :parents (note-2-8)
  :short "ACL2 Version  2.8 Notes on Bug Fixes"
  :long "<p>We have fixed a soundness bug in the tautology checker's handling
 of expressions of the form @('(not (not x))').  This bug has gone back at
 least as far as Version_2.4.  All of the regression tests passed after the
 fix, without modification.  So we hope that this bug has rarely bitten anyone.
 Thanks to Qiang Zhang for sending us a proof of @('nil') that led us to this
 fix: @('(thm (equal (and p q) (not (or (not p) (not q)))))').  And thanks to
 Matyas Sustik for an observation that led to an improvement of our initial
 fix.</p>

 <p>The preceding version (2.7) introduced a soundness bug in handling of ACL2
 @(see arrays), in which functions @(tsee compress1) and @(tsee compress2) were
 returning the input alist rather than compressing it appropriately.  Here is a
 proof of @('nil') that no longer succeeds, based on a bug report from Warren
 Hunt, who we thank for bringing this problem to our attention.</p>

 @({
  (defthm bad
    (not (let* ((ar2 (aset1 'my-array ar1 3 10))
                (ar3 (compress1 'my-array ar2))
                (ar4 (reverse (reverse ar2)))
                (ar5 (compress1 'my-array ar4)))
           (and (equal ar2 ar4)
                (not (equal ar3 ar5)))))
    :rule-classes nil)
  (defthm contradiction
    nil
    :rule-classes nil
    :hints ((\"Goal\" :use
             ((:instance bad
                         (ar1 (compress1 'my-array
                                         '((3 . 5)
                                           (:HEADER :DIMENSIONS (5)
                                                    :MAXIMUM-LENGTH 6
                                                    :DEFAULT 0
                                                    :NAME MY-ARRAY)))))))))
 })

 <p>On a related note, a new function @(tsee flush-compress) can be used for
 subtle control of under-the-hood raw Lisp support for fast array access,
 although we expect it to be very rare that users need this extra support.</p>

 <p>Previous versions have had two soundness bugs that can occur when using the
 @(see proof-builder):</p>

 <ul>

 <li>The first bug pertains to the @('expand') command, and hence
 @('x') and @('x-dumb') commands (which call @('expand')); see @(see
 proof-builder-commands).  The bug can occur when applying the above commands
 when the current term is a call of a constrained function symbol for which
 there is a @(':')@(tsee definition) rule.  Now, the @('expand') command will
 succeed only when the function symbol of the current term is a defined
 function symbol, in which case the original definition is always used, in
 analogy to how the @(':expand') hint works in the prover; see @(see hints).
 Thanks to John Erickson for sending an example that led us to wonder if there
 might be a soundness problem.</li>

 <li>The second bug pertains to the @('s') command (and commands that call it,
 e.g., @('s-prop')).  The proof-builder forms a context out of the top-level
 hypotheses and the @('if')-terms governing the current term.  If there is a
 contradiction in the top-level hypotheses, the proof-builder can appropriately
 consider the goal to be proved, and it does so.  But formerly, the criterion
 was weaker: the contradiction could involve the combination of the top-level
 hypotheses and @('if')-term governors.  Thanks to Rob Sumners for noticing
 this bug.</li>

 </ul>

 <p>A soundness bug could be provoked in some Lisps by applying @(tsee defpkg)
 to the empty string.  This has been disallowed.</p>

 <p>We fixed a soundness bug related to packages caused by a failure to track
 axioms introduced @(tsee local)ly on behalf of @(tsee defpkg) events.  See
 @(see hidden-death-package).</p>

 <p>We fixed a soundness bug caused by a failure to check that a @(':')@(tsee
 type-prescription) rule can be processed when proofs are skipped or under a
 @(tsee defequiv) event.  The former case can occur when processing an @(tsee
 encapsulate) or @(tsee include-book) event, where the rule could depend on a
 @(tsee local) @(':')@(tsee compound-recognizer) rule preceding the proposed
 @(':')@(tsee type-prescription) rule under the same @(tsee encapsulate) or
 @(tsee include-book) event.  See @(see local-incompatibility) for such an
 example.</p>

 <p>We fixed a potential soundness bug relating to reclassifying a
 @(':program') mode function to @(':logic') mode (as done by @(tsee
 verify-termination) or the submission of an appropriate ``redundant''
 definition) without adequate checking that @(tsee stobj) usage was identical.
 Allegedly redundant definitions must now preserve the @('stobjs') declaration
 as well as the formals, body, guard and type declarations.  We thank Vernon
 Austel for pointing out this problem.</p>

 <p>It was possible to get a raw Lisp error by introducing a @(tsee local)ly
 defined function with @(see guard) verification inhibited and then
 subsequently introducing the same definition non-locally without that
 inhibition.  The following example will clarify.</p>

 @({
  (encapsulate nil
    (local
      (defun foo (x) (declare (xargs :guard t :verify-guards nil)) (car x)))
    (defun foo (x) (declare (xargs :guard t)) (car x)))
  ; The following causes a raw lisp error because ACL2 runs the Common Lisp
  ; definition of foo, because it thinks that foo's guard of t was verified.
  (thm (equal (foo 3) xxx))
 })

 <p>Thanks to Jared Davis for bringing this problem to our attention.  We are
 particularly grateful to Jared because his example exploited this bug by
 applying it to a function defined using @(tsee mbe) (introduced in this same
 version, 2.8), in order to prove @('nil')!</p>

 <p>The sort of error message shown below can legitimately occur when
 certifying a book in a certification world where there was an @(tsee
 include-book) command with a relative pathname (see @(see pathname)).
 However, it was occurring more often than necessary.  This has been fixed.</p>

 <blockquote><p>ACL2 Error in (CERTIFY-BOOK \"foo\" ...): The certification
 world has include-book commands for book \"bar\" that correspond to different
 full pathnames, namely \"/u/dir1/bar\" and \"/u/dir2/bar\".  ACL2 cannot
 currently certify a book in such a world.  To work around this problem, use an
 absolute pathname for at least one of these books (see :DOC
 pathname).</p></blockquote>

 <p>Bugs were fixed in @(tsee with-output), in particular related to the use of
 values @(':all').  Also, documentation for @('with-output') has been improved.
 Thanks to Vernon Austel for pointing out the bugs.</p>

 <p>Fixed a lisp error occurring when @('bash') proof-builder command was given
 illegal syntax, e.g., @('(bash ((\"Goal\" :in-theory (enable
 binary-append))))') instead of @('(bash (\"Goal\" :in-theory (enable
 binary-append)))').</p>

 <p>We added an appropriate guard to @(tsee find-rules-of-rune), which will
 avoid hard lisp errors when this function is called on non-@(see rune)
 arguments.  Thanks to Eric Smith for pointing out this issue.</p>

 <p>It was possible for a redundant @(tsee include-book) form (see @(see
 redundant-events)) to leave a @(see command) in the ACL2 logical @(see world)
 and to cause (re-)loading of a compiled file.  These behaviors have been
 fixed.  In particular, if @('book1') has already been included in the current
 ACL2 @(see world) and @('(include-book \"book1\")') occurs in @('book2'), then
 the compiled file for @('book1') will not be loaded again when @('book2') is
 included.  Thanks to Dave Greve for bringing our attention to these problems,
 and to Eric Smith for bringing up a special case earlier (where \"//\"
 occurred in the book name).</p>

 <p>The summary printed at the end of a proof had not listed @(':')@(tsee
 induction) rules used in a proof.  This has been corrected.</p>

 <p>The use of proof trees in emacs redefined `@('control-c control-c')' in
 such a way that in telnet mode, the telnet session was interrupted and perhaps
 could not be continued.  This has been fixed.</p>

 <p>Source function @('load-theory-into-enabled-structure') contained a
 guard-violating call of @(tsee compress1).  Thanks to Vernon Austel for
 bringing this problem to our attention; even though this bug was benign (as he
 pointed out), we like keeping the source code free of guard violations.</p>

 <p>A number of proof-builder atomic macros caused a hard error when all goals
 have already been proved.  This has been fixed.  Thanks to John Erickson for
 sending an example of the issue.</p>

 <p>A bug has been fixed in @(tsee add-match-free-override).  Formerly, a
 @(tsee table) @(see guard) violation occurred when calling @(tsee
 add-match-free-override) more than once with first argument other than
 @(':clear').</p>

 <p>Definitions of functions involving large constants could cause stack
 overflows.  This has been fixed, at least in some of the most egregious cases
 (by making a source function @('fn-count-evg') tail-recursive).  Thanks to
 Jared Davis for bringing this problem to our attention.</p>

 <p>Evaluation of computed hints could cause stack overflows.  This has been
 fixed.  Thanks to Eric Smith for bringing this problem to our attention.</p>

 <p>Evaluation of @(':')@(tsee monitor) on @(':')@(tsee definition) @(see
 rune)s is now fast even if the specified function is part of a very large
 @(tsee mutual-recursion) nest.  Thanks to Eric Smith for sending an example
 showing that this wasn't always the case.</p>

 <p>Fixed a bug in @('books/bdd/cbf.lisp') that was causing certification of
 distributed bdd books to fail when the connected book directory (see @(see
 cbd)) differs from the current working directory.  Thanks to Scott Guthery for
 bringing this bug to our attention and supplying a helpful log.</p>

 <p>Duplicate rule names have been eliminated from warnings generated upon the
 use of enabled @(':')@(tsee rewrite) or @(':')@(tsee definition) rules.
 Thanks to Eric Smith for pointing out this problem.</p>

 <p>The trace utilities (see @(see trace)), as modified for GCL and Allegro
 Common Lisp, had failed to show more than the first return value for so-called
 ``@('*1*')'' functions (essentially, @(see executable-counterpart) functions)
 when they were returning multiple values (via @(see mv)).  This has been
 fixed.  Thanks to Erik Reeber for pointing out this problem.  Also, it is now
 possible to refer to @('arglist') in @(see trace$) forms when ACL2 is built on
 GCL, not just when ACL2 is built on Allegro Common Lisp.</p>

 <p>Uses of @(tsee hide) introduced during proofs by failed attempts to
 evaluate constrained functions (see @(see hide)) are now tracked, so that the
 @(see rune) @('(:DEFINITION HIDE)') will show up in the summary.</p>

 <p>The following bug, introduced back in Version 2.7, has been fixed.  The bug
 applied only to GCL and may well not have affected anyone.  But the function
 proclamation computed by ACL2 for compilation usually had an output type of
 @('nil') where it should have been @('t').</p>

 <p>The macro @(tsee gc$) had a bug exhibited when it was supplied one or more
 arguments.  This has been fixed.</p>

 <p>The macro @(tsee defabbrev) broke when supplied a string and no
 documentation, e.g., @('(defabbrev foo () \"\")').  Thanks to Rob Sumners for
 noticing this problem and providing a fix, which we have incorporated.</p>

 <p>For ACL2 executables built on Allegro Common Lisp, a Lisp error occurred
 when @(tsee trace$) was called on other than a defined function symbol.  Now
 ACL2 prints a more useful error message.</p>

 <p>The proof-builder no longer accepts a @('(')@(tsee verify)@(')') command
 when some function symbol in the original goal no longer exists in the current
 ACL2 logical @(see world).  Thanks to John Erickson for bringing this issue to
 our attention.</p>

 <p>The function @('ld-redefinition-action') may now be called by the user.
 Thanks to Vernon Austel for suggesting that we remove this symbol from the
 list of so-called untouchables.</p>

 <p>The handling of free variables in hypotheses (see @(see free-variables)) of
 rewrite and linear rules had a bug that prevented some proofs from going
 through.  Here is a simple example, essentially provided by Diana Moisuc, who
 we thank for bringing this issue to our attention.  The proof of the @(tsee
 thm) below had failed, but now will succeed.  This particular bug prevented,
 for example, the @(':all') behavior from occurring when the first hypothesis
 of the rule does not have free variables.  NOTE: Now that this bug has been
 fixed, you may find some proofs running much more slowly than before.  You can
 use @(tsee accumulated-persistence) to locate rules that are slowing down your
 proofs because of excessive attention to free variables, and then execute
 @(tsee add-match-free-override) for those rules (or, just change the rules
 themselves to specify @(':once') in the @(':')@(tsee rule-classes)).</p>

 @({
  (defstub foo1 (* ) => *)
  (skip-proofs
   (defthm aux-foo1
     (implies (and (integerp a)
                   (integerp i)
                   (equal (foo1 0)  (list 0 i)))
              (equal (foo1 a) (list 0 (+ a i))))
     :rule-classes ((:rewrite :match-free :all))))
  (thm
   (implies (and (integerp i)
                 (integerp a)
                 (equal (foo1 0) (list 0 i)))
            (equal (foo1 a) (list 0 (+ a i)))))
 })

 <p>Formerly, creation of large arrays could cause an error in the underlying
 Common Lisp implementation without helpful messages for the user.  Now, we
 check Common Lisp restrictions on arrays and print a helpful error message if
 they are violated, namely: each dimension must be less than the value of
 Common Lisp constant @('array-dimension-limit'), and the product of the
 dimensions must be less than the value of Common Lisp constant
 @('array-total-size-limit').  Thanks to Warren Hunt for bringing this issue to
 our attention.  Note: this change also removes a former restriction of @(tsee
 stobj) array fields to size smaller than 2^28-1, provided the underlying Lisp
 can support larger arrays.</p>

 <p>The @(see default-hints) in the current logical @(see world) were ignored
 by @(tsee verify-guards).  This has been fixed.  Thanks to Jared Davis for
 pointing out this bug and sending a helpful example.</p>

 <p>The @(tsee brr) mechanism has been cleaned up in order to avoid hard errors
 and infinite loops that can arrive when typing interrupts (@('control-c')) or
 end-of-files (@('control-d')) inside the @(tsee brr) loop.  Thanks to Dave
 Greve, Olga Matlin, Eric Smith, and Serita Van Groningen for bringing this
 issue to our attention.  As a byproduct, if you type @('control-d') (or if
 inside emacs, @('control-c control-d')), you may now quit entirely out of ACL2
 and lisp (see @(see good-bye)) in some cases where you formerly would not
 have, for example when sitting at the ACL2 prompt (which formerly, in Allegro
 Common Lisp for example, would merely take you into raw Lisp rather than
 quitting everything).</p>

 <p>We have eliminated structural flaws in the HTML documentation pages that
 could make them unreadable in some browsers.  Thanks to Bill Young for
 bringing this issue to our attention and to Joe Hendrix for diagnosing the
 problem.</p>

 <p>The @(see proof-builder) could run very slowly after many instructions in a
 given session.  This has been fixed; thanks to Art Flatau for bringing this
 problem to our attention.  (Implementation detail: We now keep tag-trees
 duplicate-free when we accumulate them into state.  This change could have
 minor speed advantages for some top-level proofs too, not just in the
 proof-builder.)</p>

 <p>The printing of accesses to stobjs using nth or update-nth has been done
 using symbolic constants since ACL2 Version_2.6.  However, there was a bug
 that prevented this feature from working for @(tsee update-nth) except at a
 top-level call.  This has been fixed.  Thanks to Julien Schmaltz for bringing
 this problem to our attention.  For example, consider these events:</p>

 @({
  (defstobj st field0 field1)
  (thm (equal (nth 1 (update-nth 0 17 st)) (car (cons xxx yyy)))
       :hints ((\"Goal\" :in-theory (disable nth update-nth))))
 })

 <p>Before the fix, the proof attempt of the above silly thm printed the
 following.</p>

 @({
  (NTH 1 (UPDATE-NTH *FIELD0* 17 ST))
 })

 <p>After the fix, we instead see the following.</p>

 @({
  (NTH *FIELD1* (UPDATE-NTH *FIELD0* 17 ST))
 })

 <p>It is now possible to certify and subsequently include @(see books) that
 require guard-checking to be off.  For example, the book can contain the form
 @('(defconst *silly* (car 3))') even though @('3') fails to satisfy the guard
 of @(tsee car).  Formerly, it was necessary to execute @(':')@(tsee
 set-guard-checking)@(' nil') before a @(tsee certify-book) or @(tsee
 include-book) in order for such a form to be handled without error.  Thanks to
 Hanbing Liu for bringing this problem to our attention.</p>

 <p>Fixed a @(see proof-builder) bug that could cause probably cause strange
 error, ``Attempt to access the plist field''.  Thanks to Bill Young for
 bringing this problem to our attention.</p>

 <p>Fixed a @(see proof-builder) bug that was failing to record applications of
 rewrite rules using the proof-builder's @(':rewrite') command, causing the
 proof summary to omit mention of that rule (for example, when using the
 proof-builder's @(':exit') command to generate an @(':instructions') hint).
 Thanks to Bill Young for pointing out this bug.</p>

 <p>Modernized some of the proof-tree emacs and infix printing stuff, thanks to
 suggestions made by Camm Maguire.</p>")

(defxdoc note-2-8-guards
  :parents (note-2-8)
  :short "ACL2 Version  2.8 Notes on Guard-related Changes"
  :long "<p>All the guard-related changes may be found elsewhere; in
 particular, see @(see note-2-8-bug-fixes).</p>")

(defxdoc note-2-8-new-functionality

; Not mentioned in detail below:

; Rob Sumners's stobj :inline mod moves the live stobj tests from the raw Lisp
; definitions to the *1* code.  The idea is not even to call the raw Lisp code
; with non-live stobjs.

  :parents (note-2-8)
  :short "ACL2 Version  2.8 Notes on New Functionality"
  :long "<p>WARNING: You may find that @('control-d') (in emacs, @('control-c
 control-d')) can throw you completely out of Lisp where it had not formerly
 done so.</p>

 <p>(CLISP and Allegro CL only) ACL2 now starts up inside the ACL2 loop &mdash;
 that is, @('(')@(tsee LP)@(')') is executed automatically &mdash; when built
 on CLISP or Allegro CL.  This was already the case for GCL and CMUCL, and it
 still is not true for LispWorks.  Thanks to Joe Corneli for bringing the CLISP
 command-line option @('\"-i\"') to our attention, which led to this CLISP
 change and inspired reconsideration of how to do this for Allegro CL.</p>

 <p>Pete Manolios and Daron Vroon have changed the representation of ordinals
 in ACL2, defined algorithms for ordinal arithmetic, and created a library of
 theorems to reason about ordinal arithmetic.  We thank them for these nice
 contributions.  See @(see note-2-8-ordinals) for details, in particular, for
 how to preserve existing proofs that depend on the previous ordinal
 representation.</p>

 <p>Sometimes users create rules of class @(':')@(tsee rewrite) that cause an
 infinite loop in the ACL2 rewriter.  This has lead to Lisp stack overflows and
 even segmentation faults.  Now, the depth of calls of functions in the ACL2
 rewriter is limited, and under user control.  See @(see
 rewrite-stack-limit).</p>

 <p>Macros @(tsee mbe) (``must be equal'') and @(tsee mbt) (``must be true'')
 have been introduced, which allow the user to attach fast executable
 definitions to (presumably slower) @(':')@(tsee logic) mode functions.  Thanks
 to Vernon Austel for a key idea.  Also provided is a macro @(tsee defexec),
 which employs @(tsee mbe) but enforces the requirement that the executable
 definition also terminates.  Thanks to Jose Luis Ruiz Reina for collaborating
 in the design and development of @(tsee defexec), and for useful comments from
 a number of others as well in the development of @('mbe') including Joe
 Hendrix and Rob Sumners.</p>

 <p>Definitions have been added for functions @(tsee rassoc-eq) and @(tsee
 rassoc-equal), which are like @(tsee rassoc) but use different tests and have
 different guards.  (Compare @(tsee assoc-eq) and @(tsee assoc-equal), which
 are in similar relation to @(tsee assoc).)</p>

 <p>The user can now control multiple matching for free variables in hypotheses
 for @(':')@(tsee forward-chaining) rules, as has already been supported for
 @(':')@(tsee rewrite) and @(':')@(tsee linear) rules.  For
 @(':forward-chaining') rules, ``free variables'' are those in the hypotheses
 not bound by a given trigger term.  As for @(':rewrite') and @(':linear')
 rules, free-variable matching may be limited to the first successful attempt
 by specifying @(':match-free :once') with @(':forward-chaining') in the
 @(':')@(tsee rule-classes), and @(tsee add-match-free-override) may be used to
 modify the behavior of an existing rule.  Thanks to Erik Reeber for most of
 the implementation of these new capabilities, as well as significant
 assistance with a corresponding new documentation topic (see @(see
 free-variables-examples-forward-chaining)).</p>

 <p>It is no longer necessary to specify @('(set-match-free-error nil)') in
 order to avoid errors when a rule with free variables in its hypotheses is
 missing the @(':match-free') field.  (This was already true during book
 certification, but now it is the case in interactive sessions as well.)</p>

 <p>The form @('(break-on-error)') causes, at least for most Lisps, entry into
 the Lisp debugger whenever ACL2 causes an error.  See @(see break-on-error).
 Thanks to John Erickson for providing encouragement to provide this
 feature.</p>

 <p>A new @(tsee table) has been provided so that advanced users can override
 the built-in @('untranslate') functionality.  See @(see
 user-defined-functions-table).</p>

 <p>The @(tsee pstack) mechanism (formerly denoted @('checkpoints')) has been
 improved.  The ``process [prover] stack,'' or pstack, is automatically printed
 when proofs abort.  Evaluation of function calls on explicit arguments during
 proofs is now tracked.  Actual parameters are shown with @('(pstack t)')
 rather than formals.  Thanks to Bill Legato for suggesting the first two of
 these improvements and, in general, encouraging changes that make ACL2 easier
 to use.</p>

 <p>The @(tsee defstobj) event is now allowed to take an @(':inline') argument,
 which can speed up execution.  Thanks to Rob Sumners for suggesting and
 implementing this new feature.</p>

 <p>Macro @(tsee assert$) has been added in order to make it easy to write
 assertions in one's code.  Semantically, @('(assert$ test form)') is the same
 as @('form'), but it causes a hard error (using @(tsee illegal)) if @('test')
 evaluates to @('nil').</p>

 <p>Macro @(tsee cw-gstack) no longer takes arguments for the gstack or @(tsee
 state).  However, it now takes a keyword argument (which is optional),
 @(':evisc-tuple'), that can be used to control how it prints terms.  In
 particular, @('cw-gstack') abbreviates large terms by default, but
 @('(cw-gstack :evisc-tuple nil)') causes terms to be printed in full.  Thanks
 to Robert Krug and Eric Smith for requesting this improvement.</p>

 <p>The advanced user now has more control over the evisceration of terms.  See
 @(see ld-evisc-tuple), in particular the new paragraph on ``The printing of
 error messages and warnings.''</p>

 <p>The @(tsee include-book) event now has an additional (optional) keyword,
 @(':dir').  The value of @(':dir') should be a keyword that is associated with
 an absolute directory pathname to be used in place of the current book
 directory (see @(see cbd)) for resolving the first argument of
 @('include-book') to an absolute pathname.  At start-up, the only such keyword
 is @(':system'), so that for example @('(include-book \"arithmetic/top\" :dir
 :system)') will include the book @('\"arithmetic/top\"') under the
 @('\"books/\"') directory of your ACL2 installation.  But you can associate
 ``projects'' with keywords using @(tsee add-include-book-dir), e.g.,
 @('(add-include-book-dir :my-project \"/u/smith/project0/\")').  See @(see
 add-include-book-dir) and also see @(see delete-include-book-dir) and see
 @(see include-book).  Note: You will probably not find @(':dir :system') to be
 useful if the distributed books are not placed in the path of their original
 location, pointed to by @(':dir :system'), which will often happen if the
 executable image is obtained from another site.  Also see @(see include-book),
 in particular its ``soundness warning''.</p>

 <p>The printing of results in raw mode (see @(see set-raw-mode)) may now be
 partially controlled by the user: see @(see add-raw-arity).  Also, newlines
 are printed when necessary before the value is printed.</p>

 <p>For those using Unix/Linux `make': A @('cert.acl2') file can contain forms
 to be evaluated before an appropriate @(tsee certify-book) command is invoked
 automatically (not included in @('cert.acl2')).</p>

 <p>Jared Davis has contributed a new set of books for ordered finite set
 theory to the standard distribution, @('books/finite-set-theory/osets-0.81/').
 See the @('README') file in that directory.  Thanks, Jared.</p>

 <p>Robert Krug has contributed two related changes (thanks, Robert!) in
 support of stronger arithmetic reasoning.  First, one can now enable and
 disable nonlinear arithmetic with a @(':nonlinearp') hint, which will override
 the default provided by @(tsee set-non-linearp) (initially, @('nil')).  See
 @(see hints).  Second, @(see computed-hints) can now have access to the
 @('HISTORY'), @('PSPV'), and @('CTX') variables of the waterfall, which (for
 example) allows the writing of a hint which will enable nonlinear arithmetic
 on precisely those goals that are @('stable-under-simplificationp').  See
 @(see computed-hints).</p>

 <p>Robert Krug has contributed a new set of arithmetic books to the standard
 distribution, @('books/arithmetic-3/').  See the @('README') file in that
 directory.  Thanks, Robert.</p>")

(defxdoc note-2-8-ordinals
  :parents (note-2-8)
  :short "ACL2 Version  2.8 Notes on Changes to the Ordinals"
  :long "<p>Please see @(see ordinals).</p>")

(defxdoc note-2-8-other

; Changed ev-fncall, ev, etc. so that we could have versions that take the
; world (see note below about user-defined-functions-table).

; Used memoization to speed up global-symbol and *1*-symbol by avoiding string
; concatenation.

; Eliminated all-new-flg/all-new-flag from the following, as it always had
; value nil (Robert Krug agrees with this change).
;   new-vars-in-pot-lst (formerly arg 3)
;   expanded-new-vars-in-pot-lst (formerly arg 3)
;   add-polys-and-lemmas1-nl (formerly arg 2)
;   add-polys-and-lemmas (formerly arg 2)
;   add-disjunct-polys-and-lemmas (formerly arg 3)
;   add-disjuncts-polys-and-lemmas (formerly arg 2)
;   add-terms-and-lemmas (formerly arg 4)

  :parents (note-2-8)
  :short "ACL2 Version  2.8 Notes on Miscellaneous Changes"
  :long "<p>Execution of @(tsee table) events has been sped up in many cases by
 avoiding excessive consing.</p>

 <p>ACL2 now warns if @(':')@(tsee rewrite) (or @(':')@(tsee definition)) rules
 contain free variables on the right-hand side.  Thanks to Dave Greve for
 raising this issue.</p>

 <p>Emacs file @('emacs/emacs-acl2.el') has been updated to better comprehend
 the notion of the ``ACL2 shell'', which is the buffer to which ACL2 forms are
 written by commands defined in the above file.  Thus, command @('control-t e')
 has been modified always to write to the ACL2 shell (which is @('\"*shell*\"')
 by default), and the following new commands have been defined.</p>

 <blockquote><p>o control-t c<br></br>

   Set the ACL2 shell to the current buffer.
 o control-t b<br></br>

   Change to the ACL2 shell.</p></blockquote>

 <p>The commands @(':')@(tsee pl) and @(':')@(tsee pr) may now be given a macro
 name that corresponds via the @('macro-aliases-table') to a function name, so
 that for example @(':pl append') is treated the same as @(':pl
 binary-append').  A more interesting improvement, for @(':pl') only, is that
 @(':pl') may now take any term.  When @(':pl') is given a term other than a
 symbol, it will print all rewrite rules that match that term.  Thanks to David
 Russinoff, Robert Krug, and Bill Legato for getting this going.</p>

 <p>A new function, @(tsee pkg-witness), returns a symbol in the given
 package.</p>

 <p>The installation instructions have been updated, for example to give more
 guidance on obtaining Lisp implementations and to mention the acl2-help
 mailing list.</p>

 <p>Jared Davis has suggested some symbols to be added to @('*acl2-exports*'),
 and we have done so.  Thanks, Jared.</p>

 <blockquote><p>o @('MFC') (used in @(tsee syntaxp) and @(tsee
 extended-metafunctions); thanks also to Robert Krug for this one) o @('ID'),
 @('CLAUSE'), @('WORLD'), and @('STABLE-UNDER-SIMPLIFICATIONP') (used in @(tsee
 computed-hints)) o @(tsee SET-DEFAULT-HINTS)</p></blockquote>

 <p>The command @(':')@(tsee pe) has been improved so that when the event is
 inside an included book, the path of included books (from the top-level book
 down to the one containing the event) is shown.  Thanks to Eric Smith (perhaps
 among others) for pointing out the utility of this improvement.</p>

 <p>A new release of the rtl library has been included: @('books/rtl/rel4/').
 See the @('README') file in that directory.</p>")

(defxdoc note-2-8-proof-builder
  :parents (note-2-8)
  :short "ACL2 Version  2.8 Notes on proof-builder Changes"
  :long "<p>Added new @(see proof-builder) commands @('wrap1'), @('wrap'), and
 @('wrap-induct').  @('Wrap') replaces multiple goals by their conjunction:
 @('(wrap instr1 instr2 ...)') employs @('wrap1') so that the indicated
 instructions create only at most one new goal.  @('Wrap-induct') is a simple
 example of the use of @('wrap'), so that induction creates only one goal (the
 conjunction of the base and induction steps).  @('Wrap1') can be used
 immediately after a prover call (@('bash'), @('prove'), @('reduce'), @('bdd'),
 or @('induct')) to collapse the new goals into one.  See @(see
 proof-builder-commands).</p>

 <p>The @(see proof-builder) command @('=') failed to work as expected when a
 governing @('IF')-test of the current term is T.  This has been fixed (by
 fixing source function @('conjuncts-of')).  Thanks to Yoann Padioleau for
 bringing this problem to our attention.</p>

 <p>The @('type-alist') command now takes optional arguments that control
 whether or not the governors and/or conclusion are used in computing the
 context that is printed (see @(see proof-builder-commands), specifically
 subtopic @('type-alist')).  Thanks to Rob Sumners for suggesting this
 improvement.</p>

 <p>The macro @(tsee toggle-pc-macro) has always taken an optional second
 argument of @('atomic-macro') or @('macro').  However, this was not clearly
 documented, and those two symbols had to be in the @('ACL2') package.  Both of
 these problems have been remedied.  Thanks to John Erickson for bringing the
 lack of documentation of the second argument to our attention.</p>")

(defxdoc note-2-8-proofs
  :parents (note-2-8)
  :short "ACL2 Version  2.8 Notes on Changes in Proof Engine"
  :long "<p>ACL2 now prevents certain rewriting loops; see @(see
 rewrite-stack-limit).</p>

 <p>During the computation of @(tsee constraint)s for functional instantiation,
 @('(prog2$ term1 term2)') and @('(the type term2)') are now treated as
 @('term2').</p>

 <p>A change has been made in heuristics for controlling rewriting during
 proofs by induction.  Formerly, during induction proofs, ACL2 suppressed
 rewriting of certain ``induction hypothesis'' terms, and forced expansion of
 certain ``induction conclusion'' terms, until rewriting had stabilized.  This
 meddling with the rewriter is still turned off when rewriting has stabilized,
 but it is now turned off earlier once an ancestor has been through the
 rewriter and the current goal is free of ``induction conclusion'' terms.
 Thanks to Dave Greve and Matt Wilding for providing an example and associated
 analysis that led us to look for a heuristic modification.</p>

 <p>A change has been made in the heuristics for handling certain ``weak''
 @(see compound-recognizer) rules when building contexts.  Those who want to
 dig deeply into this change are welcome to look at the code following the call
 of @('most-recent-enabled-recog-tuple') in the code for function
 @('assume-true-false') in the ACL2 sources.</p>

 <p>The handling of free variables in a hypothesis of a @(see rewrite) rule
 (see @(see free-variables)) has been improved in the case that the hypothesis
 is of the form @('(equiv x y)'), where @('equiv') is a known equivalence
 relation (see @(see equivalence)).  Previously, if the rewriter was attempting
 to rewrite the hypothesis @('(equiv x y)') of a rewrite rule, in a context
 where @('x'') is an instance of @('x'), then the rewriter could fail to notice
 a term <tt>(equiv x' y')</tt> true in the current context where @('y'') is an
 instance of @('y'), in the case that @('x'') precedes @('y'') in the @(tsee
 term-order).  This has been remedied.  This improvement applies regardless of
 whether @('x'), @('y'), or (we believe) both are already fully instantiated in
 the present context.  Thanks to Joe Hendrix for bringing up an example and to
 Vernon Austel for providing another, simple example.</p>

 <p>A very minor change has been made to the rewriter in the case that an
 equality appears on the left-hand side of a @(':')@(tsee rewrite) rule.
 Formerly, when such an equality @('(equal x y)') was commuted to @('(equal y
 x)') in order for the rule to match the current term, then all equalities on
 the instantiated right-hand side of the rule were commuted, except for those
 occurring inside another equality.  The instantiated right-hand side is no
 longer modified.  It seems very unlikely that this change will cause proofs to
 fail, though we cannot completely rule out that possibility.</p>

 <p>We have modified how the ACL2 simplifier handles the application of a
 defined function symbol to constant arguments in certain cases, which we now
 describe.  As before, ACL2 attempts to simplify such a function application by
 evaluation, provided the @(':')@(tsee executable-counterpart) of the function
 is enabled.  And as before, if that evaluation fails due to a subroutine call
 of a constrained function (introduced by @(tsee encapsulate)), ACL2 may wrap a
 call of @('hide') around this function application.  (See @(see hide).)  But
 now, ACL2 attempts to apply definitions and rewrite rules in the case that
 this evaluation fails, and only if the resulting term is unchanged does ACL2
 wrap @(tsee hide) around this function application.  Thanks to Matt Wilding
 for bringing up the idea of this modification.</p>

 <p>The generation of \"Goal\" for recursive (and mutually-recursive)
 definitions now uses the subsumption/replacement limitation (default 500).
 See @(see case-split-limitations).</p>

 <p>Default hints now apply to hints given in definitions, not just theorems.
 See @(see default-hints).</p>

 <p>Thanks to Robert Krug for implementing the following two improvements
 involving linear arithmetic reasoning: linear arithmetic now uses the
 conclusions of @(tsee forward-chaining) rules, and @(tsee type-set) now uses a
 small amount of linear reasoning when deciding inequalities.</p>")

(defxdoc note-2-8-rules
  :parents (note-2-8)
  :short "ACL2 Version  2.8 Notes on Changes in Rules, Definitions, and Constants"
  :long "<p>The @(see theory) @(tsee minimal-theory) has been changed by adding
 the @(see definition) @(see rune) for @(tsee mv-nth) to the theory.  A
 corresponding change has been made to the theory warning mechanism, which was
 failing to warn if the definition of @('mv-nth') is disabled, even though
 calls of @('mv-nth') can be expanded by special-purpose code in the rewriter.
 Thanks to Serita Van Groningen for pointing out this problem with the theory
 warning mechanism.</p>

 <p>The @(tsee defevaluator) event has been modified so that in the body of the
 evaluator function, to add a new case @('(ATOM X)') (returning @('nil')) has
 been inserted immediately after the case @('(EQ (CAR X) 'QUOTE)').  This is a
 no-op semantically but may speed up proofs.  Thanks to Warren Hunt for
 suggesting this change.</p>

 <p>A new form of @(':')@(tsee compound-recognizer) rule is now allowed:</p>

 @({
  (if (fn x) concl1 concl2)
 })

 <p>This is equivalent to an existing form:</p>

 @({
  (and (implies (fn x) concl1)
       (implies (not (fn x)) concl2))
 })

 <p>Thanks to Josh Purinton for bringing this to our attention.</p>

 <p>Rewrite rules @('realpart-+') and @('imagpart-+') have been added in order
 to simplify the @(tsee realpart) and @(tsee imagpart) (respectively) of a sum.
 They follow from a theorem @('add-def-complex') that equates a sum with the
 complex number formed by adding real and imaginary parts.  All three of these
 theorems may be found in source file @('axioms.lisp').  Thanks to Eric Smith
 for raising a question leading to these additions, as well as to Joe Hendrix
 and Vernon Austel for helpful suggestions.</p>")

(defxdoc note-2-8-system

; Modified compile-uncompiled-defuns/compile-uncompiled-*1*-defuns to write
; comment to the top of TMP.lisp/TMP1.lisp saying that file can be deleted.
; (Matyas Sustik had asked about these files.)

  :parents (note-2-8)
  :short "ACL2 Version  2.8 Notes on System-level Changes"
  :long "<p>ACL2 now runs on OpenMCL, ``an opensourced Common Lisp
 implementation, derived from Digitool's Macintosh Common Lisp product.''
 Thanks to Greg Wright and Robert Krug for doing most of the work for this
 port.</p>

 <p>When @('(')@(tsee LP)@(')') is first executed, the underlying raw Lisp
 package will change to @('\"ACL2\"') (if that is not already the current
 package in raw Lisp).  This is a minor change that will probably not be
 noticed, since up to now it has probably been the case that the ACL2
 executable starts up with @('\"ACL2\"') as the underlying raw Lisp package.
 But this change was made because we have been informed that ACL2 executables
 based on OpenMCL need not start up with @('\"ACL2\"') as the underlying raw
 Lisp package.</p>

 <p>ACL2 now runs on MCL 5.0.  Thanks to Pascal Costanza for updates to the
 instructions in file @('mcl-acl2-startup.lisp') and for an update to the ACL2
 sources (parameter @('*compiled-file-extension*')).</p>")

(defxdoc note-2-9

; BUG FIXES:
; Example for the soundness bug involving *1* package names:

; ------------------------------ sub.lisp ------------------------------
;
; #|
; (defpkg "ACL2_*1*_MYPKG" ())
; (certify-book "sub" 1)
; |#
;
; (in-package "ACL2_*1*_MYPKG")
;
; (acl2::defun foo (x)
;              (acl2::declare (acl2::xargs :verify-guards acl2::t))
;              x)
;
; ------------------------------ top.lisp ------------------------------
;
; #|
; (include-book "sub")
; (defpkg "MYPKG" ())
; (certify-book "top" 2)
; |#
;
; (in-package "ACL2")
;
; (defthm lemma1
;   (equal (acl2_*1*_mypkg::foo 3) 3)
;   :rule-classes nil)
;
; (defun mypkg::foo (x)
;   (cons x x))
;
; (defthm lemma2
;   (equal (acl2_*1*_mypkg::foo 3) '(3 . 3))
;   :rule-classes nil)
;
; (defthm ouch
;   nil
;   :rule-classes nil
;   :hints (("Goal" :use (lemma1 lemma2))))

; End of example related to *1* package names.

; Example related to soundness bug on local and redundancy checking:

; (encapsulate
;  ()
;  (defun foo (x)
;    (declare (xargs :mode :program))
;    (zp x))
;  (local (verify-termination foo))
;  (defun bar (x)
;    (foo x))
;  (defthm thm-1
;    (bar -1)
;    :rule-classes nil))
;
; (defthm thm-2
;   (not (bar -1))
;   :rule-classes nil)
;
; (defthm bad
;   nil
;   :rule-classes nil
;   :hints (("Goal" :use (thm-1 thm-2))))

; Here's a related example, showing how to get a world where a
; :common-lisp-compliant function, bar, calls an :ideal function, foo.

; ------------------------------ abc.lisp ------------------------------
;
; (in-package "ACL2")
;
; (defun foo (x)
;   (declare (xargs :guard (consp x)))
;   (car x))
;
; ------------------------------ abc-top.lisp ------------------------------
;
; (in-package "ACL2")
;
; (local (include-book "abc"))
;
; (defun foo (x)
;   (declare (xargs :guard (consp x) :verify-guards nil))
;   (car x))
;
; (defun bar (x)
;   (declare (xargs :guard (consp x)))
;   (foo x))

; End of example related to soundness bug on local and redundancy checking.

; Example related to soundness bug pertaining to safe-mode.

; ------------------------------ bad1.lisp ------------------------------
;
; (in-package "ACL2")
;
; (defconst *c* '(((a b))))
;
; (defconst *d* *c*)
;
; (defmacro bad-macro ()
;   (list 'quote (union-eq-cars (list *c* *d*))))
;
; (defthm thm1
;   (equal (bad-macro)
;          '((a b)))
;   :rule-classes nil)
;
; ------------------------------ bad2.lisp ------------------------------
;
; (in-package "ACL2")
;
; (defconst *c* '(((a b))))
;
; (defconst *d* '(((a b))))
;
; (defmacro bad-macro ()
;   (list 'quote (union-eq-cars (list *c* *d*))))
;
; (defthm thm2
;   (equal (bad-macro)
;          '((a b) (a b)))
;   :rule-classes nil)
;
; ------------------------------ bad.lisp ------------------------------
;
; (in-package "ACL2")
;
; (include-book "bad1" :load-compiled-file nil)
;
; (include-book "bad2" :load-compiled-file nil)
;
; (defthm ouch
;   nil
;   :hints (("Goal" :use (thm1 thm2)))
;   :rule-classes nil)
;
; ----------------------------------------------------------------------

; End of example related to soundness bug pertaining to safe-mode.

  :parents (release-notes)
  :short "ACL2 Version  2.9 (October, 2004) Notes"
  :long "<h3>Table of Contents</h3>
 <ul>
 <li>BUG FIXES</li>
 <li>NEW FUNCTIONALITY</li>
 <li>CHANGES IN PROOF ENGINE</li>
 <li>GUARD-RELATED CHANGES</li>
 <li>PROOF-BUILDER CHANGES</li>
 <li>SYSTEM-LEVEL CHANGES</li>
 <li>BOOK CHANGES</li>
 <li>MISCELLANEOUS CHANGES</li>
 </ul>

 <p><b>BUG FIXES.</b></p>

 <p>We fixed a soundness bug due to a conflict between user-supplied package
 names and internal package names (obtained by prepending a Lisp constant,
 @('*1*-package-prefix*')) and user-supplied package names.  For example, the
 form @('(defpkg \"ACL2_*1*_MYPKG\" ())') is no longer legal.  Thanks to Robert
 Krug for asking a question that led directly to the discovery of this bug.</p>

 <p>We fixed a soundness bug that allows @(':')@(tsee logic) mode functions to
 call @(':')@(tsee program) mode functions.  The fix furthermore prevents
 functions with @(see guard)s verified from calling functions with guards not
 verified.  We had thought we already prevented all this, but there was a
 problem with the interaction of @(tsee local) definitions and redundancy
 checking (see @(see redundant-events)).</p>

 <p>We fixed a soundness bug that could occur when built-in functions were
 called during macroexpansion (a hole in so-called ``safe-mode'').</p>

 <p>Fixed a minor bug in system functions @('genvar1') and @('genvar'), where
 @(tsee eq) had been used in place of @(tsee eql).  This bug was discovered
 during the plugging of a hole in safe-mode, mentioned just above.</p>

 <p>We fixed handling of the @(':inline') keyword for @(tsee defstobj), which
 previously could cause raw Lisp errors in OpenMCL and CMU Common Lisp.  Thanks
 to John Matthews for bringing this issue to our attention.</p>

 <p>Calls of @(tsee include-book) could result in a state for which some
 function definitions were not compiled that should have been.  The result
 could be performance degradation or even stack overflows.  This situation
 could arise in the following two ways.</p>

 <blockquote>

 <p>o Inclusion of a book with an absolute pathname that differs from the
 absolute pathname at certification time, presumably because of the use of soft
 links.  Thanks to Bob Boyer and Warren Hunt for bringing a stack overflow to
 our attention that led us to this fix.</p>

 <p>o Large @(tsee mutual-recursion) nests (more than 20 functions) are
 executed in a superior book.</p>

 </blockquote>

 <p>We fixed some performance bugs that can increase the speed of @(tsee
 include-book) calls by a factor of close to 2.  Thanks to Eric Smith for
 asking if we could speed up @(tsee include-book) processing; we have done so
 in the past, but primarily focusing on large @(tsee mutual-recursion) nests
 (which have nothing in particular to do with the current improvements).  Also,
 thanks to Rob Sumners for a very useful remark early in the process that kept
 us from drawing an incorrect conclusion at that point.</p>

 <p>We fixed @(':')@(tsee pl) so that it can be run on a form that returns
 multiple values, which it could not do previously.  Thanks to Eric Smith for
 pointing out this problem.</p>

 <p>Fixed a bug in the Allegro ACL2 trace utility (see @(see trace$)) that was
 causing ``@('10>')'' to be printed as ``@('9>')'', ``@('11>')'' to be printed
 as ``@('10 >')'', ``@('12>')'' to be printed as ``@('11 >')'', and so on.</p>

 <p>Fixed a @(see proof-builder) bug that was preventing the use of the @('DV')
 command (or a numerical command) on @(tsee let) expressions.  Thanks to Bill
 Young for pointing out this problem.</p>

 <p>Fixed a bug in a comment on how to set @('ACL2_BOOKS_DIR') in the makefile.
 Thanks to Dave Greve for pointing out this problem.</p>

 <p>Fixed a potential soundness bug in the linear arithmetic routines.  Thanks
 to Jared Davis for noticing this problem and to Robert Krug for implementing
 the fix.  (Technical details: We had been assuming that polynomials were being
 normalized &mdash; see the definition of good-polyp in linear-a.lisp &mdash;
 but this assumption was false.)</p>

 <p>When the macro @(tsee open-trace-file) is opened twice in succession, it
 now automatically closes the first trace output channel before opening
 another.</p>

 <p>It is now possible to use `make' to build ACL2 on Windows systems that
 support `make'.  Thanks to Pete Manolios and Mike Thomas for pointing out the
 problem, to Jared Davis and Mike for helping us to analyze the problem, and to
 Jared for testing the fix.</p>

 <p>Fixed a bug in the @(see guard) of @(tsee with-output) that was causing a
 needless guard violation.</p>

 <p><b>NEW FUNCTIONALITY.</b></p>

 <p>The new events @(tsee add-default-hints) and @(tsee remove-default-hints)
 allow one to append to or subtract from the current list of default hints.
 The event @(tsee set-default-hints) continues to set the list of default
 hints, discarding the previous value of the @(tsee default-hints).  Note that
 @(tsee set-default-hints) is still @(tsee local) to the @(tsee encapsulate) or
 book in which it occurs, and @(tsee add-default-hints) has the same property,
 although neither is implemented any longer using the @(tsee
 acl2-defaults-table).  New events @(tsee add-default-hints!), @(tsee
 remove-default-hints!), and @(tsee set-default-hints!) are the same as @(tsee
 add-default-hints), @(tsee remove-default-hints), and @(tsee
 set-default-hints), respectively, except that the former three events are not
 @(tsee local) to their enclosing @(tsee encapsulate) or book.  Thanks to Jared
 Davis for suggesting these enhancements.</p>

 <p>OpenMCL's tracing routines have been modified in a similar manner as those
 of Allegro CL.  Thanks to Robert Krug for providing this enhancement.</p>

 <p>Guard-checking can now be caused to happen on recursive calls.  See
 ``GUARD-RELATED CHANGES'' below for details.</p>

 <p>Advanced users can now inhibit compilation of so-called ``*1* functions''
 with the @(':comp') command; see @(see comp).  Thanks to Rob Sumners for
 suggesting this enhancement.</p>

 <p>Added new legal argument @('hard?') for the @(tsee er) macro, which is now
 documented.  See @(see er).  Thanks to Rob Sumners for a discussion leading to
 this change.  Also, the three legal first arguments to @(tsee er) &mdash;
 @('hard'), @('hard?'), and @('soft') &mdash; may now be in any package (thanks
 to Jared Davis for bringing this issue to our attention).</p>

 <p>We have removed the requirement that for a rule's hypothesis @('(bind-free
 term var-list)'), at least one variable must occur free in @('term').  For
 example, the expression @('(bind-free (bind-divisor a b) (x))') was legal
 because @('a') and @('b') occur free in @('(bind-divisor a b)'); but
 @('(bind-free (foo (bar)) (x))') was not legal.  The latter is no longer
 disallowed. (Technical note: this allows @(tsee bind-free) to be used to
 create explicit substitutions in metafunction hypotheses.)</p>

 <p>The following two enhancements have been implemented for rules of class
 @(':')@(tsee meta).  Thanks to Eric Smith for requesting more control of
 reasoning with @(':')@(tsee meta) rules, which led to these enhancements, and
 to him and Robert Krug for helpful discussions.</p>

 <blockquote>

 <p>o It is now possible to control backchaining in rules of class @(':')@(tsee
 meta) by providing a @(':backchain-limit-lst') argument, as was already
 allowed for rules of class @(':')@(tsee rewrite) and @(':')@(tsee linear).
 See @(see rule-classes).  However, unlike those other two rule classes, the
 value for @(':backchain-limit-lst') is prohibited from being a non-empty list;
 it must be either @('nil') or a non-negative integer.</p>

 <p>o (For advanced users.) It is now legal for hypothesis metafunctions to
 generate, in essence, calls of @(tsee syntaxp) and @(tsee bind-free), handled
 essentially as they are handled in hypotheses of @(':')@(tsee rewrite) and
 @(':')@(tsee linear) rules.  We say ``essentially'' primarily because both
 @(tsee syntaxp) and @(tsee bind-free) are actually macros, but hypothesis
 metafunctions must generate translated terms (see @(see term)).  The
 enterprising advanced user can call @(':')@(tsee trans) to see examples of
 translated terms corresponding to calls of @(tsee syntaxp) and @(tsee
 bind-free).</p>

 </blockquote>

 <p>A new command @(':')@(tsee trans!) has been added, which is like
 @(':')@(tsee trans) except that @(':')@(tsee trans!) ignored issues of
 single-threadedness.  See @(see trans!).  Thanks to Eric Smith for suggesting
 this addition.</p>

 <p>The @(':')@(tsee pf) command now works when the argument is the name of a
 macro associated with a function by @(see macro-aliases-table).</p>

 <p><b>CHANGES IN PROOF ENGINE.</b></p>

 <p>The simplifier has been changed slightly in order to avoid using @(see
 forward-chaining) facts derived from a literal (essentially, a top-level
 hypothesis or conclusion) that has been rewritten.  As a practical matter,
 this may mean that the user should not expect forward-chaining to take place
 on a term that can be rewritten for any reason (generally function expansion
 or application of rewrite rules).  Formerly, the restriction was less severe:
 forward-chaining facts from a hypothesis could be used as long as the
 hypothesis was not rewritten to @('t').  Thanks to Art Flatau for providing an
 example that led us to make this change; see the comments in source function
 @('rewrite-clause') for details.</p>

 <p>The rewriter has been modified to work slightly harder in relieving
 hypotheses.  Thanks to Eric Smith for providing an example that inspired the
 following, which illustrates the issue.  Suppose we introduce functions
 @('foo') and @('bar') with the (non-@(tsee local)) properties shown below.</p>

 @({
   (encapsulate
    (((foo *) => *)
     ((bar *) => *))

    (local (defun foo (x) (declare (ignore x)) t))
    (local (defun bar (x) (declare (ignore x)) t))

    (defthm foo-holds
      (implies x
               (equal (foo x) t)))
    (defthm bar-holds-propositionally
      (iff (bar x) t)))
 })

 <p>Consider what happens when ACL2's rewriter is used to prove the following
 theorem.</p>

 @({
  (thm (foo (bar y)))
 })

 <p>With ACL2's inside-out rewriting, @('(bar y)') is first considered, but
 rewrite rule @('bar-holds-propositionally') does not apply because the context
 requires preserving equality, not mere Boolean (@('iff')) equivalence.  Then
 the rewriter moves its attention outward and sees the term @('(foo (bar y))').
 It attempts to apply the rule @('foo-holds'), in a context created by binding
 its variable @('x') to the term @('(bar y)').  It then attempts to relieve the
 hypothesis @('x') of rule @('foo-holds') in that context.  Before this change,
 ACL2 basically assumed that since rewriting was inside out, then @('(bar y)')
 had already been rewritten as much as possible, so the rewrite of @('x') in
 the aforementioned context (binding @('x') to @('(bar y)')) simply returned
 @('(bar y)'), and the attempt to relieve the hypothesis of @('foo-holds')
 failed.  The change is essentially for ACL2's rewriter to make a second pass
 through the rewriter when the attempt fails to rewrite a variable to @('t'),
 this time using the fact that we are in a Boolean context.  (We mention that
 source function @('rewrite-solidify-plus') implements this idea, for those who
 want to dig deeply into this issue.)  In our example, that means that the
 rewriter considers @('(bar y)') in a Boolean context, where it may apply the
 rule @('bar-holds-propositionally') to relieve the hypothesis
 successfully.</p>

 <p>When @('(')@(tsee set-non-linearp)@(' t)') has been executed, @(see
 non-linear-arithmetic) can now be applied in some cases for which it
 previously was not.  Thanks to Robert Krug for supplying this modification and
 to Julien Schmaltz for providing a motivating example.</p>

 <p>We modified the rewriter to avoid certain infinite loops caused by an
 interaction of the opening of recursive functions with equality reasoning.
 (This change is documented in detail in the source code, in particular
 functions @('rewrite-fncall') and @('fnstack-term-member').)  Thanks to Fares
 Fraij for sending us an example that led us to make this change.</p>

 <p>The @(':')@(tsee executable-counterpart) of function @(tsee hide) is now
 disabled when ACL2 starts up.  This removes an anomaly, for example that</p>

 @({
  (thm (not (equal 1 (* (hide 0) a))))
 })

 <p>succeeded while</p>

 @({
  (thm (equal (foo (equal 1 (* (hide 0) a))) (foo nil)))
 })

 <p>failed.  Now both fail.</p>

 <p>The theory @('*s-prop-theory*') is no longer used by the
 <i>proof-builder</i>; it has been replaced by @('(theory '')@(tsee
 minimal-theory).  We have left the constant @('*s-prop-theory*') defined in
 the source code in support of existing books, however.  This change eliminates
 annoying theory warnings printed upon invocation of @(see proof-builder)
 commands @('s-prop'), @('sl'), and @('split').</p>

 <p>Terms are now kept in an internal form that avoids calls of primitive
 functions (built-ins without explicit definitions; see code for @('cons-term')
 for details), in favor of the constants that result from evaluating those
 calls.  So for example, the internal form for @('(cons 1 2)') is @('(quote (1
 . 2))').  This change was made at around the same time as changes in support
 of @(tsee bind-free); see above.  One consequence is that the splitting of
 goals into cases (technically, source function @('clausify') and even more
 technically, source function @('call-stack')) has been modified, which can
 cause subgoal numbers to change.</p>

 <p><b>GUARD-RELATED CHANGES.</b></p>

 <p>Guard-checking can now be caused to happen on recursive calls, where this
 was formerly not the case for @(':')@(tsee program) mode functions and,
 perhaps more important, for @(':')@(tsee logic) mode functions whose @(see
 guard)s have not been verified.  Moreover, a warning is printed when ACL2 does
 not rule out the exclusion of guard-checking on recursive calls.  See @(see
 set-guard-checking).  Thanks to David Rager for bringing this issue to our
 attention, and to Rob Sumners and the Univ. of Texas ACL2 seminar in general
 for their feedback.</p>

 <p>Guard violations are reported with less of the offending term hidden.
 Thanks to Jared Davis for suggesting that we look at this issue.</p>

 <p><b>PROOF-BUILDER CHANGES.</b></p>

 <p>We fixed the @(see proof-builder) so that diving works as you might expect
 for a macro call @('(op a b c)') representing @('(binary-op a (binary-op b
 c))').  In the past, if the current term was of the form @('(append t1 t2
 t3)'), then @('(DV 3)') (and @('3')) would dive to @('t3') even though the
 corresponding function call is @('(binary-append t1 (binary-append t2 t3))').
 This is still the case, but now this behavior holds for any macro associated
 with a function in @('binop-table') (see @(see add-binop)).  Moreover, users
 can now write customized diving functions; see @(see dive-into-macros-table),
 and also see @('books/misc/rtl-untranslate.lisp') for example calls to @(tsee
 add-dive-into-macro).  Of course, the old behavior can still be obtained using
 the @(see proof-builder)'s @('DIVE') command; see @(see
 proof-builder-commands).</p>

 <p>The @('runes') command in the @(see proof-builder) now shows only the @(see
 rune)s used by the most recent primitive or macro command (as shown by
 @(':comm')), unless it is given a non-@('nil') argument.  Also, @(see
 proof-builder) command @('lemmas-used') has been added as, in essence, an
 alias for @('runes').</p>

 <p>(The following two items are also mentioned above under ``BUG FIXES.'')</p>

 <p>Fixed a @(see proof-builder) bug that was preventing the use of the @('DV')
 command (or a numerical command) on @(tsee let) expressions.  Thanks to Bill
 Young for pointing out this problem.</p>

 <p>The theory @('*s-prop-theory*') is no longer used by the
 <i>proof-builder</i>; it has been replaced by @('(theory '')@(tsee
 minimal-theory).  We have left the constant @('*s-prop-theory*') defined in
 the source code in support of existing books, however.  This change eliminates
 annoying theory warnings printed upon invocation of @(see proof-builder)
 commands @('s-prop'), @('sl'), and @('split').</p>

 <p><b>SYSTEM-LEVEL CHANGES.</b></p>

 <p>Fixed a problem with building ACL2 on CMUCL in some systems (source
 function @('save-acl2-in-cmulisp')).  Thanks to Bill Pase for bringing this to
 our attention.</p>

 <p>The installation instructions have been extended to include instructions
 for building on GCL in Mac OS X.  Thanks to Jun Sawada and Camm Maguire.</p>

 <p>Initial pre-allocation of space has been updated for GCL to reflect more
 current GCL executables (we considered GCL 2.6.1-38).  This can help avoid
 running out of memory for large ACL2 sessions.</p>

 <p>The main @('Makefile') has been replaced by @('GNUmakefile'), in order to
 enforce the use of GNU `make'.  If you use another `make' program, you'll get
 an error message that may help you proceed.</p>

 <p>(GCL only) SGC is no longer turned on for GCL 2.6 sub-versions through
 2.6.3 if @('si::*optimize-maximum-pages*') is bound to @('T'), due to an
 apparent issue with their interaction in those sub-versions.  Also, we have
 eliminated preallocation for all versions after 2.6.1 because GCL doesn't need
 it (comments are in source function @('save-acl2-in-akcl')).  Thanks to Camm
 Maguire for excellent GCL help and guidance, and to Camm and Bob Boyer for
 useful discussions.</p>

 <p>We have removed support for so-called ``small'' images.  Thus, @(':')@(tsee
 doc), @(':')@(tsee pe) and @(':')@(tsee pc), @(tsee verify-termination), and
 other commands are fully supported in ACL2 saved images.  Because of this and
 other changes in the generation of the so-called ``*1*'' logical functions,
 related to guards (as described above in -GUARD-RELATED CHANGES'', and related
 to the discussion of safe-mode in ``BUG FIXES'' above), image sizes have
 increased substantially.</p>

 <p>We no longer @('time') or run ``@('nice')'' the certification of individual
 books.  The file @('books/Makefile-generic') had done these by default, and
 some individual distributed and workshop book directories had @('Makefile')s
 that did so as well.  Thanks to Mike Thomas, who pointed out the lack of
 @('nice') on some Windows systems (and we decided on this simple solution).
 Overall targets in @('books/Makefile') still @('time') their runs by default,
 and the particular @('time') program is now controlled by a @('Makefile')
 variable.</p>

 <p>Failures during @('make certify-books') or @('make regression') now show up
 in the log as ``@('**CERTIFICATION FAILED**')'', regardless of the operating
 system (as long as it supports `make').  Formerly, one searched for
 ``@('**')'' but this did not appear in openMCL runs.</p>

 <p>We have eliminated ``Undefined function'' warnings that could occur in
 OpenMCL.</p>

 <p><b>BOOK CHANGES.</b></p>

 <p>Reconciled the definitions of @('firstn') in @('book/misc/csort.lisp'),
 @('books/bdd/bdd-primitives.lisp'),
 @('books/ordinals/ordinal-definitions.lisp'), and
 @('books/data-structures/list-defuns.lisp').  Thanks to Ray Richards for
 bringing this issue to our attention.</p>

 <p>Distributed book @('books/misc/defpun') now can handle @(see stobj)s where
 it did not previously.  Thanks to John Matthews for bringing this issue to our
 attention.</p>

 <p>The \"make\" variable @('COMPILE_FLG') in file @('books/Makefile-generic')
 formerly only had an effect if there was a @('cert.acl2') file present.  That
 oversight has been remedied.</p>

 <p>File @('\"books/arithmetic/certify.lsp\"') was missing a @(tsee
 certify-book) command for @('\"natp-posp\"').  Thanks to John Cowles for
 noticing this deficiency and supplying a fix.  (This file is of use to those
 who want to certify the @('\"books/arithmetic/\"') books without using
 @('\"make\"').)</p>

 <p>A few small changes have been made to @('\"books/rtl/rel4\"').</p>

 <p>Small changes were made to books @('misc/symbol-btree') and
 @('misc/rtl-untranslate').  In particular, the definition of
 @('symbol-btreep') was strengthened.</p>

 <p>We made a minor fix to @('books/ordinals/e0-ordinal.lisp'), adding
 @('(verify-guards ob+)') and hence @('(verify-guards ocmp)') as well.  This
 was necessitated by the fix prohibiting functions with guards verified from
 calling functions with guards not verified (see also the related discussion
 under ``BUG FIXES'' above).</p>

 <p><b>MISCELLANEOUS CHANGES.</b></p>

 <p>Further sped up processing of large @(tsee mutual-recursion) nests
 (extending what was done for Version_2.7), perhaps by a factor of two in some
 cases.</p>

 <p>As promised in Version_2.5 (see @(see note-2-5)), structured pathnames are
 no longer supported.  So for example, the argument to @(tsee include-book)
 must now be a string constant.</p>

 <p>Some documentation has been improved, for @(see stobj)s thanks to
 suggestions by John Matthews and much of the rest thanks to feedback from Eric
 Smith.</p>

 <p>The function @(tsee current-package) is now available to users (it has been
 taken off the list of so-called ``untouchables'').  Thanks to Jared Davis for
 bringing this issue to our attention.</p>

 <p>The documentation for topic @(see using-computed-hints-7) has been
 improved.  Thanks to Doug Harper and Eric Smith for inspiring this
 improvement.</p>

 <p>We added several symbols to @('*acl2-exports*'): @(tsee cw), @(tsee er),
 @(tsee intern$), @(tsee set-case-split-limitations), and @(tsee
 set-difference-eq).  Thanks to Jared Davis for suggesting most of these.</p>

 <p>Now, a @(tsee table) event that sets the value for a key, @('(table tbl key
 val :put)'), is redundant (see @(see redundant-events)) when it does not
 change the value associated with an existing key of the table.  In particular,
 @(tsee define-pc-macro) is now fully redundant when it does not change an
 existing @(see proof-builder) macro-command definition.  Thanks to Bill Young
 for bringing the latter issue to our attention.</p>

 <p>The definitions of unused system functions @('ev-w') and @('ev-w-lst') have
 been deleted.</p>

 <p>ACL2 now prints a warning if a @(tsee defpkg) event introduces a package
 name with lower-case letters, since there is opportunity for later confusion
 in that case.  Thanks to Frederic Peschanski for bringing this problem to our
 attention and Sandip Ray for encouragement.</p>

 <p>ACL2 now works in Version 19 of CMU Common Lisp.</p>

 <p>The function @(tsee sys-call) has been modified so that for ACL2 built on
 Allegro Common Lisp in Unix or Linux, the existing environment is used.
 Thanks to Erik Reeber for bringing this issue to our attention.</p>

 <p>The function @(tsee disabledp) can now be given a macro name that has a
 corresponding function; see @(see macro-aliases-table).  Also, @(tsee
 disabledp) now has a @(see guard) of @('t') but causes a hard error on an
 inappropriate argument.</p>")

(defxdoc |NOTE-2-9(R)|
  :parents (release-notes)
  :short "ACL2 Version  2.9(r) (October, 2004) Notes"
  :long "<p>No changes have been made for support of non-standard analysis,
 other than a minor modification or two in @('books/nonstd/') books.</p>

 <p>Please also see @(see note-2-9) for changes to Version_2.9 of ACL2.</p>")

(defxdoc note-2-9-1

; Changes that are too low-level for the user documentation:

; The name *soundness-related-warning-summaries* has been changed to
; *uninhibited-warning-summaries*, and "Compiled file" has been added to this
; list, along with "Tainted".  When we added "Tainted", we found that a
; "Compiled file" warning could be made without the "Compiled file" showing up
; in the event summary.  That appears to be because we circumvented the basic
; design of warnings in function unfound-compiled-file by locally binding state
; global 'ld-skip-proofsp to nil.

; Here is an example of how to exploit the soundness bug, mentioned below, in
; symbol-package-name.
;
; ++++++++++++++++++++++++++++++ bad-1.lisp ++++++++++++++++++++++++++++++
;
; (in-package "ACL2")
;
; (defthm lemma-1
;   (equal (symbol-package-name (intern (car (cons "X-EQUIV" xxx)) "COMMON-LISP"))
;          "LISP")
;   :rule-classes nil)
;
; ++++++++++++++++++++++++++++++ bad-2.lisp ++++++++++++++++++++++++++++++
;
; (in-package "ACL2")
;
; (defthm lemma-2
;   (equal (symbol-package-name 'COMMON-LISP::X-EQUIV)
;          "COMMON-LISP")
;   :rule-classes nil)
;
; ++++++++++++++++++++++++++++++ bad.lisp ++++++++++++++++++++++++++++++
;
; (in-package "ACL2")
;
; (include-book "bad-1")
;
; (include-book "bad-2")
;
; (defthm bad
;   nil
;   :hints (("Goal" :use lemma-1))
;   :rule-classes nil)
;
; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  :parents (release-notes)
  :short "ACL2 Version  2.9.1 (December, 2004) Notes"
  :long "<p>
 (GCL only) A bug in @(tsee symbol-package-name) has been fixed that could be
 exploited to prove @('nil'), and hence is a soundness bug.  Thanks to Dave
 Greve for sending us an example of a problem with @(tsee defcong) (see below)
 that led us to this discovery.</p>

 <p>ACL2 now warns when @(tsee defcong) specifies @(tsee equal) as the first
 equivalence relation, e.g., @('(defcong equal iff (member x y) 2)').  The
 warning says that the rule has no effect because @(tsee equal) already refines
 all other equivalence relations.  Formerly, this caused an error unless
 @(':event-name') was supplied (see @(see defcong)), and in fact the error was
 a nasty raw Lisp error on GCL platforms due to some mishandling of packages by
 ACL2 that has been fixed (see the paragraph about @(tsee symbol-package-name)
 above).  Thanks to Dave Greve for sending a helpful example in his report of
 this problem.</p>

 <p>(GCL only) The build process was broken for GCL 2.6.0 (and perhaps some
 earlier versions), and has been fixed.  Thanks to Jose Luis Ruiz-Reina for
 bringing this problem to our attention.</p>

 <p>(GCL only) We have increased the hole size to at least 20% of max-pages,
 which may eliminate some garbage collection at the expense of larger virtual
 memory (not larger resident memory or larger image).  Thanks to Camm Maguire
 for helpful explanations on this topic.</p>

 <p>We have clarified the @(see guard) warning message that is printed during
 evaluation of recursively-defined functions whose @(see guard)s have not been
 verified, for example:</p>

 @({
    ACL2 Warning [Guards] in TOP-LEVEL:  Guard-checking may be inhibited
    on some recursive calls of executable counterparts (i.e., in the ACL2
    logic), including perhaps EVENLP.  To check guards on all recursive
    calls:
      (set-guard-checking :all)
    To leave behavior unchanged except for inhibiting this message:
      (set-guard-checking :nowarn)
 })

 <p>And, ACL2 no longer prints that message when the @(see guard) was
 unspecified for the function or was specified as @('T').  Thanks to Serita
 Nelesen for bringing the latter issue to our attention.  Finally, ACL2 now
 prints such a warning at most once during the evaluation of any top-level
 form; thanks to Bill Young for pointing out this issue.</p>

 <p>The function @(tsee verbose-pstack) has been enhanced to allow specified
 prover functions <b>not</b> to be traced.  See @(see verbose-pstack).</p>

 <p>Added @(tsee lp), @('wet'), and @(tsee set-non-linearp) to
 @('*acl2-exports*'), and hence to the @('\"')@(tsee ACL2-USER)@('\"')
 package.</p>

 <p>The distributed book @('books/arithmetic-3/bind-free/integerp.lisp') has
 been modified in order to prevent potential looping; specifically, the
 definition of function @('reduce-integerp-+-fn-1').  Thanks to Robert Krug for
 providing this change.</p>

 <p>A small improvement was made in the @('wet') failure message when the error
 occurs during translation to internal form.  Thanks to Jared Davis for
 pointing out the obscurity of some @('wet') error messages.</p>

 <p>We have improved ACL2's evaluation mechanism for the function
 @('bad-atom<='), which now is specified to return @('nil') if neither argument
 is a so-called ``bad atom'' (as recognized by function @('bad-atom')).  The
 following events had caused a hard error, for example.  (We're sorry that
 @('bad-atom') and @('bad-atom<=') are not documented, but we also consider it
 unlikely that anyone needs such documentation; otherwise, please contact the
 implementors.)</p>

 @({
  (defun foo (x y) (declare (xargs :guard t)) (bad-atom<= x y))
  (defun bar (x y) (declare (xargs :guard t)) (foo x y))
  (thm (equal (bar 3 4) 7))
 })

 <p>We have also changed the guard on @(tsee alphorder) to require both
 arguments to be atoms.</p>

 <p>For forms @('(local x)') that are skipped during @(tsee include-book), or
 during the second pass of @(tsee certify-book) or @(tsee encapsulate), ACL2
 had nevertheless checked that @('x') is a legal event form.  This is no longer
 the case.</p>

 <p>The @(see proof-builder) now does non-linear arithmetic when appropriate.
 It had formerly ignored @(tsee set-non-linearp) executed in the ACL2 command
 loop.</p>

 <p>Incremental releases are now supported.  See @(see version) and {obsolete
 after Version 4.3} set-tainted-okp.  Thanks to Hanbing Liu for discovering a
 flaw in our original design.</p>

 <p>The pattern-matching algorithm for @(':')@(tsee rewrite) rules has been
 made slightly more restrictive, thanks to a suggestion and examples from
 Robert Krug.  For example, previously one could get an infinite loop as
 follows.</p>

 @({
  (defstub foo (x) t)
  (defaxiom foo-axiom
    (equal (foo (+ 1 x))
           (foo x)))
  (thm (foo 0)) ; or replace 0 by any integer!
 })

 <p>That is because the term @('(foo 0)') was considered to match against the
 pattern @('(foo (+ 1 x))'), with @('x') bound to @('-1').  While such matching
 is sound, it leads to an infinite loop since it allows @('foo-axiom') to
 rewrite @('(foo 0)') to @('(foo -1)'), and then @('(foo -1)') to @('(foo
 -2)'), and so on.  The fix is to insist that the new value, in this case
 @('-1'), is no larger in size according to @(tsee acl2-count) than the old
 value, in this case @('0').  Since that test fails, the match is considered to
 fail and the loop no longer occurs.  An analogous fix has been made for
 multiplication, where now we only match when the new term is still a non-zero
 integer.  That change avoids a loop here.</p>

 @({
  (defstub foo (x) t)
  (defaxiom foo-axiom
    (equal (foo (* 2 x))
           (foo x)))
  (thm (foo 0)) ; or try (thm (foo 4))
 })

 <p>Added macro @('find-lemmas') in @('books/misc/find-lemmas.lisp') (see brief
 documentation there) for finding all lemmas that mention all function symbols
 in a given list.</p>

 <p>@(':Restrict') @(see hints) now work for @(':')@(tsee definition) rules,
 though they continue to be ignored by the preprocessor and hence you may want
 to use @(':do-not '(preprocess)') with any restrict hints.  Thanks to John
 Matthews for pointing out the lack of support for @(':definition') rules in
 @(':restrict') hints.</p>

 <p>Some books have been updated.  In particular, there is a new directory
 @('books/workshops/2004/') in workshops distribution, for the 2004 ACL2
 workshop.  There is also a new version of Jared Davis's ordered sets library,
 formerly in @('books/finite-set-theory/osets-0.81/') but now in
 @('books/finite-set-theory/osets/').</p>

 <p>Fixed a bug in the (under-the-hood) raw Lisp definition of @(tsee
 defchoose), which had been causing a warning in CMU Common Lisp.</p>

 <p>[Technical improvements related to the use of ``@('make dependencies')''
 for certifying distributed books:]<br></br> File @('books/Makefile-generic')
 now does a better job with ``@('make dependencies'),'' specifically with
 respect to handling @('*.acl2') files and handling @(tsee include-book)
 commands with @(':dir :system').  Regarding the latter, suppose for example
 that book @('basic.lisp') contains the line:</p>

 @({
  (include-book \"arithmetic/top-with-meta\" :dir :system)
 })

 <p>Then @('make dependencies') would generate the following line:</p>

 @({
  basic.cert: $(ACL2_SRC_BOOKS)/arithmetic/top-with-meta.cert
 })

 <p>Thus, if @(':dir :system') is used with @(tsee include-book), the
 corresponding @('Makefile') should define the variable @('ACL2_SRC_BOOKS').  A
 standard @('Makefile') header for a books directory could thus be as
 follows.</p>

 @({
  # The following variable should represent the ACL2 source directory.  It is the
  # only variable in this Makefile that may need to be edited.
  ACL2_SRC = ../../../../../..

  ACL2_SRC_BOOKS = $(ACL2_SRC)/books
  include $(ACL2_SRC_BOOKS)/Makefile-generic
  ACL2 = $(ACL2_SRC)/saved_acl2h
 })

 <p>Finally, the ``@('-s')'' flag may now be omitted when running ``@('make
 dependencies').''</p>")

(defxdoc note-2-9-2

; Example for item below,
; "Guard-related warnings could be printed during proofs.  These warnings have
;  been eliminated."
;
;(defun my-test1 (expr)
;  (declare (xargs :guard (true-listp expr)
;                  :verify-guards nil))
;  (if (atom expr)
;      expr
;    (cons (my-test1 (car expr))
;          (my-test1 (cdr expr)))))
;
;(defun foo (n)
;  (declare (xargs :measure (acl2-count n)))
;  (if (zp n) n (foo (equal (list (my-test1 '(a b c)) (my-test1 '(a b c))) 17)) ))
;
;(thm (equal (list (my-test1 '(a b c)) (my-test1 '(a b c))) 17))

  :parents (release-notes)
  :short "ACL2 Version  2.9.2 (April, 2005) Notes"
  :long "<p>Also see @(see note-2-9-1) for other changes since the last
 non-incremental release
 (Version_2.9).</p>

 <p>There was a bug in non-linear arithmetic (see @(see non-linear-arithmetic))
 that caused the following error:</p>

 @({
  ACL2 !>(include-book \"rtl/rel4/lib/top\" :dir :system)
  ....
  ACL2 !>(set-non-linearp t)
   T
  ACL2 !>(thm
   (implies (and (bvecp a 77)
                 (bvecp b 50))
            (bvecp (fl (/ (* a b) (expt 2 23)))
                   104))
   :hints ((\"Goal\" :in-theory (enable bvecp))))

  [Note:  A hint was supplied for our processing of the goal above.
  Thanks!]

  By the simple :definition BVECP, the :executable-counterparts of EXPT
  and UNARY-/ and the simple :rewrite rule ASSOCIATIVITY-OF-* we reduce
  the conjecture to

  Goal'
  (IMPLIES (AND (INTEGERP A)
                (<= 0 A)
                (< A 151115727451828646838272)
                (INTEGERP B)
                (<= 0 B)
                (< B 1125899906842624))
           (BVECP (FL (* A B 1/8388608)) 104)).

  HARD ACL2 ERROR in VARIFY:  This should not have happened.  The supposed
  variable, '1/8388608, is instead a constant.

  ACL2 !>
 })

 <p>Thanks to Robert Krug for providing a fix for the above error.</p>

 <p>Guard-checking was being inhibited (since v2-9) for calls of built-in
 primitives on explicit values, e.g., @('(car 3)').  This has been fixed.</p>

 <p>Guard-related warnings could be printed during proofs (this bug was
 introduced in Version_2.9.1).  These warnings have been eliminated.</p>

 <p>Compound-recognizer rules @('natp-compound-recognizer') and
 @('posp-compound-recognizer') are now built into ACL2 for predicates @(tsee
 natp) and @(tsee posp), and hence have been deleted from book
 @('natp-posp.lisp') (where they were called @('natp-cr') and @('posp-cr'),
 respectively).</p>

 <p>The function @('file-clock-p'), which recognizes a component of the ACL2
 @(tsee state), is now defined using @(tsee natp) instead of @(tsee integerp).
 Thanks to Jared Davis for suggesting this change.  (Technical explanation
 about functions in ACL2 source file @('axioms.lisp'): With a @('file-clock')
 of -1, the call of @('make-input-channel') in @('open-input-channel') will
 create a channel that can't be closed; see the guard of
 @('close-input-channel').)</p>

 <p>(Allegro CL users only) Support is now provided for building an Allegro CL
 application, provided you have an Allegro CL dynamic runtime license.  (Our
 belief is that with such a license, many users can use the same application,
 rather than each user needing a separate license.)  See new GNUmakefile target
 @('allegro-app') and file @('build-allegro-exe.cl') for more information.</p>

 <p>The new home page now contains a link to a new page
 @('other-releases.html'), which contains information about other ACL2
 releases.  (This is in one's local home page, but may not show up on the
 central ACL2 home page until the next non-incremental release.)  Thanks to
 Warren Hunt for suggesting this addition.</p>

 <p>We thank Erik Reeber for suggesting a solution to output redirection using
 @(tsee sys-call), which we have described at the end of its documentation.</p>

 <p>A new documentation topic fixes the flawed argument for conservativity of
 the @(tsee defchoose) event that appears in Appendix B of Kaufmann and Moore's
 paper, ``Structured Theory Development for a Mechanized Logic'' (Journal of
 Automated Reasoning 26, no. 2 (2001), pp. 161&ndash;203).  See @(see
 conservativity-of-defchoose).  Thanks to John Cowles and Ruben Gamboa for
 helpful feedback on drafts of this note.</p>

 <p>The solution to exercise 6.15 in @('books/textbook/chap6/solutions.txt')
 has been fixed.  Thanks to Aaron Smith for pointing out the problem.</p>

 <p>A new documentation topic @(see defun-sk-example) gives a little more help
 in using @(tsee defun-sk) effectively.  Thanks to Julien Schmaltz for
 presenting this example as a challenge.</p>

 <p>(GCL only) There is now a way to speed up GCL builds of ACL2, at the cost
 of perhaps a percent or so in performance of the resulting image.  Using
 `make' one supplies the following.</p>

 @({
  LISP='gcl -eval \"(defparameter user::*fast-acl2-gcl-build* t)\"
 })

 <p>Various makefiles have been improved in several ways.</p>

 <blockquote><p>(1) Parallel book certification, using GNU make's @('-j')
 option, can be used.</p>

 <p>(2) Book certifications now stops at the first failure if
 @('books/Makefile') or @('books/Makefile-generic') is used, and returns
 non-zero exit status.  However, the various make targets in the ACL2 source
 directory (@('regression'), @('certify-books'), etc.) still continue past
 failures unless you provide @('ACL2_IGNORE=' '') on the `make' command
 line.</p>

 <p>(3) The build process has been modified (file @('GNUmakefile')) so that it
 stops upon a failed compile or a failed initialization.</p>

 <p>(4) The automatic dependency generation (from ``@('make dependencies')''
 has been improved so that commands of the form @('(ld \"my-book.lisp\")') in
 @('.acl2') files cause the appropriate dependencies to be
 generated.</p></blockquote>

 <p>Thanks to comments from several users that led to the above Makefile
 improvements: Ray Richards, Doug Harper, and the Rockwell ACL2 users for (1)
 and (2) (and inspiring (4)), and David Rager for (2) and (3).  In particular,
 Doug Harper sent a replacement for the @('.date') mechanism, which was
 interfering with @('make -n'); so, these files are no longer written.</p>

 <p>A mechanism has been added for saving output.  In particular, you can now
 call @(tsee ld) on a file with output turned off, for efficiency, and yet when
 a proof fails you can then display the proof attempt for the failed (last)
 event.  See @(see set-saved-output).  Another new command &mdash; see @(see
 set-print-clause-ids) &mdash; causes subgoal numbers to be printed during
 proof attempts when output is inhibited.</p>

 <p>Documentation has been added for using ACL2's makefile support to automate
 the certification of collections of books.  See @(see
 books-certification-classic).</p>

 <p>Fixed a bug in @(tsee sys-call-status) that was causing hard Lisp
 errors.</p>

 <p>Improved @(tsee cw-gstack) to allow a @(':frames') argument to specify a
 range of one or more frames to be printed.  see @(see cw-gstack).</p>

 <p>Fixed a bug in @(see proof-builder) command @('forwardchain').  Thanks to
 Ming-Hsiu Wang for bringing this bug to our attention.</p>

 <p>We have provided a mechanism for saving an executable image.  See @(see
 saving-and-restoring) and see @(see save-exec).  We have eliminated obsolete
 functions @('note-lib') and @('make-lib').</p>

 <p>Modified the @(tsee ground-zero) @(see theory) so that it contains all of
 the built-in rules (in ACL2 source file @('axioms.lisp')).  It had formerly
 failed to include rules from some definitions and theorems near the end of
 @('axioms.lisp').</p>

 <p>A new event, @(tsee set-enforce-redundancy), allows the enforcement of
 @(tsee defthm), @(tsee defun), and most other events during book development.
 See @(see set-enforce-redundancy).</p>

 <p>A bug has been fixed that had allowed @(tsee deftheory) @(see events) to
 cause a hard Lisp error when calling @(tsee union-theories) on ill-formed
 theories after, for example:</p>

 @({
  :set-guard-checking nil
  (in-theory (union-theories '((:rewrite no-such-rule))
                             (current-theory 'ground-zero)))
 })

 <p>The handling of @(see guard) checking has been modified somewhat in a way
 that should only very rarely affect users.  (An ``Essay on Guard Checking'' in
 the ACL2 source code explains this point to anyone interested in
 implementation details.)</p>

 <p>(GCL ONLY) Removed the -dir setting in the ACL2 wrapper script for GCL.
 This should generally have no effect for most users, but it eliminates a
 potential source of error down the road.</p>

 <p>Several interesting new definitions and lemmas have been added to the rtl
 library developed at AMD, and incorporated into @('books/rtl/rel4/lib/').
 Other book changes include a change to lemma @('truncate-rem-elim') in
 @('books/ihs/quotient-remainder-lemmas.lisp'), as suggested by Jared
 Davis.</p>

 <p>The macro @(tsee real/rationalp) may now be referred to in @(tsee
 in-theory) @(see events) and @(see hints), thanks to a new @(tsee
 add-macro-alias) event.  Thanks to Jared Davis for this suggestion.</p>

 <p>ACL2 terms of the form @('(if p 'nil 't)') are now printed as @('(not p)'),
 where in some setting they had been printed as @('(and (not p) t)').  Thanks
 to Robert Krug for this improvement.</p>

 <p>(GCL ONLY) Added profiling support, based heavily on code supplied by Camm
 Maguire.  See file @('save-gprof.lsp') for instructions.  Thanks to Camm, and
 also to David Hardin for inspiring this addition.</p>

 <p>Added support for preprocessing before printing (untranslating) a term.
 See @(see user-defined-functions-table), in particular the discussion of
 @('untranslate-preprocess').  Thanks to Jared Davis for inspiring this
 addition, and for providing a book that takes advantage of it
 (@('books/misc/untranslate-patterns.lisp')).</p>

 <p>The documentation has been improved for explaining how @(see rune)s are
 assigned; see @(see rune).  Thanks to Robert Krug for pointing out
 inaccuracies in the existing documentation.</p>")

(defxdoc note-2-9-3

; Things that seem too minor to mention:

; (Intern (coerce (list #\Page) 'string) "ACL2") was printing as control-L
; without surrounding |..|, which cannot be read back in (at least in GCL).  A
; similar problem occurs with (Intern (coerce (list #\A #\Page #\B) 'string)
; "ACL2") So, added #\Page to *slashable-chars*.

; Eliminated a warning in CMUCL 19b due to missing arguments in error cases for
; source functions find-alternative-start1 and find-alternative-stop.

  :parents (release-notes)
  :short "ACL2 Version  2.9.3 (August, 2005) Notes"
  :long "<p>Also see @(see note-2-9-1) and see @(see note-2-9-2) for other
 changes since the last non-incremental release (Version_2.9).</p>

 <p>We fixed a soundness bug that exploited the ability to define @(':')@(tsee
 program) mode functions that are improperly guarded, and then to use those
 functions in @(tsee defconst) forms.  The fix is to evaluate @(tsee defconst)
 forms using the same ``safe-mode'' that is used in macroexpansion (see @(see
 guards-and-evaluation)).  Here is a proof of @('nil') that succeeded in
 Allegro Common Lisp (but not, for example, GCL).  See also a long comment in
 source function @('defconst-fn') for an example that does not require the use
 of @(':set-guard-checking').</p>

 @({
  :set-guard-checking nil ; execute before certifying the book below

  (in-package \"ACL2\")

  (encapsulate
   ()
   (local (defun f1 ()
            (declare (xargs :mode :program))
            (char-upcase (code-char 224))))
   (local (defconst *b* (f1)))
   (defun f1 ()
     (char-upcase (code-char 224)))
   (defconst *b* (f1))
   (defthm bad
     (not (equal *b* (code-char 224)))
     :rule-classes nil))

  (defthm ouch
    nil
    :hints ((\"Goal\" :use bad))
    :rule-classes nil)
 })

 <p>We fixed a soundness hole due to the fact that the \"LISP\" package does
 not exist in OpenMCL.  We now explicitly disallow this package name as an
 argument to @(tsee defpkg).  Thanks to Bob Boyer and Warren Hunt for bringing
 an issue to our attention that led to this fix.</p>

 <p>ACL2 now requires all package names to consist of standard characters (see
 @(see standard-char-p), none of which is lower case.  The reason is that we
 have seen at least one lisp implementation that does not handle lower case
 package names correctly.  Consider for example the following raw lisp log
 (some newlines omitted).</p>

 @({
  >(make-package \"foo\")
  #<\"foo\" package>
  >(package-name (symbol-package 'FOO::A))
  \"foo\"
  >(package-name (symbol-package '|FOO|::A))
  \"foo\"
  >
 })

 <p>Distributed book @('books/textbook/chap10/compiler'), as well as workshop
 books in directory @('books/workshops/2004/cowles-gamboa/support/'), were
 modified to accommodate the above change.</p>

 <p>Added @('newline'), @(tsee add-to-set-eql), @('the-fixnum'), and
 @('the-fixnum!')  to @('*acl2-exports*').  Thanks to Jared Davis for bringing
 these to our attention.</p>

 <p>Added a line to @('acl2.lisp') to support CMUCL running on Mac OSX, thanks
 to a suggestion from Fabricio Chalub Barbosa do Rosario.</p>

 <p>The executable scripts for saved ACL2 images now include @('$*'), so that
 command-line arguments will be passed along.</p>

 <p>(For GCL profiling only) Fixed a colon (@(':')) that should have been a
 semicolon (@(';')) in file @('save-gprof.lsp').  Thanks to David Hardin for
 pointing out this bug.</p>

 <p>The documentation for @(':')@(tsee elim) rules has been expanded and
 improved, thanks to useful feedback from Hanbing Liu.</p>

 <p>Fixed a bug in the guard for function @('include-book-dir').</p>

 <p>For those who want to experiment with an alternate implementation of @(tsee
 mv) and @(tsee mv-let), there is now support for under-the-hood implementation
 of these in terms of raw Lisp functions @('values') and
 @('multiple-value-bind'), respectively.  The regression suite has seen about a
 10% speed-up in Allegro CL and about an 8% slowdown in GCL for builds with
 this change.  See the makefile (@('GNUmakefile')) for examples of how to build
 ACL2 by including the feature, @(':acl2-mv-as-values').  Source file
 @('init.lsp') has been renamed to @('init.lisp') in support of this change
 (technical detail: otherwise GCL loads the init file too soon, before its
 @('-eval') argument is evaluated).  Thanks to David Rager for inspiring this
 change, by pointing out the problematic use of globals by the existing @(tsee
 mv) implementation from the standpoint of supporting parallel evaluation.
 This capability is experimental: there is likely to be some remaining work to
 be done on it.</p>

 <p>A change related to the one just above is that we now limit the maximum
 number of arguments to any call of @(tsee mv) to 32.  Thanks to Bob Boyer for
 raising a question that lead to this change.</p>

 <p>Eliminated some compiler warnings in OpenMCL.</p>

 <p>In the rtl library (@('books/rtl/rel4/')), functions @('bits') and
 @('setbits') have had their @(see guard)s improved (as they had been too
 restrictive, especially for @('setbits')).</p>

 <p>A new function @(tsee time$) permits timing of forms, by using (under the
 hood) the host Common Lisp's @('time') utility.</p>

 <p>We fixed an infinite loop that could occur during destructor elimination
 (see @(see elim)).  Thanks to Sol Swords to bringing this to our attention and
 sending a nice example, and to Doug Harper for sending a second example that
 we also found useful.</p>

 <p>The method of speeding up GCL-based builds (see @(see note-2-9-2)) has
 changed slightly from Version_2.9.2.  Now, in the `make' command:</p>

 @({
    LISP='gcl -eval \"(defparameter user::*fast-acl2-gcl-build* t)\"
 })

 <p>We improved the pretty-printer's handling of keywords.  For example, before
 this change one might see the following printed by ACL2.</p>

 @({
  (MODIFY TH S :KEY1 VAL1 :KEY2
          (IF (IF X Y Z) AAAAAAAAAA BBBBBBB))
 })

 <p>Now, the above might print as follows.  Notice that we have avoided
 breaking after a keyword (see @(see keywordp)) that is preceded by other forms
 on the same line.</p>

 @({
  (MODIFY TH S
          :KEY1 VAL1
          :KEY2 (IF (IF X Y Z) AAAAAAAAAA BBBBBBB))
 })

 <p>See @(see note-2-9-3-ppr-change) for a detailed discussion of this
 change.</p>

 <p>(GCL ONLY) Evaluation in a break is no longer inhibited by ACL2 when built
 on top of GCL, so GCL now matches other Common Lisps in this respect.</p>

 <p>For ACL2 built on most host Common Lisps, you will see the string @('[RAW
 LISP]') in the prompt, at least at a break, to emphasize that one is inside a
 break and hence should probably quit from the break.  See @(see breaks).</p>

 <p>Jared Davis suggested improvements to lemmas @('len-update-nth') (in source
 file @('axioms.lisp')) and @('append-true-listp-type-prescription') (in
 @('books/meta/term-defuns.lisp')), which have been incorporated.  The former
 required a change in @('books/workshops') book
 @('2004/ruiz-et-al/support/q-dag-unification.cert'), which has been made.</p>

 <p>The @(see proof-builder) command @('rewrite') allows further binding of
 free variables in hypotheses, with new optional argument
 @('instantiate-free').  proof-builder command @('show-rewrites') (@('sr'))
 gives corresponding additional information.  Documentation for these commands
 has been improved; see @(see proof-builder-commands).  Thanks to John Matthews
 and Bill Young for suggestions and feedback leading to these improvements.</p>

 <p>Fixed downcase printing so that the package name of a symbol is also
 downcased.  For example, after execution of @('(defpkg \"FOO\" nil)') and
 @('(set-acl2-print-case :downcase)'), @(''foo::ab') will print back as the
 same, rather than as @(''FOO::ab').</p>

 <p>It is now possible to control the output so that numbers are printed in
 binary, octal, or hex, though the default is still radix 10.  See @(see
 set-print-base).  Note that in support of this change, built-in functions
 @(tsee explode-nonnegative-integer) and @('explode-atom') now take an extra
 @('print-base') argument.  Different support for radix conversion may be found
 in a book newly contributed by Jun Sawada, @('books/misc/radix.lisp').</p>

 <p>Built-in axiom @('car-cdr-elim') is now only an @(':')@(tsee elim) rule.
 It was formerly both an @(':elim') rule and a @(':')@(tsee rewrite) rule.  A
 new rule, @('cons-car-cdr'), takes the place of the old @(':rewrite') rule,
 but is instead a hypothesis-free rule that can cause a case split (see source
 file @('axioms.lisp')).  Thanks to Jared Davis for suggesting this change.</p>

 <p>Lemmas about @(tsee alphorder) (@('alphorder-reflexive'),
 @('alphorder-transitive'), @('alphorder-anti-symmetric'), and
 @('alphorder-total')) are now available.  (They had been @(tsee local) in
 source file @('axioms.lisp').)  Thanks to Serita Nelesen for bringing this
 issue to our attention.</p>

 <p>ACL2 has, for some time, printed a space in the event summary after the
 open parenthesis for a @(tsee defthm) event, in order to ease backward
 searching for the original form, for example @('(defthm bar ...)'):</p>

 @({
  Form:  ( DEFTHM BAR ...)
 })

 <p>The intention was that this extra space should be printed for every event
 form; but it was missing in some cases, for example, for @(tsee
 verify-guards).  This has been fixed.</p>

 <p>In analogy to @(tsee include-book), now @(tsee ld) takes the (optional)
 keyword argument @(':dir').  Thanks to Jared Davis for providing an
 implementation of this feature and to Eric Smith and Jeff Marshall for
 requesting this feature.</p>

 <p>We fixed a bug in @(tsee include-book) that could cause an error when
 redefinition is on, for example:</p>

 @({
  (set-ld-redefinition-action '(:warn! . :overwrite) state)
  (include-book \"/u/acl2/books/arithmetic/top\")
 })

 <p>The behavior of @(tsee include-book) now matches the documentation:
 handling of compiled files for uncertified @(see books) will follow the same
 rules as for certified books.  In particular, if you create an object file in
 raw Lisp for some book, then including that book will load that object file.
 Thanks to Jared Davis for bringing this issue to our attention.</p>

 <p>New documentation explains the interaction of redefinition and redundancy.
 See @(see redundant-events) &mdash; the ``Note About Unfortunate
 Redundancies'' is new.  Thanks to Grant Passmore for providing examples that
 led us to write this additional documentation.</p>

 <p>Solutions to exercises in <a
 href='http://www.cs.utexas.edu/users/moore/publications/how-to-prove-thms'>
 How To Prove Theorems Formally</a> are now available in distributed book
 @('books/misc/how-to-prove-thms.lisp').  Also in that directory may be found a
 new book @('hanoi.lisp') that contains a solution to the Towers of Hanoi
 problem.</p>")

(defxdoc note-2-9-3-ppr-change
  :parents (note-2-9-3)
  :short "Change in pretty-printing for ACL2 Version_2.9.3"
  :long "<p>We have improved pretty-printing in ACL2 Version_2.9.3 to handle
 keywords a little differently.  To see a discussion of the basics of this
 change, see @(see note-2-9-3).  In this note we describe it in considerable
 detail.</p>

 <p>Those who wish to understand the ACL2 pretty-printer's implementation can
 now find considerably more comments on it in the source code.  In this note,
 we do not focus on the implementation.  Rather, we motivate the change and
 show how the improved prettyprinter performs.</p>

 <p>Why do we want better keyword handling?  Imagine a macro that builds a new
 state from an old state by changing the values in the affected fields, leaving
 everything else unchanged.  One could write</p>

 @({
  (modify th s :key1 val1 :key2 val2 :key3 val3)
 })

 <p>where the three keys identify fields in the state.</p>

 <p>To make it easier to read new concrete states, we may have a function that
 prints them ``relative'' to a given base state, expressing the new state as a
 modification of the given base state.  So we may find ourselves prettyprinting
 modify forms like that above.</p>

 <p>The previous prettyprinter will sometimes print the form above as
 follows.</p>

 @({
  (modify th s :key1
          val1
          :key2 val2 :key3 val3)
 })

 <p>This can be unpleasant to read, because of the way @(':key1') and @('val1')
 are separated.  Here is an example of the old prettyprinter and the new one,
 both printing an expression from the ACL2 source code in a width of 40:</p>

 @({
  Old:
  (ADD-TO-TAG-TREE
   'ASSUMPTION
   (MAKE
    ASSUMPTION :TYPE-ALIST TYPE-ALIST
    :TERM TERM :REWRITTENP REWRITTENP
    :IMMEDIATEP IMMEDIATEP :ASSUMNOTES
    (LIST
     (MAKE
          ASSUMNOTE :CL-ID
          NIL :RUNE RUNE :TARGET TARGET)))
   TTREE)

  New:
  (ADD-TO-TAG-TREE
       'ASSUMPTION
       (MAKE ASSUMPTION
             :TYPE-ALIST TYPE-ALIST
             :TERM TERM
             :REWRITTENP REWRITTENP
             :IMMEDIATEP IMMEDIATEP
             :ASSUMNOTES
             (LIST (MAKE ASSUMNOTE
                         :CL-ID NIL
                         :RUNE RUNE
                         :TARGET TARGET)))
       TTREE)
 })

 <p>Basically the change we made forces the prettyprinter to print each
 @(':key') on a new line unless they all fit on a single line.  So we would now
 get either</p>

 @({
  (modify th s :key1 val1 :key2 :val2 :key3 val3)
 })

 <p>or</p>

 @({
  (modify th s
          :key1 val1
          :key2 val2
          :key3 val3)
 })

 <p>Furthermore, we fixed it so that if @('val1') (say) is a big s-expression
 we may still print it on the same line as its key.  The old prettyprinter
 enforced the rule that if you wanted to print @('(foo a b)') and @('b') gets
 broken up into several lines, then it has to start on a new line.  Thus, we'd
 never print</p>

 @({
  (foo a (bbb
          (mum x)))
 })

 <p>but would print instead</p>

 @({
  (foo a
       (bbb
        (mum x)))
 })

 <p>Now, if a is a keyword, we can print the first way.</p>

 <p>So here are some nice examples of prettyprinted keyword forms.  All of
 these are printed for a page of width 40.</p>

 @({
  <--            40 chars               ->
  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

  (MODIFY TH S :KEY1 V1 :KEY2 V2)

  (MODIFY TH S :KEY1 V1 :KEY2 V2 :KEY3 V3)

  (MODIFY TH S1                               ; Because of the extra char
          :KEY1 V1                            ; in S1 the flat size exceeds
          :KEY2 V2                            ; 40 and we break it.
          :KEY3 V3)
 })

 <p>The old ppr would have printed this as:</p>

 @({
  (MODIFY
       TH S1 :KEY1 V1 :KEY2 V2 :KEY3 V3)
 })

 <p>Returning to new examples:</p>

 @({
  <--            40 chars               ->
  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

  (MODIFY TH S
          :KEY1 (IF (IF X Y Z) AAAA BBBB)
          :KEY2 VAL2
          :KEY3 VAL3)
 })

 <p>Now we extend @('AAAA') and @('BBBB') by one char each, so it would
 overflow the right margin if printed as above, and we get:</p>

 @({
  <--            40 chars               ->
  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

  (MODIFY
       TH S
       :KEY1 (IF (IF X Y Z) AAAAX BBBBX)
       :KEY2 VAL2
       :KEY3 VAL3)
 })

 <p>If we make these names even longer we force the value off the line
 containing @(':key1'):</p>

 @({
  (MODIFY
       TH S
       :KEY1
       (IF (IF X Y Z) AAAAXXXXX BBBBXXXXX)
       :KEY2 VAL2
       :KEY3 VAL3)
 })

 <p>Here are some examples from the ACL2 source code, printed in 40
 characters:</p>

 @({
  (DEFTHM
   ALPHORDER-ANTI-SYMMETRIC
   (IMPLIES (AND (NOT (CONSP X))
                 (NOT (CONSP Y))
                 (ALPHORDER X Y)
                 (ALPHORDER Y X))
            (EQUAL X Y))
   :HINTS
   ((\"Goal\"
     :IN-THEORY
     (UNION-THEORIES
      '(STRING< SYMBOL-<)
      (DISABLE
         CODE-CHAR-CHAR-CODE-IS-IDENTITY))
     :USE
     ((:INSTANCE SYMBOL-EQUALITY (S1 X)
                 (S2 Y))
      (:INSTANCE BAD-ATOM<=-ANTISYMMETRIC)
      (:INSTANCE
           CODE-CHAR-CHAR-CODE-IS-IDENTITY
           (C Y))
      (:INSTANCE
           CODE-CHAR-CHAR-CODE-IS-IDENTITY
           (C X)))))
   :RULE-CLASSES
   ((:FORWARD-CHAINING
     :COROLLARY
     (IMPLIES
        (AND (ALPHORDER X Y)
             (NOT (CONSP X))
             (NOT (CONSP Y)))
        (IFF (ALPHORDER Y X) (EQUAL X Y)))
     :HINTS
     ((\"Goal\"
       :IN-THEORY (DISABLE ALPHORDER))))))
 })

 <p>Here is that same one, printed in a width of 60.</p>

 @({
  (DEFTHM
   ALPHORDER-ANTI-SYMMETRIC
   (IMPLIES (AND (NOT (CONSP X))
                 (NOT (CONSP Y))
                 (ALPHORDER X Y)
                 (ALPHORDER Y X))
            (EQUAL X Y))
   :HINTS
   ((\"Goal\"
       :IN-THEORY
       (UNION-THEORIES
            '(STRING< SYMBOL-<)
            (DISABLE CODE-CHAR-CHAR-CODE-IS-IDENTITY))
       :USE ((:INSTANCE SYMBOL-EQUALITY (S1 X)
                        (S2 Y))
             (:INSTANCE BAD-ATOM<=-ANTISYMMETRIC)
             (:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY (C Y))
             (:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY
                        (C X)))))
   :RULE-CLASSES
   ((:FORWARD-CHAINING
        :COROLLARY (IMPLIES (AND (ALPHORDER X Y)
                                 (NOT (CONSP X))
                                 (NOT (CONSP Y)))
                            (IFF (ALPHORDER Y X) (EQUAL X Y)))
        :HINTS ((\"Goal\" :IN-THEORY (DISABLE ALPHORDER))))))
 })

 <p>Just for comparison, here is the above printed in 60 columns by the old
 prettyprinter.</p>

 @({
  (DEFTHM
   ALPHORDER-ANTI-SYMMETRIC
   (IMPLIES (AND (NOT (CONSP X))
                 (NOT (CONSP Y))
                 (ALPHORDER X Y)
                 (ALPHORDER Y X))
            (EQUAL X Y))
   :HINTS
   ((\"Goal\" :IN-THEORY
            (UNION-THEORIES
                 '(STRING< SYMBOL-<)
                 (DISABLE CODE-CHAR-CHAR-CODE-IS-IDENTITY))
            :USE
            ((:INSTANCE SYMBOL-EQUALITY (S1 X)
                        (S2 Y))
             (:INSTANCE BAD-ATOM<=-ANTISYMMETRIC)
             (:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY (C Y))
             (:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY
                        (C X)))))
   :RULE-CLASSES
   ((:FORWARD-CHAINING
         :COROLLARY
         (IMPLIES (AND (ALPHORDER X Y)
                       (NOT (CONSP X))
                       (NOT (CONSP Y)))
                  (IFF (ALPHORDER Y X) (EQUAL X Y)))
         :HINTS
         ((\"Goal\" :IN-THEORY (DISABLE ALPHORDER))))))
 })

 <p>Of course, given that you cannot tell for sure whether the keywords you're
 seeing are part of a keyword/value parameter list or part of some constant
 containing random keywords, the prettyprinter can't solve the problem
 perfectly.  We just tried to make it work nicely on well-formed keyword/value
 parameter lists.</p>

 <p>For example, here is a form printed by the each prettyprinter.</p>

 @({
  Old:
  (MEMBER
   X
   '(:MONDAY
        :MON :TUESDAY :TUES :WEDNESDAY
        :WED :THURSDAY :THURS :FRIDAY
        :FRI :SATURDAY :SAT :SUNDAY :SUN))

  New:
  (MEMBER X
          '(:MONDAY :MON
                    :TUESDAY :TUES
                    :WEDNESDAY :WED
                    :THURSDAY :THURS
                    :FRIDAY :FRI
                    :SATURDAY :SAT
                    :SUNDAY :SUN))
 })

 <p>The new way is not how one would print it by hand!  But then, neither is
 the old way.</p>")

(defxdoc note-2-9-4

; The soundness bug "due to inadequate checking of :meta rules" is documented
; in chk-acceptable-rules.

; Things that seem too minor to mention:

; Added a force-output call to print-prompt by way of new macro
; with-output-forced.  This seemed necessary for SBCL.

; In load-acl2, replaced (eval '(setq state *the-live-state*)) with what we
; used to do only for cmulisp, namely (set 'state *the-live-state*).

; Made small fix to translate11's handling of synp, to avoid requiring
; quote-normal form but to insist that the QUOTE calls have one argument.

; The error message for guard violations was cleaned up: added a sentence for
; new users, added ev-fncall-guard-er-msg for code sharing, and added initial
; part for new users to :doc set-guard-checking.

; To see the change mentioned below for set-let*-abstractionp, try this:
; (defpkg "FOO" (union-eq *acl2-exports*
;                         *common-lisp-symbols-from-main-lisp-package*))
; (in-package "FOO")
; (defstub foo (x) t)
; (defstub bar (x) t)
; :set-let*-abstractionp t
; (thm (equal (foo (append x y)) (bar (append x y))))

; Added hard! severity value for er (not advertised).

; Replaced conjuncts-of by flatten-ands-in-lit.

; Modified books/workshops/2004/sumners-ray/support/Makefile to avoid having to
; remake success.txt when that is unnecessary.

; Regarding this item below:
;
; We fixed an inefficiency that could cause an ~ilc[ld] command to seem to hang
; at its conclusion.  Thanks to Sandip Ray for pointing out this problem.
;
; Here is a way to see the problem.  The change was to maybe-add-command-landmark.
; (include-book "arithmetic/top-with-meta" :dir :system)
; (ld '((u) (include-book "arithmetic/top-with-meta" :dir :system)))

; Added (type (signed-byte 29) col) declarations for parameter col in fmt0 and
; fmt1.

; Modified many warnings to say something like "A rule generated by FOO"
; instead of "The rule generated by FOO", in response to an email from John
; Cowles.  This may not really deal with the objection that it appears that
; more than one copy of the same warning can appear for a single event (for the
; case of more than one rule), but at least the new wording is more accurate,
; and much more of a change could require considerable effort.

  :parents (release-notes)
  :short "ACL2 Version  2.9.4 (February, 2006) Notes"
  :long "<p>Also see @(see note-2-9-1), see @(see note-2-9-2), and see @(see
 note-2-9-3) for other changes since the last non-incremental
 release (Version_2.9).</p>

 <p>A soundness bug has been fixed that was due to inadequate checking of
 @(':')@(tsee meta) rules in the presence of @(tsee local) @(see events).
 Specifically, a @('local') @(tsee defevaluator) event is insufficient for
 supporting a @(':meta') rule (an example is shown in source function
 @('chk-acceptable-rules')).  Thanks to Dave Greve and Jared Davis for bringing
 this bug to our attention, by sending a proof of @('nil') that exploited this
 bug.  The fix is to check legality of @(':meta') rules even when skipping
 proofs during an @(tsee include-book) event or the second pass of an @(tsee
 encapsulate) event.</p>

 <p>Fixed problem with parallel make for workshop books by adding a dependency
 line to @('books/workshops/2003/Makefile').</p>

 <p>Default hints (see @(see set-default-hints)) no longer prevent the use of
 @(':INSTRUCTIONS') (see @(see proof-builder)).  Thanks to Jared Davis for
 pointing out this problem.</p>

 <p>New functions @(tsee remove-eq) and @(tsee remove-equal) have been defined,
 in analogy to @(tsee remove).  These two symbols have also been added to
 @('*acl2-exports*').  Thanks to David Rager for pointing out that
 @('remove-equal') was missing.  Moreover, the definitions of @('delete1-eq')
 and @('delete1-equal') have been eliminated.  Function @('remove1-eq'), now in
 @(':')@(tsee logic) mode in source file @('axioms.lisp'), serves in place of
 @('delete1-eq'), with corresponding new function definitions for @(tsee
 remove1) and @(tsee remove1-equal).</p>

 <p>The symbol @(tsee assert$) has been added to @('*acl2-exports*').  Thanks
 to Jared Davis for the suggestion.</p>

 <p>Added SBCL support.  Thanks to Juho Snellman for significant assistance
 with the port.  Thanks to Bob Boyer for suggesting the use of feature
 @(':acl2-mv-as-values') with SBCL, which can allow thread-level parallelism in
 the underlying lisp; we have done so when feature @(':sb-thread') is
 present.</p>

 <p>We have continued to incorporate suggestions for wording improvements in
 documentation and error messages.  Thanks to all who send these suggestions,
 especially to Eric Smith, who has suggested the vast majority of them.</p>

 <p>Made a small improvement to errors and warnings caused on behalf of @(see
 set-enforce-redundancy), to indicate when an event of the same name already
 exists.</p>

 <p>Fixed a bug in @('books/misc/rtl-untranslate.lisp') that was causing a
 guard violation when adding a new entry for an existing key.</p>

 <p>Fixed a bug in translation to internal form that caused @(tsee defun-sk)
 and @(tsee defchoose) to have difficulties handling ignored variables in
 @(tsee let) forms.  Thanks to Sandip Ray to bringing this issue to our
 attention with a helpful example.</p>

 <p>The form @('(push :acl2-mv-as-values *features*)') has been added in source
 file @('acl2-init.lisp') for SBCL and OpenMCL only, in order to support
 parallel execution (looking to the future...).</p>

 <p>Default-hints (see @(see set-default-hints)) were being ignored inside the
 @(see proof-builder), but no longer.  Thanks to John Erickson for bringing
 this problem to our attention and providing a simple example of it.</p>

 <p>Modified the @('TAGS') @('\"make\"') target (specifically, function
 @('make-tags')) so that it is gracefully skipped if the @('etags') program is
 not found.  Thanks to David Rager for pointing out this issue.</p>

 <p>Sandip Ray has re-worked the supporting materials for his ACL2 Workshop
 2003 talk (originally with John Matthews and Mark Tuttle), to run in a few
 minutes.  The result is in @('workshops/2003/ray-matthews-tuttle/support/')
 and is included in the full ACL2 regression suite.  Thanks, Sandip.</p>

 <p>Debian releases of ACL2 had created superfluous @('.cert.final') files when
 certifying books.  This has been fixed; thanks to Jared Davis for noticing
 this problem.</p>

 <p>Jared Davis has pointed out that ``If you add a @(':backchain-limit-lst 0')
 to a rewrite rule whose hypotheses are all forced, then ACL2 `really assumes
 them' without trying to relieve them right there through rewriting.''
 Relevant documentation has been added for @(':backchain-limit-lst'); see @(see
 rule-classes).</p>

 <p>A new version of the rtl library has been included in @('books/rtl/rel5/').
 Thanks to David Russinoff for contributing hand proofs for the new lemmas, and
 to Matt Kaufmann for carrying out their mechanization.</p>

 <p>Fixed a bug in @(tsee save-exec) that was failing to set the initial
 @('cbd') according to the current directory when starting up ACL2.  Thanks to
 Camm Maguire for bringing our attention to this problem.</p>

 <p>Variables introduced during @('let*') abstraction are now in the current
 package.  Thanks to Jared Davis for suggesting such a change.  See @(see
 set-let*-abstractionp).</p>

 <p>It is now allowed for two definitions to be considered the same from the
 standpoint of redundancy (see @(see redundant-events)) when one specifies a
 @(':')@(tsee guard) of @('t') and the other has no explicit @(':guard')
 (hence, the guard is implicitly @('t')).  Thanks to Jared Davis for bringing
 this issue to our attention.</p>

 <p>(For users of @('emacs/emacs-acl2.el')) There have been a few enhancements
 to distributed file @('emacs/emacs-acl2.el') (skip this paragraph if you
 don't use that file):</p>

 <blockquote><p>o @('Control-t q') continues to compare windows ignoring
 whitespace, but now, a prefix argument can be given to control case is also
 ignored (ignore case if positive, else use case).</p>

 <p>o @('Control-t Control-l') has been defined to be similar to @('Control-t
    l'), except that proofs are skipped and output is suppressed.</p>

 <p>o @('Control-t u') has been defined to print, to the shell buffer, a
   @(':')@(tsee ubt!) form for the command containing the cursor.</p>

 <p>o Control-t Control-f buries the current buffer.</p>

 <p>o @('Meta-x new-shell') now puts the new shell buffer in @('shell-mode')
   (thanks to David Rager for noticing this issue).</p></blockquote>

 <p>Linear arithmetic has been modified so that we do not generate the equality
 @('(equal term1 term2)') from the pair of inequalities @('(<= term1 term2)')
 and @('(<= term2 term1)') in the case that we would have to @(tsee force) both
 @('term1') and @('term2') to be @(tsee acl2-numberp)s.  Thanks to Dave Greve
 for providing a motivating example and to Robert Krug for providing a fix.</p>

 <p>The event @(tsee delete-include-book-dir) had not been allowed inside @(see
 books) and @(tsee encapsulate) forms.  This was an oversight, and has been
 fixed.</p>

 <p>Sandip Ray has contributed a new library of books to support proofs of
 partial and total correctness of sequential programs based on assertional
 reasoning, in @('books/symbolic/').  This work is based on the paper
 J. Matthews, J S. Moore, S. Ray, and D. Vroon, ``A Symbolic Simulation
 Approach to Assertional Program Verification,'' currently in draft form.  In
 particular, the books include the macro @('defsimulate'), which automatically
 transforms inductive assertion proofs of correctness of sequential programs to
 the corresponding interpreter proofs.  See the @('README') in that
 directory.</p>

 <p>We have changed the implementation of @(':dir :system') for @(tsee ld) and
 @(tsee include-book).  This change will not affect you if you build an ACL2
 executable in the normal manner, leaving in place the @('books/') subdirectory
 of the source directory; nor will it affect you if you download a GCL Debian
 binary distribution.  The change is that if environment variable
 @('ACL2_SYSTEM_BOOKS') is set, then it specifies the distributed books
 directory, i.e., the directory determined by @(':dir :system').  You may find
 it convenient to set this variable in your ACL2 script file (typically,
 @('saved_acl2')).  If it is set when you build ACL2, the generated script for
 running ACL2 will begin by setting @('ACL2_SYSTEM_BOOKS') to that value.
 Thanks to various people who have discussed this issue, in particular Jared
 Davis who sent an email suggesting consideration of the use of an environment
 variable, and to Eric Smith who helped construct this paragraph.  (Note that
 this use of @('ACL2_SYSTEM_BOOKS') replaces the use of @('ACL2_SRC_BOOKS')
 described previously; see @(see note-2-9-1).)</p>

 <p>ACL2 now automatically deletes files @('TMP*.lisp') created during the
 build process and created by @(':')@(tsee comp).  If you want these to be
 saved, evaluate @('(assign keep-tmp-files t)') in the ACL2 loop or in raw
 Lisp.  The @('clean') target for the standard `make' process for certifying
 books (see @(see books-certification-classic)) will however delete all files
 @('TMP*.*').</p>

 <p>The @('TMP') files discussed just above now generally include the current
 process ID in their names, e.g., @('TMP@16388@1.lisp') instead of
 @('TMP1.lisp').  Thanks to Bob Boyer for suggesting this measure, which will
 reduce the possibility that two different processes will attempt to access the
 same temporary file.</p>

 <p>Now, @(':')@(tsee pe) will print the information formerly printed by
 @(':pe!'), slightly enhanced to work for logical names that are strings, not
 just symbols.  Thanks to Warren Hunt for leading us to this change by
 suggesting that @(':pe nth') print the definition of @(tsee nth).</p>

 <p>We eliminated spurious warnings that could occur in raw mode in OpenMCL or
 CMUCL when @(see stobj)s are present.  We thank Juho Snellman for pointing out
 the relevant bug and appropriate fix.</p>

 <p>@('Mfc-rw') now takes a third argument that can specify an arbitrary known
 equivalence relation; see @(see extended-metafunctions).  Thanks to Dave Greve
 for discussions suggesting this improvement.</p>

 <p>A small modification to a symbol-reading function allows documentation
 string processing on Windows systems that use CR/LF for line breaks.  Thanks
 to William Cook for bringing this issue to our attention.</p>

 <p>The documentation has been improved on how to control the printing of ACL2
 terms.  See @(see user-defined-functions-table).  Thanks to Sandip Ray for
 asking a question that led to the example presented there.</p>

 <p>We fixed an inefficiency that could cause an @(tsee ld) command to seem to
 hang at its conclusion.  Thanks to Sandip Ray for pointing out this
 problem.</p>

 <p>We checked that ACL2 runs under LispWorks 4.4.5, and have inhibited
 redefinition warnings.</p>

 <p>Two changes have been made on behalf of congruence-based reasoning.  Thanks
 to Dave Greve for examples and discussions that have led to these changes, and
 to Eric Smith and Vernon Austel, who also sent relevant examples.</p>

 <blockquote><p>o When a call of the new unary function @(tsee double-rewrite)
 is encountered by the rewriter, its argument will be rewritten twice.  This
 solves certain problems encountered in congruence-based rewriting.  Warnings
 for @(':')@(tsee rewrite) and @(':')@(tsee linear) rules will suggest when
 calls of @(tsee double-rewrite) on variables in hypotheses are likely to be a
 good idea.  See @(see double-rewrite).</p>

 <p>o Hypotheses of the form @('(equiv var (double-rewrite term))'), where
 @('equiv') is a known @(see equivalence) relation and @('var') is a free
 variable (see @(see free-variables)), will bind @('var') to the result of
 rewriting @('term') twice.  Previously, hypotheses of the form @('(equal var
 term)') would bind a free variable @('var'), but the call had to be of
 @('equal') rather than of an arbitrary known equivalence
 relation.</p></blockquote>

 <p>The following improvements were made in support of ACL2 on top of
 OpenMCL.</p>

 <blockquote>

 <p>o New versions of OpenMCL that do not have @(':mcl') in Lisp variable
 @('*features*') will now work with ACL2.  Thanks to David Rager for bringing
 this issue to our attention.</p>

 <p>o Added support for OpenMCL 1.0 for 64-bit DarwinPPC/MacOS X, thanks to
 Robert Krug.</p>

 <p>o Fixed tracing in OpenMCL so that the level is reset to 1 even if there
 has been an abort.</p>

 <p>o Added support in OpenMCL for @('WET').</p>

 <p>o Incorporated suggestions from Gary Byers for printing the ``Welcome to
 OpenMCL'' prompt before initially entering the ACL2 loop and, and for setting
 useful environment variable @('CCL_DEFAULT_DIRECTORY') in the ACL2
 script.</p></blockquote>

 <p>Fixed a long-standing bug in forward-chaining, where variable-free
 hypotheses were being evaluated even if the @(see executable-counterpart)s of
 their function symbols had been disabled.  Thanks to Eric Smith for bringing
 this bug to our attention by sending a simple example that exhibited the
 problem.</p>

 <p>Improved reporting by the @(see break-rewrite) utility upon failure to
 relieve hypotheses in the presence of free variables, so that information is
 shown about the attempting bindings.  See @(see
 free-variables-examples-rewrite).  Thanks to Eric Smith for requesting this
 improvement.  Also improved the @(see break-rewrite) loop so that terms, in
 particular from unifying substitutions, are printed without hiding subterms by
 default.  The user can control such hiding (``evisceration''); see :DOC
 @('set-brr-term-evisc-tuple').</p>

 <p>A new directory @('books/defexec/') contains books that illustrate the use
 of @(tsee mbe) and @(tsee defexec).  Thanks to the contributors of those books
 (see the @('README') file in that directory).</p>

 <p>The directories @('books/rtl/rel2') and @('books/rtl/rel3') are no longer
 distributed.  They are still available by email request.  (Subdirectory
 @('rel1/') supports some of the optional @('workshop/') books, so it is still
 distributed.)</p>

 <p>Added book @('books/misc/sticky-disable.lisp') to manage @(see theories)
 that might otherwise be modified adversely by @(tsee include-book).  Thanks to
 Ray Richards for a query that led to our development of this tool.</p>

 <p>The commands @('(exit)') and @('(quit)') may now be used to quit ACL2 and
 Lisp completely; in fact they macroexpand to calls of the same function as
 does @(tsee good-bye) (which is now a macro).  Thanks to Jared Davis for
 suggesting the new aliases.  (OpenMCL-only comment:) These all work for
 OpenMCL even inside the ACL2 loop.</p>

 <p>The macro @('wet') now hides structure by default on large expressions.
 However, a new optional argument controls this behavior, for example avoiding
 such hiding if that argument is @('nil').  Thanks to Hanbing Liu for pointing
 out that @('wet') was not helpful for very large terms.</p>

 <p>We have fixed a bug in the forward-chaining mechanism that, very rarely,
 could cause a proof to be aborted needlessly with an obscure error message.
 Thanks to Jared Davis for sending us an example that evoked this bug.</p>

 <p>Fixed a bug that was causing proof output on behalf of
 @(':functional-instance') to be confusing, because it failed to mention that
 the number of constraints may be different from the number of subgoals
 generated.  Thanks to Robert Krug for pointing out this confusing output.  The
 fix also causes the reporting of rules used when silently simplifying the
 constraints to create the subgoals.</p>

 <p>Fixed a bug in handling of leading @('./') in pathnames, as in:
 @('(include-book \"./foo\")').  Thanks to Jared Davis for bringing this bug to
 our attention.</p>

 <p>Made a small fix for handling of free variables of @(':')@(see
 forward-chaining) rules, which had erroneously acted as though a hypothesis
 @('(equal var term)') can bind the variable @('var').</p>

 <p>A small change has been made for @(':')@(tsee type-prescription) rules for
 hypotheses of the form @('(equal var term)'), where @('var') is a free
 variable and no variable of @('term') is free (see @(see free-variables)).  As
 with @(':')@(tsee rewrite) and @(':')@(tsee linear) rules, we now bind
 @('var') to @('term') even if @('(equal u term)') happens to be known in the
 current context for some term @('u').  Also as with @(':rewrite') and
 @(':linear') rules, similar handling is given to hypotheses @('(equiv var
 (double-rewrite term))') where @('equiv') is a known @(see equivalence)
 relation.</p>

 <p>We changed the handling of free variables in hypotheses of @(':')@(tsee
 rewrite) rules being handled by the @(see proof-builder)'s @('rewrite')
 (@('r')) command, in complete analogy to the change described just above for
 @(':')@(tsee type-prescription) rules.</p>

 <p>The installation instructions have been updated for obtaining GCL on a
 Macintosh.  Thanks to Robert Krug for supplying this information and to Camm
 Maguire for simplifying the process by eliminating the @('gettext')
 dependency.</p>

 <p>The macro @(tsee comp) is now an event, so it may be placed in @(see
 books).</p>

 <p>Previously, a @(tsee save-exec) call could fail because of file permission
 issues, yet ACL2 (and the underlying Lisp) would quit anyhow.  This has been
 fixed.  Thanks to Peter Dillinger for bringing this problem to our
 attention.</p>

 <p>Jared Davis, with assistance from David Rager, has updated his ordered sets
 library, @('books/finite-set-theory/osets/').  See file @('CHANGES.html') in
 that directory.</p>

 <p>A new function, @(tsee reset-kill-ring), has been provided for the rare
 user who encounters memory limitations.  See @(see reset-kill-ring).</p>")

(defxdoc note-2-9-5

; Things that seem too minor to mention:

; Modified translate11 to complain about LOCAL in code.  Before this fix, the
; definition
; (defun foo (x state) (local (value x)))
; caused (foo 3 state) to cause a hard error in getprop.

; Removed "time nice" from books/defexec/dag-unification/Makefile (doesn't work
; in some environments, as I recall).

; Added targets d64fsl and all-d64fsl to books/Makefile*, to support
; compilation of already-certified books on 64-bit OpenMCL.

; Added initial bindings of acl2-raw-mode-p and raw-mode-restore-lst to nil (in
; *initial-global-table*), as suggested by Peter Dillinger.

; Fixed warning stack issue with print-summary, which caused new
; theory-invariant implementation to avoid popping warning stacks because of
; with-output calls.

; Inlined call of equivalence-relation-to-geneqv with something more
; appropriate, and eliminated equivalence-relation-to-geneqv.

; Changed rewrite-with-lemmas so that :expand hints (from user or from
; induction) are always followed, without the being-openedp call that used to
; be there.

; The change for bodies (new 'def-bodies property) causes the following
; to use the latest definition for the body (e.g., affecting :expand
; hints).
; - non-rec-defun, called by deref for nu-rewriter
; - recursivep, called in rewrite-with-lemma and bdd-rules-alist1
; - expand-and-or, used by preprocess
; - non-recursive-fnnames, used only in warnings
; - proof-builder's expand command (hence also x and x-dumb commands)
; - induction heuristics that use controller-alist

; Modified extend-type-alist to add check for (not (fquotep term)), which had
; been assumed but was not necessarily true because of the call of
; extend-type-alist from extend-type-alist-with-bindings.

; Updated *current-acl2-world-key-ordering*, and comments about it.

; Replaced the use of proclaim by the use of declaim (thanks to Bob Boyer for
; the suggestion to consider this).

; Fixed typo in uncovered-equivs-alist, 'f instead of 'if, that could cause
; incorrect double-rewrite warnings.  But went beyond this and gave more
; appropriate special handling for 'if.

; Fixed obscure bug in maybe-push-undo-stack, which could happen with:
;
; :redef!
; (defun exit-boot-strap-mode () t)
;
; The problem was that we assumed that a *1* function is defined when its raw
; Lisp counterpart is defined.

; Added missing dependencies in books/ihs/Makefile.

; Changed chk-embedded-event-form so that it returns the expansion rather than
; the original form, in support of the implementation of make-event.

; Eliminated get-check-sums-lst and check-sum-file (dead code).

; Acl2-compile-file now loads the compiled file.

; Simplified *compiled-file-extension* according to a suggestion from Gary
; Byers.

; With Robert Krug's help, including arithmetic-3/bind-free/top will now print
; a message about turning on non-linear.

; Made slight improvement in ev-fncall-guard-er-msg so that we don't suggest
; set-guard-checking nil when the problem is safe-mode or stobjs.

; Documentation and comments have been changed, for the most part, so that the
; word ``multiple'' is used correctly.  Thanks to David Russinoff for pointing
; out this issue.

; Fixed getpid$ for clisp to use 'system::process-id rather than 'process-id.
; This puts the process id into the name of TMP* files produced by :comp t,
; which hadn't been done for clisp because of the getpid$ bug.

; Changed definition of macro state-global-let* (specifically, changed
; definition of supporting function state-global-let*-cleanup) to produce much
; more compact code for large numbers of bindings as in
; protect-system-state-globals.  Without that change, lispworks
; reported:
; **++++ Error in ACL2::PROTECTED-EVAL-WITH-PROOFS:
;   Function size 87365 is too large.

; Eliminated compiler note "Ignoring free ignore declaration" for mbe, for
; CMUCL and SBCL (had already done so for OpenMCL).

; Fixed a bug in make-include-books-absolute that caused an "Implementation
; error" when with-output occurs in a progn with an include-book in the
; certification world, as in:
; (progn (include-book "cowles/acl2-asg" :dir :system)
;        (with-output :off summary (defun abc (x) x)))

; Added a call to the garbage collector before saving in Allegro CL, CMUCL,
; SBCL, CLISP, and OpenMCL.  (There was already such a call in GCL and
; LispWorks.)  We saw a little performance increase and significant shrinkage
; of the saved image when we did this for Allegro CL.

  :parents (release-notes)
  :short "Changes in Version  3.0 since Version  2.9.4"
  :long "<p>Fixed a bug in @(tsee cw-gstack) that was causing a hard error when
 attempting to report on a forced assumption.  Thanks to Jared Davis for
 pointing this out and sending an example that helped us to determine a
 fix.</p>

 <p>Added @(tsee set-backchain-limit) to the set of legal @(see events) that
 can be placed in @(tsee encapsulate) forms and @(see books).  Thanks to John
 Cowles for bringing this issue to our attention.</p>

 <p>Fixed a bug that broke @('wet').  Thanks to David Rager for bringing this
 bug to our attention.</p>

 <p>Guard verification now evaluates ground subexpressions (those with no free
 variables) when computing the guard conjecture for the body of a function.
 Thanks to Jared Davis for useful conversations leading to this change.  See
 @(see verify-guards), in particular its ``Note on computation of guard
 conjectures and evaluation'' near the end of that topic, for more details.</p>

 <p>Added a warning when a @(tsee theory-invariant) is redefined.  Thanks to
 Jared Davis for suggesting a warning in this case and providing an informative
 example.  Also, @(tsee theory-invariant)s are now maintained more completely,
 as they are checked at the end of every event except for events executed on
 behalf of an @(tsee include-book) or the second pass of an @(tsee
 encapsulate).</p>

 <p>Fixed the handling of runic designators to match their specification (see
 @(see theories)), so that disabling the name of a @(tsee defthm) event @(tsee
 disable)s all rules generated for that event.</p>

 <p>(For those who do numerous builds using feature @(':acl2-mv-as-values'),
 currently only OpenMCL and multi-threaded SBCL by default:) You can speed up
 builds by adding the following parameter to `make', under conditions described
 in @('GNUmakefile'): @('USE_ACL2_PROCLAIMS=:REUSE').</p>

 <p>Arranged that traced functions (see @(see trace$)) are automatically
 untraced when events are undone (for example see @(see ubt)), at least for
 most underlying Common Lisp implementations.</p>

 <p>The macro @(tsee defun-sk) now creates non-executable functions, which
 allows @(tsee stobj)s to be used where they had previously been prohibited.
 More generally, the user now has control over @(tsee declare) forms to be used
 by the underlying @(tsee defun)'d function; see @(see defun-sk).  Thanks to
 Sandip Ray for pointing out the need for such a modification.</p>

 <p>@(':')@(tsee Definition) rules are now treated, at least by default, as
 truly first-class definitions.  In particular, @(':expand') @(see hints) use
 the latest @(':')@(tsee definition) rule by default.  You may specify
 @(':install-body nil') to get the previous behavior of @(':definition') rules;
 See @(see definition), and you may choose a previously-installed
 @(':definition') rule to provide the current body; see @(see set-body).  Also
 see @(see rule-classes) for details of the @(':install-body') field, and see
 @(see hints) to see a new @(':with') directive for controlling expansion.  The
 @(':with') directive for @(':expand') hints can even direct the use of a
 @(':')@(tsee rewrite) rule for expansion!  Thanks to various people, including
 Sandip Ray and Rob Sumners, for discussions on the issue of the applicability
 of @(':definition') rules for @(':expand') @(see hints).</p>

 <p>@(see Constraint)s for functional instantiation now use the original
 definition rather than a simplified (``normalized'') version of it.</p>

 <p>Fixed a bug that caused the prompt to stay the same when guard-checking is
 off (see @(see set-guard-checking)) and raw-mode is changed (see @(see
 set-raw-mode)).</p>

 <p>Lemma names in directory @('books/ordinals') have been changed by replacing
 @('/\\') with @('&') and replacing @('\\/') with @('V').  We made this change
 because backslash is an escape character and hence disappears unless it is
 itself escaped.</p>

 <p>Fixed @(see proof-tree) output so that failed non-proof events do not cause
 the proof-tree to be re-printed.  Thus for example, if you have already
 advanced the checkpoint marker, it will not be reset by subsequent failed
 non-proof events.  Thanks to Pete Manolios and Peter Dillinger for bringing
 this bug to our attention.</p>

 <p>Fixed a bug that was preventing the printing of @(see stobj) fields as
 constants instead of numbers in certain cases.  (Note that this bug only
 affected printing, not soundness.) Thanks to Eric Smith for bringing this
 problem to our attention and providing the following example (which now works
 fine).</p>

 @({
  (defstobj st fld1 fld2)
  (in-theory (disable update-nth))
  (defund run (st)
    (declare (xargs :stobjs (st))) ;adding this didn't seem to help..
    st)

  ;works great; *fld1* prints as  *fld1*
  (thm (equal (update-nth *fld1* 'abc st)
              (car (cons x y))))

  ;*fld1* gets printed as 0, presumably because the call to run intervenes.
  (thm (equal (update-nth *fld1* 'abc (run st))
              (car (cons x y))))
 })

 <p>The macro @(tsee progn) now allows the use of macros defined within its
 bodies even when at the event level, as illustrated by the following
 example.</p>

 @({
  (progn (defmacro my-defun (&rest args)
           `(defun ,@args))
         (my-defun g (x) x))
 })

 <p>Thanks to Anna Slobodova for bringing this issue to our attention.  A
 related change is that all arguments of @(tsee progn) must now be embedded
 event forms (see @(see embedded-event-form)), so use @(tsee er-progn) instead
 if this is not the case.</p>

 <p>The change to @(tsee progn) mentioned above also fixes a bug in handling
 @(see local) events inside a @(tsee progn) that is inside an @(tsee
 encapsulate) or in a book.  For example, the following form formerly caused an
 error.</p>

 @({
  (encapsulate
   ()
   (defun foo (x) x)
   (progn (local (defun bar (x) x))
          (defun abc (x) x)))
 })

 <p>We fixed two bugs in @(':')@(tsee puff) and @(':')@(tsee puff*).  The
 first, brought to our attention by Eric Smith (who we thank), caused a cryptic
 error message when puffing a command with no subsidiary stored events; try,
 for example, @('(encapsulate () (value-triple 3))').  The second was due to a
 failure to restore the @(tsee acl2-defaults-table).  Suppose for example that
 we have certified the book @('foo.lisp'), which contains @('(')@(tsee
 program)@(')') followed by some definitions and/or theorems.  Now suppose we
 start ACL2 and execute the following.</p>

 @({
  (include-book \"foo\")
  (defthm test-thm
    (equal x x)
    :rule-classes nil)
 })

 <p>If we now execute @(':')@(tsee puff)@(' 1'), ACL2 will roll back the world
 to before the @(tsee include-book); then ``puff'' the include-book, which will
 leave us in @(':')@(tsee program) mode; and finally skip re-execution of the
 @(tsee defthm) because such @(see events) are skipped in @(':')@(tsee program)
 mode.  The fix is to re-install the @(tsee acl2-defaults-table) immediately
 after the @(tsee include-book) to its pre-@(tsee include-book) value.</p>

 <p>A new event, @(tsee make-event), provides something like macros that take
 state.  For example, one can use it to put tests into certified books, do
 proof search, and generate new function names.  Many examples appear in
 directory @('books/make-event/').  See @(see make-event).  Thanks to Bob Boyer
 and Jared Davis for useful feedback and to Warren Hunt, David Rager, and
 Sandip Ray for helpful discussions leading to some of the examples in
 directory @('books/make-event/').</p>

 <p>In support of @(tsee make-event), which is described in the preceding
 paragraph, @('certify-book') has a new keyword argument, @(':save-expansion'),
 that controls whether the result of expanding @(tsee make-event) forms is
 written out to a file.  See @(see certify-book); and for a discussion of book
 expansion files, see @(see make-event).</p>

 <p>We fixed a soundness bug that did not correctly detect @(tsee local)
 events.  For example, the following event was admitted.</p>

 @({
  (encapsulate
   ()
   (local
    (encapsulate
     ()
     (local (progn (program))) ; or, (local (with-output :off summary (program)))
     (set-irrelevant-formals-ok t)
     (defun foo (x)
       (declare (xargs :measure (acl2-count x)))
       (1+ (foo x)))))
   (defthm inconsistent
     nil
     :hints ((\"Goal\" :use foo))
     :rule-classes nil))
 })

 <p>A new value for @(see guard) checking, @(':none'), is now allowed.  If you
 execute @(':')@(tsee set-guard-checking)@(' :none'), then no guard checking
 will take place (but raw Lisp code will not be executed in this case).  As a
 result, you should never see a guard violation, even for calls of
 @(':')@('program') mode functions.  We thank Pete Manolios, who has long
 wanted this feature, and also Peter Dillinger, for asking for it.  New
 documentation explains the interaction between the @(see defun-mode) and the
 value supplied to @(':')@(tsee set-guard-checking).  See @(see
 guard-evaluation-table), see @(see guard-evaluation-examples-script), and see
 @(see guard-evaluation-examples-log).</p>

 <p>In the course of adding the @(see guard)-checking value @(':none')
 described in the paragraph above, we eliminated an optimization that
 eliminated guard checking for some recursive calls of @(':')@(see logic) mode
 mutually-recursive functions that have not had their guards verified.  But we
 doubt that this change will be noticed by any users!)</p>

 <p>The ACL2 hyper-card has been enhanced, thanks to David Rager, with a
 listing of ``Useful EMACS Commands'' to match comments in
 @('emacs/emacs-acl2.el').</p>

 <p>Users contributed books following the @('Readme.lsp') methodology:
 @('data-structures/memories') and @('unicode') (Jared Davis), @('proofstyles')
 (Sandip Ray and J Moore).</p>

 <p>Made some improvements to @('books/Makefile-generic') (a file discussed
 elsewhere; see @(see books-certification-classic)).  In particular, improved
 handling of @('.acl2') files for @('dependencies') target.</p>

 <p>(Only OpenMCL and, with feature @(':acl2-mv-as-values'), GCL) Fixed a bug
 that was causing proclaiming to fail when definitions are submitted
 interactively.</p>

 <p>The default stack size has been increased for several lisps.</p>

 <p>(Very technical) A restriction has been weakened on the use of @(tsee
 local) @(see stobj)s under a call of an ACL2 evaluator (@('trans-eval') or
 @('simple-translate-and-eval')).  Now, the error can only take place for
 @(tsee stobj) names that occur in the term being evaluated.  Thanks to Erik
 Reeber for bringing this issue to our attention.</p>

 <p>The notion of ``ancestor'' has been changed slightly.  This notion is used
 by extended metafunctions and @(see break-rewrite) (see @(see
 extended-metafunctions) and see @(see brr@)), and also with backchain limits
 (see @(see backchain-limit) and see @(see set-backchain-limit)).  Basically,
 each time a hypothesis is encountered during application of a @(see rewrite)
 rule, that hypothesis is pushed (after instantiating and negating) onto the
 current list of ancestors before it is rewritten.  However, hypotheses of the
 form @('(equal var term)'), where @('var') is free (see @(see
 free-variables)), had not been included in the ancestors (similarly for
 @('(equiv var (double-rewrite term))') where @('equiv') is a known @(see
 equivalence) relation).  Now such ``binding hypotheses'' are included in a
 special way in ancestors data structures.  In particular, @('(null
 (mfc-ancestors mfc))') will now be true if and only if the term being
 rewritten is part of the current goal as opposed to a hypothesis from a rule
 encountered during backchaining, even if that hypothesis is a binding
 hypothesis.  Thanks to Dave Greve for bringing this issue to our
 attention.</p>

 <p>Termination and induction analysis now continue through both arguments of
 @(tsee prog2$), not just the second.  (Normally, the gathering up of @(tsee
 if) tests stops at function calls; but it continued through the second
 argument of @(tsee prog2$), and now it will continue through both arguments.)
 Thanks to Sol Swords for discussion leading to this change.</p>

 <p>The ACL2 distribution is now kept on the http server rather than the ftp
 server (but the home page has not been moved).  Thanks to Robert Krug for
 letting us know that some ACL2 users have found it inconvenient to fetch ACL2
 using ftp.</p>

 <p>The file @('books/README.html') has been renamed to @('books/Readme.html'),
 since some browsers don't show the former in the directory listing.</p>")

(defxdoc note-3-0

; See note-2-9-5 for some comments enumerating changes not in the :doc since
; v2-9-4.

  :parents (release-notes)
  :short "ACL2 Version  3.0 (June, 2006) Notes"
  :long "<p>Please see @(see note-2-9-5) for a description of changes since
 Version 2.9.4.  These include the new @(tsee make-event) feature, a soundness
 bug fix, an improvement for @(':expand') @(see hints), evaluation in the logic
 by way of @(':')@(tsee set-guard-checking)@(' :none'), and many other
 improvements.</p>

 <p>More generally, there have been several incremental releases since Version
 2.9: see @(see note-2-9-1), see @(see note-2-9-2), see @(see note-2-9-3), see
 @(see note-2-9-4), and see @(see note-2-9-5).</p>

 <p>A very few users have contributed books following the instructions on the
 web.  We expect that when more contributions come in, we will give more
 attention to the question of how to organize the distributed and workshop
 books.  For now, we have simply added the new contributions according to the
 old-style distribution methodology.</p>")

(defxdoc |NOTE-3-0(R)|
  :parents (release-notes)
  :short "ACL2 Version  3.0(r) (June, 2006) Notes"
  :long "<p>No significant changes have been made since Version 2.9 for support
 of non-standard analysis in particular.</p>

 <p>Please also see @(see note-3-0) for changes to Version 3.0 of ACL2.</p>")

(defxdoc note-3-0-1

; Things that seem too minor to mention:

; Modified proclaiming to understand (declare (type fixnum ...)) for function
; arguments.

; Regarding the subsumption item below: We still do the old subsumption check
; for chk-evaluator and processing of :by hints, because the user has some idea
; in these cases of what is going on (plus, the former will probably always be
; fast).  But we do the restricted check in the clause-set-subsumes call of
; chk-acceptable-equivalence-rule and (for induction) in
; some-pool-member-subsumes because those are kind of subtle and it's OK if
; they fail.

; The new requirement on the argument of satisfies resulted in an extra wrld
; argument for translate-declaration-to-guard (and other source functions),
; which is used in several books.

; Took suggestion from Bob Boyer to arrange to throw out extra values returned
; by intern, for efficiency (see intern-in-package-of-symbol and comments "See
; comment in intern-in-package-of-symbol").

; Fixed *initial-global-table* to satisfy ordered-symbol-alistp, and added a
; check for this just after the definition of *initial-global-table*.

; The improvement in handling of theories included an extra argument in
; set-difference-theories-fn and in union-theories-fn, lst1-known-to-be-runic.
; Users who are sophisticated and brave enough to use these unadvertised
; internal functions should be able to figure out this change, so we choose not
; to confuse other users by mentioning that in this :doc topic.

; Regarding the item below on hard lisp error and safe mode: We added a number
; of function/macro symbols to the list in *oneify-primitives* and to avoid
; oneifying, in order to support the use of safe-mode with make-event (which
; however we have abandoned for now because it seems difficult to ensure that
; we are dealing properly with *1* functions with corresponding hand-coded raw
; Lisp definitions).  We also fixed bugs discovered as we attempted to certify
; the books/make-event books:
; - state-global-let*-get-globals to use f-boundp-global in place of
;   boundp-global;
; - the call of fmt1 in print-warnings-summary;
; - the call (eq new-type-alist type-alist) in type-alist-clause-finish; and
; - the calls of eq in changed-pot-vars.

; Oneify-cltl-code has been slightly optimized for the case that
; 'guard-checking-on is :none, by eliminating some code that has no effect.

; The event comp now compiles properly for lists of functions even when some
; are in the boot-strap world.  In general, the code for
; compile-uncompiled-defuns and compile-uncompiled-*1*-defuns was cleaned up
; considerably, including the removal of proclaiming since add-trip is
; responsible for that.

; Deleted now-dead code collect-ideal-user-defuns and
; collect-ideal-user-defuns1.

; Among the "miscellaneous efficiency improvements not listed above" is an
; improvement to assume-true-false, which now takes an ignore argument that
; avoids some computation of the true-type-alist or false-type-alist when these
; are to be thrown away anyhow.

; Improved the "Guards" warning from certify-book to avoid rather odd mention
; of loading into raw Lisp.  Thanks to Sandip Ray and Robert Krug for helpful
; discussions.

; Modified documentation for topics ``~ilc[brr]'' and ``~ilc[breaks]'' to
; clarify that if you are at a raw Lisp break, then ~c[(]~ilc[abort!]~c[)] will
; get you back to the ACL2 top level.  Thanks to Dave Greve and Eric Smith for
; bringing this issue to our attention.

; Made minor mods, e.g. to avoid an eq test of n against header in the raw Lisp
; code for aref1.

; Improved support for window interfaces, in particular with new state globals
; window-interface-prelude and window-interface-postlude, thanks to
; contributions from Peter Dillinger.

  :parents (release-notes)
  :short "ACL2 Version  3.0.1 (August, 2006) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the
 documentation has been updated to reflect all changes that are recorded
 here.</p>

 <p>Fixed a soundness bug, introduced in the previous release, due to a failure
 to disallow @(tsee table) @(see events) that set the @(tsee
 acl2-defaults-table) in a @(tsee local) context.  Here is a proof of @('nil')
 that exploits the bug.</p>

 @({
  (encapsulate ()
   (local (program))
   (defun foo ()
     (declare (xargs :measure 17))
     (+ 1 (foo))))
  (thm
   nil
   :hints ((\"Goal\" :in-theory (disable foo (foo)) :use foo)))
 })

 <p>Fixed a bug in the alternatives to @(tsee good-bye), which are the @(tsee
 exit) and @(tsee quit) commands.  Thanks to Jared Davis and Peter Dillinger
 for pointing this out right away.</p>

 <p>The definition of @(tsee len) has been highly optimized in raw Lisp.
 Thanks to Bob Boyer and Warren Hunt for suggesting such an improvement and
 providing a lot of help in coming up with the current implementation.</p>

 <p>The clause subsumption algorithms have been improved, both to improve
 efficiency during warnings for @(':')@(tsee rewrite) rules and to punt when
 the subsumption computation for induction appears to be blowing up.  Thanks to
 Robert Krug for bringing this issue to our attention and supplying a useful
 example.</p>

 <p>A bug has been fixed that prevented @(tsee time$) from working properly in
 OpenMCL and multi-threaded SBCL (actually, in any ACL2 image where feature
 @(':acl2-mv-as-values') is present).  Thanks to Sol Swords for bringing this
 problem to our attention.</p>

 <p>A @(see type-spec) of the form @('(satisfies pred)') carries the
 requirement that @('pred') be a unary function symbol in the current ACL2
 @(see world); otherwise, it is illegal.  Thanks to Dave Greve for pointing out
 that Common Lisp has this requirement.</p>

 <p>Installed a fix provided by Gary Byers (for ACL2 source function
 @('install-new-raw-prompt')), for OpenMCL, that fixes an issue exposed in some
 versions of OpenMCL when compiler optimization is off.</p>

 <p>Fixed a bug in contributed book @('misc/untranslate-patterns.lisp') that
 was causing calls of @('add-untranslate-pattern') to be rejected in @(see
 books).  Thanks to Ray Richards for pointing out this bug and to Jared Davis
 for assisting in the fix.</p>

 <p>Fixed a bug in @(tsee defstobj) when keywords @(':initially') and
 @(':resizable') are both supplied.  In this case, the definition of the
 resizing function mistakenly failed to quote the @(':initially') value, even
 though this value is not to be evaluated.  One could even get an error in this
 case, as in the following example supplied by Erik Reeber, whom we thank for
 bringing this bug to our attention:</p>

 @({
    (defstobj $test
      (test-x :type (array t (5)) :initially (0) :resizable t))
 })

 <p>A new feature, @(tsee with-prover-time-limit), allows the setting of time
 limits during proofs.  This is <b>not</b> a general-purpose time-limit
 utility, nor is it guaranteed to implement a strict bound; it only attempts to
 limit time approximately during proofs.  Thanks to Pete Manolios and Daron
 Vroon, who made the most recent request for such a feature, and to Robert Krug
 for a helpful discussion.</p>

 <p>(GCL only) Fixed a bug in the procedure for building a profiling image.
 Thanks to Sol Swords for bringing this bug to our attention and to Eric Smith
 for bringing a subsequent problem to our attention.</p>

 <p>Handling of @(see theories) can now use significantly less time and space.
 A regression suite run took about 25% longer before this change than it did
 after making this change (and also the ones in the next two paragraphs).
 Thanks to Vernon Austel for bringing this issue to our attention and for
 supplying code, quite some time ago, that provided detailed, useful
 implementation suggestions.  Also thanks to the folks at Rockwell Collins,
 Inc. for pushing the limits of the existing implementation, thus encouraging
 this improvement.</p>

 <p>Fixed a performance bug in obtaining executable counterpart symbols.</p>

 <p>We now avoid certain computations made on behalf of warnings, when such
 warnings are disabled.</p>

 <p>We have relaxed the checks made when including an uncertified book, to
 match the checks made when including a certified book.  Thanks to Eric Smith
 for suggesting this change.</p>

 <p>Fixed a bug in @(':')@(tsee pso) (see @(see set-saved-output)) that caused
 an error when printing the time summary.</p>

 <p>Made fixes to avoid potential hard Lisp errors caused by the use of
 @(':')@(tsee program) mode functions.  The fix was to use a ``safe mode,''
 already in use to prevent such errors during macroexpansion; see @(see
 guards-and-evaluation).  However, such errors were possible during evaluation
 of macro @(see guard)s, for example as follows:</p>

 @({
  (defun foo (x)
    (declare (xargs :mode :program))
    (car x))
  (defmacro mac (x)
    (declare (xargs :guard (foo 3)))
    x)
  (defun g (x)
    (mac x))
 })

 <p>A similar issue existed for calls of @(tsee defpkg), @(tsee in-theory),
 @(tsee table), @(tsee make-event), and @('value-triple'), but has been fixed
 for all but @('in-theory') and @('make-event'), where technical issues have
 caused us to defer this change.</p>

 <p>Fixed a bug in @('wet') that caused problems in OpenMCL, and perhaps other
 Lisp implementations, when the argument to @('wet') calls, or depends on,
 certain built-ins including @(tsee prog2$), @(tsee time$), @(tsee mbe), and
 @(tsee must-be-equal).  Thanks to David Rager for bringing this problem to our
 attention.</p>

 <p>The file @('books/Makefile-generic') has been improved so that when book
 certification fails with `make', the failure message contains the book
 filename.</p>

 <p>Documentation has been written to explain how to avoid an expensive
 immediate rewrite of the result of applying a @(':')@(tsee rewrite) or
 @(':')@(tsee meta) rule.  See @(see meta).  Thanks to Robert Krug for
 supplying this trick, and to Eric Smith and Dave Greve for useful
 discussions.</p>

 <p>(OpenMCL only) OpenMCL-based ACL2 image names formerly had extension
 @('\".dppccl\"'), which was correct only for some platforms (including 32-bit
 Darwin PPC).  That has been fixed, thanks to a suggestion from Gary Byers.</p>

 <p>It is now legal to attach both a @(':use') and a @(':cases') hint at the
 same goal.  Thanks to Eric Smith for (most recently) requesting this
 feature.</p>

 <p>It is now permissible to include the same symbol more than once in the
 imports list of a @(tsee defpkg) form (i.e., its second argument).  Also, the
 evaluation of @(tsee defpkg) forms with long import lists now uses a
 reasonably efficient sorting routine to check for two different symbols with
 the same name (see also @('books/misc/sort-symbols.lisp')).  If you currently
 call a function like @('remove-duplicates-eql') for your imports list, as had
 been suggested by a @(tsee defpkg) error message, then you may experience some
 speed-up by removing that call.  Thanks to Eric Smith for helping to discover
 this issue through profiling.</p>

 <p>Made miscellaneous efficiency improvements not listed above (for example,
 following a suggestion of Eric Smith to avoid checking for so-called ``bad
 Lisp objects'' during @(tsee include-book), which saved almost 3% in time on
 one large example).</p>

 <p>Modified the notion of ``untouchable'' to separate the notion of
 untouchable functions and macros from the notion of untouchable state global
 variables.  See @(see push-untouchable).  Thanks to Bob Boyer for sending an
 example, @('(put-global 'ld-evisc-tuple t state)'), that suggested to us the
 need for more restrictive handling of untouchables.  In particular, many
 @('ld') specials (see @(see ld)) are now untouchable.  You may be able to work
 around this restriction by calling @(tsee ld); see for example the change to
 @('books/misc/expander.lisp').  But please contact the ACL2 implementors if
 this sort of workaround does not appear to be sufficient for your
 purposes.</p>

 <p>Fixed a bug in function @('set-standard-oi') (see @(see standard-oi)).</p>

 <p>Fixed a bug in the use of @(tsee ld-evisc-tuple).  The bad behavior was an
 improper use of the print-level and print-length components of the tuple
 (specifically, taking its @(tsee caddr) and @(tsee cadddr) instead of taking
 its @(tsee cadr) and @(tsee caddr)).  Thanks to Bob Boyer for bringing this
 bug to our attention.</p>

 <p>A new argument to the @('compile-flg') argument of @(tsee certify-book),
 @(':all'), causes creation of a file to be compiled in place of the given
 book, where that file contains not only a copy of the book (with @(tsee
 make-event) forms expanded) but also contains definitions of the so-called
 ``executable counterparts'' of the functions defined in the book.  Then,
 functions defined in the book will be run compiled when including the book,
 even for functions whose @(see guard)s have not been verified, or are in
 @(':program') mode and running in so-called ``safe mode'' (for example, during
 expansion of macros).  The default behavior, value @('t') of @('compile-flg'),
 is unchanged.  Moreover, a new @(':comp!') argument of @(tsee include-book)
 now compiles the executable counterparts when creating the book's compiled
 file, and unlike @(':comp'), always deletes the old compiled file first so
 that one always gets a fresh compile.</p>

 <p>Now, @(tsee certify-book) gives a \"Guards\" warning only for @(':')@(tsee
 logic) mode functions that are defined in the given book but have not had
 their guards verified.  Previously, it also warned about such functions that
 were defined in the certification world or in sub-books.</p>

 <p>A new command, @(tsee redo-flat), facilitates the debugging of failed
 @(tsee encapsulate) and @(tsee progn) forms by evaluating preliminary forms in
 order to leave one at the point of failure.  See @(see redo-flat).  Thanks to
 Ray Richards and others for asking for such a utility, and to Sandip Ray for
 useful discussions.</p>

 <p>We have changed the automatic declaration of of function types (still done
 in GCL and OpenMCL only, for now).  Our motivation was to avoid the assumption
 that Common Lisp functions return one value when ACL2 says that they do;
 thanks to Bob Boyer for bringing this issue to our attention with the example
 of defining @('(foo x y)') to be @('(floor x y)').  ACL2 was saying that
 @('foo') returns a single value, but because @('floor') returns two values in
 raw Lisp, so does @('foo').  Other changes to automatic declaration include
 comprehending @(tsee defund), not just @(tsee defun).</p>

 <p>A new function, @(tsee mod-expt), computes @('(mod (expt base exp) m)'),
 and does so efficiently in some implementations (currently only in GCL 2.7.0,
 which is not yet released).  Thanks to Warren Hunt for suggesting such an
 addition.</p>

 <p>New functions @(tsee getenv$) and @(tsee setenv$) have been made available
 for reading and writing environment variables.  Thanks to Jun Sawada for
 requesting these utilities.</p>

 <p>The query utility @(':')@(tsee pl) has been improved in several ways.  As
 before, @(':')@(tsee meta) rules are only printed if the argument is a symbol;
 but the information printed for them is now more appropriate.  The following
 are changes for the case that the argument is not a symbol, but rather, a
 term.  (1) Rules are displayed that have @(see equivalence) relations other
 than @(tsee equal).  (2) All matching @(':')@(tsee definition) rules are
 displayed, where previously @(':definition') rules were only shown if they
 were ``simple'' rules (sometimes known as ``abbreviations''); see @(see
 simple).  (3) The ``Equiv'' field is printed for terms, not just symbols.  (4)
 The substitution is shown that, when applied to the left-hand side of the
 rule, will yield the specified term.  Thanks to Eric Smith for suggesting
 these changes.</p>

 <p>The @(see proof-builder) command @(';show-rewrites') has been improved to
 match the changes described above for @(':')@(tsee pl).  In particular,
 @(':')@(tsee definition) rules that are not ``@(see simple)'' are now
 displayed by the @(see proof-builder)'s @('show-rewrites') (and @('sr'))
 command, and the @(see proof-builder)'s @('rewrite') command has been
 correspondingly modified to accept these @(':definition') rules.</p>

 <p>Fixed `make' targets @('copy-distribution'), @('copy-workshops'), and
 @('copy-nonstd') so that they should also work for non-developers.</p>

 <p>Fixed a bug that was causing @(':')@(tsee pr) to display @(tsee syntaxp)
 hypotheses oddly in some cases, in particular @('(syntaxp (let ...))').  (The
 problem was in the ``untranslate'' display of the internal form of
 @('syntaxp') calls.)  Thanks to Robert Krug for bringing this problem to our
 attention.  We also removed the restriction on @(tsee bind-free) that its
 argument could not be a variable, a constant, or (more interestingly) a @(tsee
 lambda) application (i.e., a @(tsee let) or @(tsee mv-let) expression).</p>")

(defxdoc |NOTE-3-0-1(R)|
  :parents (release-notes)
  :short "ACL2 Version  3.0.1(r) (August, 2006) Notes"
  :long "<p>No significant changes have been made since Version 3.0 for support
 of non-standard analysis in particular.</p>

 <p>Please also see @(see note-3-0-1) for changes to Version 3.0.1 of
 ACL2.</p>")

(defxdoc note-3-0-2

; Things that seem too minor to mention to users:

; Added ev-w and ev-w-lst.

; The "soundness bug in linear arithmetic" mentioned below was confined to
; linearize1.  Robert provided the fix and we checked it.  Below is an example
; from Robert that proves nil in ACL2 Version_3.0.1 but fails after the patch.

;  (defun id (x) x)
;
;  (defthm id-rationalp
;    (implies (force (rationalp x))
;             (rationalp (id x)))
;    :rule-classes :type-prescription)
;
;  (in-theory (disable id))
;
;  (defun id2 (x y)
;    (if (zp x)
;        y
;      (id2 (+ -1 x) y)))
;
;  (in-theory (disable (:type-prescription id2)))
;
;  (defthm bad
;    (implies (and (not (equal (id x) (id2 y z)))
;                  (acl2-numberp y)
;                  (integerp z)
;                  (<= 0 z))
;             (or (< (id x) (id2 y z))
;                 (< (id2 y z) (id x))))
;    :hints (("[1]Goal" :in-theory (enable (:type-prescription id2))))
;    :rule-classes nil)
;
;  (set-guard-checking :none)
;
;  (let ((x "foo")
;        (y 0)
;        (z 0))
;    (implies (and (not (equal (id x) (id2 y z)))
;                  (acl2-numberp y)
;                  (integerp z)
;                  (<= 0 z))
;             (or (< (id x) (id2 y z))
;                 (< (id2 y z) (id x)))))
;
;  (thm
;   nil
;   :hints (("Goal" :use (:instance bad (x "foo") (y 0) (z 0))))) ; |

; Added type declaration in ts-subsetp (but seemed not to make a measurable
; difference in time, at least for fast GCL build).

; Here is evidence for the bug in symbol-package-name-pkg-witness-name:

;  (defthm contradiction
;    nil
;    :hints (("Goal"
;             :use ((:instance symbol-package-name-pkg-witness-name
;                              (pkg-name ""))
;                   (:instance intern-in-package-of-symbol-symbol-name
;                              (x (pkg-witness ""))
;                              (y 3)))
;             :in-theory (disable (pkg-witness)
;                                 intern-in-package-of-symbol-symbol-name)))
;    :rule-classes nil)

; Implementation note: for reset-prehistory, the key idea is to manipulate
; world global 'command-number-baseline-info.

; Set ld-skip-proofsp to 'include-book during loading of compiled file by
; include-book.

; The "what could be considered a soundness hole" could be exploited as
; follows.

;     (in-package "ACL2")
;
;     ; Portcullis commands:
;     #|
;     (set-ld-redefinition-action '(:warn! . :overwrite) state)
;
;     (encapsulate
;      ()
;      (defun foo () t)
;      (local (defun foo () nil))
;      (defthm foo-prop
;        (equal (foo) nil)
;        :rule-classes nil))
;     |# ; |
;
;     ; NOTE: After the above commands:
;     ; ACL2 !>(redefined-names state)
;     ; NIL
;     ; ACL2 !>
;
;     ; Now execute:
;
;     ; (certify-book "bad" 1)
;
;     (defthm contradiction
;       nil
;       :hints (("Goal" :use foo-prop))
;       :rule-classes nil)

; After certifying the book we can do this:

; (include-book "bad")
; (thm nil :hints (("Goal" :use contradiction)))

; The documentation can now be built on Linux and probably Mac OS (seems that
; Linux texinfo issues have been solved).

; Made a correction in :doc guard-evaluation-table for built-in :program mode
; functions.

; Improved error message when compound event (including certify-book and
; include-book) has sub-event that is not an embedded event form.  If the
; sub-event is a macro call, then then "Note" at the end will give the original
; form as the macro call, not as the compound event.

; Improved max-output-type-for-declare-form-lst to add missing arguments in
; error message, as suggested by Robert.  Also improved
; max-output-type-for-declare-form to check for true lists before calling
; max-output-type-for-declare-form-lst.

; Improved translate error message from mutual-recursion so that the ctx
; identifies the problem function.  Thanks to Robert Krug for pointing out the
; value of making such an identification.

; Expanded *initial-global-table* to include all built-in state globals, so as
; do allow a more inclusive value of *protected-state-globals-for-make-event*
; (called *protected-system-state-globals* starting with v3-2).  Thanks to
; Peter Dillinger for pointing out that
; *protected-state-globals-for-make-event* was incomplete.

; In the course of implementing ttags for include-book-fn, we noticed that we
; were accessing a world with global-val (in particular on property
; 'boot-strap-flg) after calling chk-certificate-file, which calls
; chk-raise-portcullis, which can extend the world.  We fixed this to call
; global-val on an installed world instead.  It seems possible that for large
; proof efforts, this change might provide performance improvements.

; Moved Boyer's scary sys-call example from :doc make-event to :doc sys-call,
; since make-event isn't the issue.

; Here are the books changed to accommodate the fix for the soundness bug in
; the redundancy criterion for defun events.  It's possible that a few of these
; changes are no longer necessary now that we ignore the measure for redundancy
; when including books.
;
; workshops/2000/moore-manolios/partial-functions/report.lisp
; rtl/rel1/lib1/float.lisp
; rtl/rel1/lib1/round.lisp
; rtl/rel1/lib3/float.lisp
; rtl/rel1/lib3/round.lisp
; rtl/rel2/lib/bits.lisp
; rtl/rel2/lib/float.lisp
; rtl/rel3/lib/bits.lisp
; rtl/rel3/lib/float.lisp
;
; Problem with rtl/rel3/lib/top.lisp: can't have :? before real measure..
; Solution: Modify the following to use :? in expo:
; rtl/rel3/support/bvecp-lemmas.lisp
; rtl/rel4/support/bvecp-lemmas.lisp
; (Might not be necessary with the skip-proofs change, but it's a nice change
; anyhow.)
; Then also needed (even after skip-proofs mod) to make such a change in:
; rtl/rel4/lib/bvecp-raw-helpers.lisp
;
; rtl/rel4/lib/bits.lisp
; rtl/rel4/lib/float.lisp
; rtl/rel4/lib/fadd.lisp
; rtl/rel5/lib/log.lisp
; rtl/rel5/lib/float.lisp
; rtl/rel5/lib/add.lisp
; finite-set-theory/osets-0.9/sets.lisp
; finite-set-theory/osets/sets.lisp
; workshops/2004/davis/support/sets.lisp
; workshops/2000/russinoff-short/summary.lisp

; Improved the error message for a bad bind-free alist result, based on an
; example sent by Serita Nelesen to the acl2-help mailing list.

; Directory books/defexec/chapter3 has been renamed books/defexec/other-apps/
; because the records stuff is part of Section 4 of the corresponding paper,
; not Section 3.

  :parents (release-notes)
  :short "ACL2 Version  3.0.2 (December, 2006) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the
 documentation has been updated to reflect all changes that are recorded
 here.</p>

 <p>Fixed soundness bugs in the handling of primitive function @(tsee
 pkg-witness), and improved its documentation.  (The executable counterpart
 returned an incorrect default value, and the axiom
 @('symbol-package-name-pkg-witness-name') needed @('pkg-name') to be other
 than @('\"\"') in order to avoid the default value of \"ACL2\".)  As fallout,
 a new built-in @(':')@(tsee forward-chaining) rule,
 @('symbol-package-name-of-symbol-is-not-empty-string'), now asserts that the
 @(tsee symbol-package-name) of a symbol is never @('\"\"').  Thanks to Mike
 Gordon for bringing these soundness bugs to our attention by attempting to
 prove translations of ACL2 axioms in HOL4.</p>

 <p>Fixed a soundness bug in linear arithmetic, due to incomplete tracking of
 forced assumptions while deriving inequalities.  Thanks to Robert Krug for
 providing a fix and a proof of @('nil') before the fix.</p>

 <p>Fixed a soundness bug in the redundancy criterion for @(tsee defun) events,
 which has been modified; see @(see redundant-events).  This bug is illustrated
 below.  Thanks to Peter Dillinger and Jared Davis for contributions to an
 email thread that led us to discover this bug.  The solution is that for a
 definition to be redundant with an earlier definition, ACL2 no longer ignores
 @(':')@(tsee measure) @(tsee xargs) except when skipping proofs (e.g., during
 @(tsee include-book)).  However, a new ``measure'', @('(:? v1 ... vk)'), is
 supported, for specifying a measured subset of the set of formals, i.e., a set
 of formals that serves as the set of parameters for some valid measure.</p>

 @({
  (encapsulate
   ()

   (local (defun foo (x y)
            (declare (xargs :measure (acl2-count y)))
            (if (and (consp x) (consp y))
                (foo (cons x x) (cdr y))
              y)))

  ; So the following is redundant -- but it guesses a measure
  ; of (acl2-count x), which isn't right!
   (defun foo (x y)
     (if (and (consp x) (consp y))
         (foo (cons x x) (cdr y))
       y)))

  ; end of encapsulate

  ; Now we prove a non-theorem by exploiting the bug above,
  ; erroneously replacing formal y by a constant in the induction
  ; scheme hinted below.  (This should not be allowed, as y should be
  ; labeled as a measured formal.)

  (defthm bad
    (atom x)
    :rule-classes nil
    :hints ((\"Goal\" :induct (foo x '(3)))))

  ; It's easy to get a contradiction by instantiating the
  ; non-theorem just above.
  (defthm contradiction
    nil
    :rule-classes nil
    :hints ((\"Goal\" :use ((:instance bad (x '(7)))))))
 })

 <p>Fixed a bug in @(':')@(tsee pl) and the @(see proof-builder)'s
 @('show-rewrites') (@('sr')) command that was causing a Lisp break.  For
 @(':')@(tsee pl), also improved the display of unifying substitutions,
 modified output to take binding hypotheses @('(equal var term)') into account
 properly, and arranged for inclusion of @(see meta) rules that modify the
 given term.  Thanks to Eric Smith for bringing these issues to our
 attention.</p>

 <p>Introduced new utilities for undoing @(see command)s, @(':')@(tsee ubu) and
 @(':')@(tsee ubu!), which are analogous to @(':')@(tsee ubt) and @(':')@(tsee
 ubt!)  (respectively) except that they only undo back up to, but not
 including, the indicated command.</p>

 <p>Fixed a performance bug, pointed out by Eric Smith, that was negating
 efforts made for the preceding release to avoid computation for disabled
 warnings.</p>

 <p>Added @(tsee time$) and @('value-triple') to @('*acl2-exports*').  Thanks
 to Bob Boyer and Erik Reeber (respectively) for bringing these issues to our
 attention.</p>

 <p>Improved the automatic proclaiming of function types for GCL and OpenMCL,
 specifically to use an output format consistent with the Common Lisp spec.
 Thanks to Bob Boyer for bringing this issue to our attention.</p>

 <p>Added @('books/misc/transfinite.lisp'), which deals with transfinite
 induction in ACL2.  Thanks to Eric Smith for contributing this book.</p>

 <p>Added @('books/misc/process-book-readme.lisp') to the distribution.  Thanks
 to Sandip Ray for pointing out its omission.</p>

 <p>Added contributions @('books/concurrent-programs/bakery/') and
 @('books/concurrent-programs/german-protocol/').  These contributions can be
 used as tutorials, especially by new ACL2 users, for learning how to model
 concurrent protocols in ACL2 and the steps involved in reasoning about their
 correctness.  Thanks to Sandip Ray for these contributions.  See the
 @('Readme.lsp') files in these directories.</p>

 <p>Theory invariants may now involve the variable @('ENS') instead of the
 variable @('THEORY').  The practical effect of this change is that any
 expression of the form @('(MEMBER-EQUAL rune THEORY)') occurring in a @(tsee
 theory-invariant) expression should be replaced by @('(ACTIVE-RUNEP rune)').
 See @(see theory-invariant).  Thanks to Eric Smith and Dave Greve for pointing
 out an inefficiency in the handling of theory invariants that led to this
 change, which can speed up their handling by orders of magnitude on large
 examples, and to Eric for testing this change and pointing out problems with
 an early implementation of it.</p>

 <p>Theory invariants (see @(see theory-invariant)) are no longer checked on
 theories defined by @(tsee deftheory) @(see events).  After all, one can
 define a theory with @('deftheory') that is not intended to be used as the
 current theory, but rather is intended to be combined with other @(see
 theories) (see @(see theory-functions)).  Thanks to Eric Smith for bringing
 this issue to our attention.</p>

 <p>@(tsee Theory-invariant) errors had been reported with very little detail
 when warnings were inhibited.  This problem has been fixed; thanks to Eric
 Smith for bringing it to our attention and providing an example.  We have also
 improved the handling of redundancy for @(tsee theory-invariant) @(see
 events).</p>

 <p>The macro @(tsee defun-sk) now has a new optional keyword, @('rewrite'),
 that can be used to change the form of the @(':')@(tsee rewrite) rule
 generated when the quantifier is @(tsee forall).  Thanks to Eric Smith and
 Sandip Ray for useful discussions on this topic.  We have also slightly
 modified the @(see hints) for the @(tsee defthm) event underneath a
 @('defun-sk') in order to make the proof more reliably efficient.</p>

 <p>A new event, @(tsee reset-prehistory), allows setting of a barrier before
 which undoing is illegal.  An argument to this macro allows the barrier to be
 made permanent; otherwise, it can be removed with @(':')@(tsee
 ubt-prehistory).  Thanks to Peter Dillinger for useful conversations leading
 to the addition of @(tsee reset-prehistory).</p>

 <p>A new query, @('(')@(tsee wormhole-p)@(' ')@(tsee state)@(')'), allows
 users to determine whether or not they are in a @(tsee wormhole).  Thanks to
 Peter Dillinger for providing this utility.</p>

 <p>@('Value-triple') no longer evaluates its form during @(tsee include-book),
 and in raw Lisp its calls trivially macroexpand to @('nil'), without any
 consideration of its argument.  This change avoids errors and warnings when
 @(see stobj) names occur in the argument.</p>

 <p>We fixed what could be considered a soundness hole that could occur by
 exploiting redefinition in a particular way.  Thanks to Peter Dillinger for
 raising a question that led to discovery of this hole.</p>

 <p>A bug has been fixed in handling of illegal @(see theory) expressions.
 Thanks to Eric Smith, who reported this problem and provided the example
 @('(in-theory '((:definition natp) (:rewrite doesntexist)))') to show how a
 hard error could occur.</p>

 <p>Improved error reporting by @(tsee certify-book) when the certification
 @(see world) contains inadmissible forms.</p>

 <p>Modified @(tsee defchoose) to add two new keyword arguments.  There is now
 a @(':doc') keyword argument; previously, an optional documentation string
 (see @('doc-string')) was to be placed just before the body, without a
 keyword.  There is also a @(':strengthen') argument that strengthens the axiom
 added, which allows for the definition of ``fixing'' functions for equivalence
 relations that choose canonical representatives of equivalence classes.  See
 @(see defchoose).  Thanks for Dave Greve for useful discussions that led us to
 this @(':strengthen') enhancement.</p>

 <p>Added @('books/misc/bash.lisp'), which provides utilities for simplifying a
 goal into a list of subgoals (as documented at the top of that file).  Thanks
 to Dave Greve for requesting this utility and suggesting refinements to its
 functionality, which have been incorporated.</p>

 <p>(For Emacs users only) The command @('meta-x new-shell') provided by file
 @('emacs/emacs-acl2.el') now puts you in shell-mode, which for example
 supports directory tracking.  Thanks to Jared Davis for suggesting this
 change.</p>

 <p>Fixed some mishandling of @(see stobj)s by @(tsee make-event)
 expansion.</p>

 <p>Introduced a new event, @(tsee defttag), that introduces a ``trust tag''
 (``ttag'') allowing for extensions of ACL2 and for the use of generally unsafe
 ACL2 constructs.  Thanks to Peter Dillinger, Sandip Ray, and Erik Reeber for
 useful discussions on @('defttag') and the following related items.</p>

 <blockquote>

 <p>A new event, @(tsee remove-untouchable), can be used to give users access
 to system functions and data structures.  We also fixed a bug in @(tsee
 push-untouchable); and, it no longer is a no-op in @(':')@(tsee program) mode.
 Thanks to Peter Dillinger for proposing @(tsee remove-untouchable) and
 suggesting that it and @(tsee push-untouchable) be functional in @(':')@(tsee
 program) mode.</p>

 <p>Raw-mode (see @(see set-raw-mode)) no longer disables @(tsee certify-book).
 However, @(tsee set-raw-mode) is now disallowed unless there is an active ttag
 (see @(see defttag)).  If you want to execute @('(')@(tsee set-raw-mode)@('
 t)') and there is no active ttag, consider executing @('(')@(tsee
 set-raw-mode-on!)@(')') instead.</p>

 <p>Redefinition of system functions is disallowed unless there is an active
 ttag.  However, @(tsee redef!) now introduces @('(defttag :redef!)') in order
 to allow redefinition of system functions.</p>

 <p>A new event, @(tsee progn!), is a legal embedded event form that can go in
 @(see books) and both @(tsee encapsulate) and @(tsee progn) forms (see @(see
 embedded-event-form)), and is similar to @(tsee progn) except that it allows
 arbitrary forms.  Thus, a @(tsee progn!) form is potentially dangerous and can
 only be evaluated if there is an active ttag.</p>

 <p>See @(see ttags-seen) for information about how to find the ttags known in
 the current ACL2 @(see world), and for related caveats.</p>

 <p>A new book created with Peter Dillinger, @('books/misc/hacker.lisp') (added
 after Version_3.3: now @('books/hacking/hacker.lisp')), uses @(tsee progn!) to
 define utilities @('with-raw-mode') and @('with-redef-allowed'), which
 respectively allow raw Lisp evaluation and redefinition to take place within a
 certifiable book (!).</p></blockquote>

 <p>Macro @(tsee with-output) is no longer allowed in function bodies because
 it does not have (and has never had) any effect in raw Lisp.  See @(see
 with-output) for a workaround.</p>

 <p>Fixed a bug in redundancy of @(tsee defstobj) in raw Lisp, which caused an
 error when certifying a book with a redundant @(tsee defstobj) event whose
 @(tsee stobj) had already been modified.  Here is an example:</p>

 @({
  (defstobj st fld)
  (update-fld 3 st)
  (certify-book \"foo\" 1) ; where foo.lisp contains (defstobj st fld)
 })

 <p>New books illustrating @(tsee make-event) have been contributed in
 directory @('books/make-event/'): @('dotimes.lisp') (David Rager),
 @('stobj-test.lisp'), and @('logical-tangent.lisp') (Peter Dillinger).</p>

 <p>Modified @('print-object$') (see @(see io)) so that it no longer prints an
 extra space at the end.</p>

 <p>Replaced the ``draconian restriction to avoid capture'' that had prevented
 some @(':functional-instance') @(see hints) from being legal.  The
 corresponding check now only requires that no variable free in the functional
 substitution is captured by a @(tsee let) or @(tsee mv-let) (or @(tsee
 lambda)) binding.  See @(see lemma-instance).</p>

 <p>Added new extended metafunction, @('mfc-rw+'), which is equivalent to
 @('mfc-rw') except that it takes an alist argument, which may be useful for
 efficiency.  See @(see extended-metafunctions).  Thanks to Robert Krug for
 suggesting this more efficient variant of @('mfc-rw').</p>

 <p>Added support for the @('ignorable') @(tsee declare) form.</p>

 <p>We now cause an error on a call of @('open-input-channel') (see @(see io))
 with an argument string whose first character is the @('|') character.  Thanks
 to Bob Boyer for providing an example (several months ago) showing the danger
 of such calls, namely that the following command would log you out and kill
 all of your processes when running on top of GCL in Linux:<br></br>

 @('(open-input-channel \"|kill -9 -1\" :object state)')</p>

 <p>Restricted the use of @(tsee make-event) to contexts in which it can be
 tracked properly, under legal @(see events) (see @(see embedded-event-form)).
 Thanks to Peter Dillinger for bringing an example to our attention that led to
 this fix.</p>

 <p>Fixed a bug that was avoiding @(see guard)-checking for the functions
 @(tsee compress1) and @(tsee compress2).  Thanks to David Rager for bringing
 this bug to our attention.</p>

 <p>Added an error message when a @(tsee defun) or @(tsee mutual-recursion)
 event fails, to clarify whether failure is for the @(see measure) conjecture
 or for the @(see guard) conjecture.  Thanks to David Rager for requesting
 clarification for such failures.</p>

 <p>Fixed a bug in reporting of @(see guard) violations (hard Lisp error) when
 certain macros (for example, @(tsee cond)) are used in the @(see guard).
 Thanks to Jared Davis for bringing this problem to our attention and providing
 assistance with the solution, in particular by providing a helpful
 example.</p>

 <p>Grant Passmore has contributed a resolution/paramodulation prover written
 in ACL2, in directory @('books/deduction/passmore/').  Thanks, Grant.</p>

 <p>Improved the error message when illegal theories are encountered.</p>

 <p>Improved the suppression of output for @('inhibit-output') arguments of
 routines in the book @('books/misc/expander.lisp').  Thanks to Qiang Zhang for
 pointing out the possibility for improvement here.</p>

 <p>Added a new directory @('books/arithmetic-3/extra/') that extends
 @('books/arithmetic-3') with additional rules, contributed by Alex Spiridonov
 with guidance from Robert Krug.  WARNING: This directory is under development.
 It may undergo large changes in future releases, so please consider it
 experimental and subject to change.  Feedback is welcomed.</p>

 <p>As part of the work mentioned just above, Robert Krug and Alex Spiridonov
 contributed improvements to @('books/arithmetic-3/'):</p>

 <blockquote>

 <p>o A new rule @('|(* (/ x) (/ (expt x n)))|') in
 @('bind-free/collect.lisp'), which is important for reducing @('collect-*')
 expressions though it slowed down one proof (see comment above this rule in
 @('bind-free/collect.lisp')).</p>

 <p>o Slight improvements of rules @('integerp-mod') and @('rationalp-mod') in
 @('floor-mod/floor-mod.lisp').</p>

 <p>o To avoid conflict with @('books/rtl/rel6/arithmetic/'), renamed rule
 @('mod-minus') to @('mod-neg') in @('floor-mod/floor-mod.lisp'), and renamed
 @('integerp-+-reduce-leading-constant') to
 @('integerp-+-reduce-leading-rational-constant') in
 @('bind-free/integerp.lisp').</p></blockquote>

 <p>(GCL on Windows only) Made a low-level change to avoid multiplying stacks
 for GCL on Windows, since GCL 2.6.6 broke while doing this.</p>

 <p>Fixed bugs in linear arithmetic (rarely evidenced, it seems) involving
 using @('<') to compare complex rational constants.  Thanks to Robert Krug for
 helping with the fixes.</p>

 <p>Added a new event, @(tsee assert-event), for checking that forms evaluate
 to non-@('nil') values.  Thanks to Peter Dillinger for suggesting and
 collaborating on this addition.</p>")

(defxdoc note-3-1
  :parents (release-notes)
  :short "ACL2 Version  3.1 (December, 2006) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the
 documentation has been updated to reflect all changes that are recorded
 here.</p>

 <p>Please see @(see note-3-0-2) for a description of changes since Version
 3.0.1, and also see @(see note-3-0-1) for additional changes since Version
 3.0.</p>")

(defxdoc |NOTE-3-1(R)|
  :parents (release-notes)
  :short "ACL2 Version  3.1(r) (December, 2006) Notes"
  :long "<p>No significant changes have been made since Version 3.0 for support
 of non-standard analysis in particular.</p>

 <p>Please also see @(see note-3-1) for changes to Version 3.1 of ACL2.</p>")

(defxdoc note-3-2

; The "soundness bug that was allowing unknown packages" mentioned below was
; due to binding *inside-include-book-fn* to t in certify-book-fn, which was
; causing avoidance of the chk-bad-lisp-object check done by read-object.  Here
; is a proof of nil in Version_3.1.  Each book is to be certified in a fresh
; session (fresh for each book).

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ----------------
; Book sub.lisp:
; ----------------
; ; Portcullis command:
; ; (make-event (er-progn (defpkg "FOO" nil) (value '(value-triple nil))))
;
; (in-package "ACL2")
;
; (defconst *c* 'foo::a)
;
; (defthm thm1
;   (equal (symbol-package-name *c*) "FOO")
;   :rule-classes nil)
;
; ----------------
; Book top.lisp:
; ----------------
; ; Portcullis command:
; ; (defpkg "FOO" '(a))
;
; (in-package "ACL2")
;
; (include-book "sub")
;
; (defthm contradiction
;   nil
;   :hints (("Goal" :use thm1))
;   :rule-classes nil)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Here is Peter Dillinger's original example related to package stuff.  After
; certifying "pkg" (after executing the given defpkg) and then (after :ubt! 1)
; "use", then (include-book "use") will break (unknown package) in a new
; session when an attempt is made to read use.cert.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; File pkg.lisp:

; #| (defpkg "FOO" ()) |#
;
; (in-package "ACL2")
;
; (defun foo::foo () 42)
;
; (defun bar () '(value-triple (foo::foo)))

;;; File use.lisp:

; (in-package "ACL2")
;
; (include-book "pkg")
;
; (make-event (bar))
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; We came up with the following example when dealing with the issues exposed in
; the two examples above.  If you certify "book1", "book2", and then "top",
; with portcullis commands as shown, then (include-book "top") will break
; (unknown package) when run in a new session, when reading top.cert.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; File book1.lisp:

; ; (defpkg "P1" nil)
; ; (certify-book "book1" 1)
;
; (in-package "ACL2")
;
; (defun f1 (x) x)

;;; File book2.lisp:

; ; (defpkg "P1" nil)
; ; (defmacro my-id (x) x)
; ; (defpkg "P2" (my-id '(p1::a p1::b x y)))
; ; (certify-book "book2" 3)
;
; (in-package "ACL2")
;
; (defun f2 (x) x)

;;; File top.lisp:

; (in-package "ACL2")
;
; (include-book "book1")
;
; (local (include-book "book2"))
;
; (defun f3 (x) x)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Fixed a bug in books/arithmetic-3/extra/Makefile discovered by Gary Byers
; (our fault, not Alex Spiridonov's).  Also disabled two rules in ext.lisp in
; that directory, in part following suggestion of Robert Krug.

; Following a suggestion from Peter Dillinger, makunbound-global and put-global
; can now take a first argument that is not a quoted symbol, provided there are
; no untouchables.  The latter can be accomplished by, for example:
; (defttag t)
; (make-event
;  (let ((names (global-val 'untouchable-vars (w state))))
;    (value `(remove-untouchable (,@names) nil))))

; Made minor efficiency improvements to termination-machine.

; An expansion file is no longer written by certify-book if :save-expansion and
; the compile-flg are nil.

; Fixed a bug in ffnnames-subsetp that made it true too often when lambda terms
; are involved, and hence could allow probably-not-validp to be true too
; often.  This in turn could lead irrelevant-lits to return too large a list,
; which could lead eliminate-irrelevance-clause to strengthen the clause too
; much.  So this was a (probably rare) heuristic issue but not a soundness
; issue.

; Improved with-warnings-suppressed for Allegro and CLISP, and removed
; corresponding suppressions elsewhere since lp calls ld-fn under
; with-warnings-suppressed already.

; Installed fix from Robert Krug to
; books/arithmetic-3/bind-free/default-hint.lisp that prints messages when
; enabling or disabling nonlinear arithmetic using a particular computed hint.

; For the "subtle soundness bug related to ~c[:]~ilc[meta] rules" item below,
; the developer-only directory tests/meta/ has some relevant tests.

; Updated files books/Makefile* to comprehend OpenMCL compiled files on
; 64-bit Linux and Intel-based Macs.  Thanks to Robert Krug for pointing out
; that the ``clean'' target wasn't cleaning up such files.  Note however that
; we no longer create compiled files for OpenMCL anyhow.

; The raw version of mfc-rw appeared to be missing a throw in the case that the
; obj is not a member of '(t nil ?).  This has been fixed.

; Added a missing unsigned-byte (fixnum) declaration to rewrite-solidify-plus.

; Modified state-global-let* to take an optional ``setter'' function with each
; binding.

; For GCL, at Peter Dillinger's request, read-object now binds si::*notify-gbc*
; to nil (but only when reading from *standard-ci* or *standard-oi*).

; Fixed failure to lay down a command landmark when value :q is returned, e.g.:
; (er-progn (defun foo (x) x) (value :q))

; In maybe-add-command-landmark, eliminated redundant (eq wrld old-wrld) test
; that had been conjoined with (raw-mode-p state) check.

; Fixed complex comment about make-event in encapsulate-pass-2.

; Disallowed theory-invariant in code just as we do for table, in translate11.
; Also cleaned up theory-invariant a bit by separating out its raw Lisp version
; and removing its name from *macros-for-nonexpansion-in-raw-lisp*.

; Modified handling of state global 'inhibit-output-lst, so that if it's set
; during the expansion phase of a make-event, then it will persist.  Thanks to
; Jared Davis for asking about allowing the setting inhibit-output-lst as an
; embedded event form.

; Regarding "The rewriter has been tweaked to run faster": Here is the example
; from Eric (and Jared).  Note that we get a slow-down by a factor of about 10
; even without set-nu-rewriter-mode in versions before we added the following
; test near the end of rewrite, in v3-2:
; (not (member-eq (nu-rewriter-mode wrld) '(nil :literals)))

;  (defun repeat (n v)
;    (declare (xargs :guard (natp n)))
;    (if (zp n)
;        nil
;      (cons v (repeat (1- n) v))))
;
;  (defthmd len-of-cons
;    (equal (len (cons a x))
;           (+ 1 (len x))))
;
;  (in-theory (disable len))
;
;  (set-rewrite-stack-limit nil)
;
;  (set-nu-rewriter-mode t) ; slows things down by a factor of almost 20
;
;  (thm (equal (len (repeat 7000 a)) 7000)
;       :hints (("goal'" :in-theory (enable len-of-cons))
;               ("Goal"
;                :do-not '(preprocess)
;                :expand (:free (a x) (repeat a x)))))

; Regarding the slow array warning related to wormholes mentioned below: here
; is a way to cause that problem before Version_3.2.
;   (wormhole t 'interactive-break nil '(value 'hi!))
;   (in-theory (disable binary-append))
;   :a!
;   (thm (equal (car (cons x y)) x))

; The modification for tag-trees caused about a 1% slowdown.  However, a
; trivial modification to ancestors-check, which avoids recursion if ancestors
; is nil, caused about a 1.5% speedup.

; Here is how to cause the slow-array-warning mentioned below in Version_3.1
; and before.
;
; (wormhole t 'interactive-break nil '(value 'hi!))
; (in-theory (disable binary-append))
; :a!
; (thm (equal (car (cons x y)) x))

; Fixed books/Makefile-generic to use :ttags :all for include-book commands
; that support compilation (targets all-o, all-fasl, etc.).

; Fixed include-book with :load-compiled-file :comp (or :comp!) so that it
; always deletes a new expansion file.

; Built-in state global variables may no longer be made unbound with
; makunbound-global.  See always-boundp-global.

; Removed some noise printed even using with-output, e.g.:
; (with-output :off :all (encapsulate nil (program)))
; Thanks to Peter D. for requesting such a change.

; Make-event can now be used inside state-global-let* when there is an active
; trust tag.  See the discussion in :doc make-event of "the one exception to
; this restriction".  Also, we have eliminated compiler warnings for calls of
; progn!.  The problem was that state was unbound at a top-level call of
; progn!, but when we modified the raw Lisp code for progn! to bind state to
; *the-live-state*, we found that (pprogn .... (progn! ....)) was giving us a
; compiler warning since state no longer occurred free in the last form!  So we
; fixed pprogn as well to declare state ignorable above the last form.

; Fixed spacing after a period that was resulting in output such as the
; following after a successful termination proof:
;
; "admit this function under the principle of definition.We could deduce"

  :parents (release-notes)
  :short "ACL2 Version  3.2 (April, 2007) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Before this release, a raw Lisp error could put the ACL2 user into the
 debugger of the host Common Lisp.  Now, such cases will generally put the user
 back at the top-level loop after an informative message.  For details, see
 @(see set-debugger-enable); also see @(see break$).</p>

 <p>Fixed a soundness bug that was allowing unknown packages to sneak into a
 book and wreak havoc.  Thanks to Peter Dillinger for sending an interesting
 example that led us to an exploration resulting in finding this bug.  (A
 comment in the source code for @('note-3-2') shows such an example.)  That
 example led us to fix a couple of other bugs related to packages.  See @(see
 hidden-death-package) if you are generally interested in such issues, and for
 associated examples, see comments in @('note-3-2') in the ACL2 source
 code.</p>

 <p>Fixed subtle soundness bugs related to @(':')@(tsee meta) rules by
 restricting evaluators (see @(see defevaluator)), as discussed in a new
 documentation topic: see @(see evaluator-restrictions).</p>

 <p>Fixed a soundness bug that was allowing redefinition from @(':')@(tsee
 logic) to @(':')@(tsee program) mode.  This prohibition had been in ACL2 for
 awhile but was accidentally removed in the preceding version.</p>

 <p>Fixed a soundness bug related to @(tsee trace$).  Thanks to Peter Dillinger
 for bringing it to our attention and for useful discussions, and providing a
 proof of @('nil'), the essence of which is illustrated as follows:</p>

 @({
  (value-triple (trace$ (bar :entry (defun foo () 17))))
 })

 <p>Thus, @(tsee trace$) could be used to cause destructive raw Lisp behavior.
 Now, @('trace$') fails unless it is either given a list of symbols or else
 there is an active trust tag (see @(see defttag)); otherwise, consider using
 @('trace!') instead.</p>

 <p>Closed a loophole that could be viewed as compromising soundness.  It was
 possible to write files during book certification by exploiting @(tsee
 make-event) expansion, but that is no longer the case by default.  A new
 function @(tsee open-output-channel!) is identical as a function to
 @('open-output-channel'), except that the new function may be called even
 during @(tsee make-event) expansion and @(tsee clause-processor) @(see hints),
 but requires that there is an active trust tag (see @(see defttag)).  Thanks
 to Peter Dillinger for producing a convincing example (forging a @(see
 certificate) during book certification; see @(see open-output-channel!)) and
 to him, Sandip Ray, and Jared Davis for useful discussions on the topic.</p>

 <p>Added book @('books/defexec/reflexive/reflexive.lisp') to illustrate
 reflexive functions.</p>

 <p>ACL2 now generate scripts that invoke the saved image with @('exec').
 (Previously this was only done for GCL and CLISP.)  The benefit of this change
 can be to avoid the lingering of ACL2 processes after enclosing processes have
 exited.  Thanks to Peter Dillinger for pointing out this issue.</p>

 <p>ACL2 has a better implementation of @('(')@(tsee good-bye)@(')') (hence of
 synonyms @('(')@(tsee quit)@(')') and @('(')@(tsee exit)@(')')).  As a result,
 you should now be able to exit ACL2 and Lisp from within the ACL2
 read-eval-print loop with any of the above; formerly, this was not supported
 for some Lisp implementations, and was slow in OpenMCL.  Thanks to SBCL
 developer Harald Hanche-Olsen for useful advice.</p>

 <p>Fixed a bug in raw-mode (see @(see set-raw-mode)) that was causing hard
 errors when evaluating calls of @(tsee er-progn), or of macros expanding to
 such calls.</p>

 <p>Fixed a few Makefile dependencies, necessary only for parallel `make'.</p>

 <p>A new book, @('misc/defpun-exec-domain-example.lisp'), provides an example
 showing how partial functions which return a unique value for arguments in a
 specified domain can be efficiently executed with ACL2.  Execution is achieved
 using the @(tsee mbe) construct.  Thanks to Sandip Ray for providing this
 example.</p>

 <p>Existing function @(tsee mod-expt) computes @('(mod (expt base exp) mod)')
 with great efficiency in GCL, but not in other Lisps.  Now, the book
 @('arithmetic-3/floor-mod/mod-expt-fast.lisp') defines a function
 @('mod-expt-fast') that should provide significantly improved performance for
 such expressions in other Lisps as well, though still probably not as fast as
 when using @('mod-expt') in GCL.  Thanks to Warren Hunt, with contributions
 from Robert Krug, for providing this book,</p>

 <p>Modified macro @(see break-on-error) to print of an error message before
 entering a break, and to cause a hard error if the underlying Lisp cannot
 handle it (formerly, a raw Lisp break would occur).  Thanks to Bob Boyer for
 bringing these issues to our attention.</p>

 <p>The book @('books/misc/defpun.lisp'), as well as other books related to the
 @('defpun') macro, has been modified to avoid namespace collisions by
 prefixing function symbol names with @('\"DEFPUN-\"'); for example @('base')
 has been replaced by @('defpun-base').  Thanks to Dave Greve for providing a
 first version of this update to @('defpun.lisp').</p>

 <p>A theory, @('base'), in @('books/arithmetic-3/bind-free/top.lisp'), has
 been renamed @('arithmetic-3-bind-free-base'), to avoid potential name
 conflicts.</p>

 <p>Fixed @('books/arithmetic-3/bind-free/banner.lisp') to print (as before) a
 message about how to turn on non-linear arithmetic, by modifying the call of
 @('value-triple') to use @(':on-skip-proofs t').  Thanks to Robert Krug for
 bringing this issue to our attention.</p>

 <p>Modified @('books/Makefile-subdirs') and @('books/Makefile-psubdirs') so
 that they can be used with @('books/Makefile-generic').  Thus, one can set
 things up so that `make' can be used to certify books both in the current
 directory and subdirectories, for example as follows.</p>

 @({
    ACL2 = ../../saved_acl2

    arith-top: top all
    all: top

    DIRS = pass1 bind-free floor-mod
    include ../Makefile-subdirs
    include ../Makefile-generic

    top.cert: top.lisp
    top.cert: bind-free/top.cert
    top.cert: floor-mod/floor-mod.cert
    top.cert: floor-mod/mod-expt-fast.cert
 })

 <p>An experimental extension of ACL2 is under development by Bob Boyer and
 Warren Hunt to support function memoization, hash conses, and an applicative
 version of hash tables.  The default build of ACL2 does not include this
 extension, other than simple logic definitions of functions in new source file
 @('hons.lisp').  Future versions of ACL2 may fully incorporate this
 experimental extension.</p>

 <p>The @(tsee defevaluator) event macro has been modified primarily by adding
 a new constraint as follows, where @('evl') is the evaluator.  The idea is
 that for the evaluation of a function call, one may replace each argument by
 the quotation of its evaluation and then also replace the alist environment
 with @('nil').</p>

 @({
  (DEFTHMD UNHIDE-evl-CONSTRAINT-0
    (IMPLIES (AND (CONSP X)
                  (SYNTAXP (NOT (EQUAL A ''NIL)))
                  (NOT (EQUAL (CAR X) 'QUOTE)))
             (EQUAL (evl X A)
                    (evl (CONS (CAR X)
                               (KWOTE-LST (UNHIDE-evl-LIST (CDR X) A)))
                         NIL))))
 })

 <p>In order to support this change, there is another change: an evaluator maps
 @('nil') to @('nil') (note @('(AND X (CDR (ASSOC-EQ X A)))') in place of
 @('(CDR (ASSOC-EQ X A))') below).</p>

 @({
  (DEFTHM UNHIDE-evl-CONSTRAINT-1
    (IMPLIES (SYMBOLP X)
             (EQUAL (UNHIDE-evl X A)
                    (AND X (CDR (ASSOC-EQ X A))))))
 })

 <p>With the new @(tsee defevaluator), Dave Greve has been able to do a proof
 about beta reduction that seemed impossible before (see
 @('books/misc/beta-reduce.lisp')).  Thanks to Dave for suggesting an initial
 version of this change.</p>

 <p>Explicit compilation is now avoided for OpenMCL, resulting in fewer files
 to manage (no more files resulting from compilation) and, according to some
 tests, slightly faster run times.  See @(see compilation).  Thanks to Bob
 Boyer and Warren Hunt for suggesting this possibility.</p>

 <p>Now, the @('term-evisc-tuple') (see @(see ld-evisc-tuple)) is overridden by
 state global @('user-term-evisc-tuple') in all cases.  Formerly, this was only
 the case when @('term-evisc-tuple') was called with non-@('nil') first
 argument.</p>

 <p>Symbols with the dot (@('.')) character are generally no longer printed
 with vertical bars.  For example, before this change:</p>

 @({
    ACL2 !>'ab.c
    |AB.C|
    ACL2 !>
 })

 <p>After this change:</p>

 @({
    ACL2 !>'ab.c
    AB.C
    ACL2 !>
 })

 <p>Thanks to Jared Davis for suggesting this improvement.</p>

 <p>Fixed bugs in @('guard') verification for theorems.  The following examples
 illustrate these bugs.  If either theorem's body is executed in raw Lisp there
 is likely to be a hard Lisp error, even though @(tsee verify-guards) was
 supposed to ensure against that behavior.</p>

 @({
  ; Example: Verify-guards failed to check that all functions in the theorem
  ; had already been guard-verified.
  (defun my-car (x) (car x))
  (defthm my-car-compute-example (equal (my-car 3) (my-car 3)))
  (verify-guards my-car-compute-example)

  ; Example: Verify guards of a theorem whose body uses state improperly.
  (defthm bad-state-handler
    (if (state-p state)
        (equal (car state) (car state))
      t)
    :rule-classes nil)
  (verify-guards bad-state-handler)
 })

 <p>See @(see GCL) for an example, developed with Warren Hunt and Serita
 Nelesen, that shows how to get fast fixnum (small integer) arithmetic
 operations in GCL.</p>

 <p>Fixnum declarations are now realized as @('(signed-byte 30)') and
 @('(unsigned-byte 29)') instead of what was generally @('(signed-byte 29)')
 and @('(unsigned-byte 28)').  MCL users may thus find better performance if
 they switch to OpenMCL.  Note that some definitions have changed
 correspondingly; for example, @(tsee zpf) now @(tsee declare)s its argument to
 be of type @('(unsigned-byte 29)') instead of @('(unsigned-byte 28)').  A few
 @(see books) may thus need to be adjusted; for example, changes were made to
 books in @('books/data-structures/memories/').</p>

 <p>ACL2's rewriter now avoids removing certain true hypotheses and false
 conclusions.  When a hypothesis rewrites to true or a conclusion rewrites to
 false, ACL2 formerly removed that hypothesis or conclusion.  Now, it only does
 such removal when the hypothesis or conclusion is either a call of @(tsee
 equal) or an equivalence relation (see @(see equivalence)), or else is
 sufficiently trivial (roughly, either redundant with another hypothesis or
 conclusion or else trivially true without considering the rest of the goal).
 A specific example may be found in source file @('simplify.lisp'); search for
 ``; But we need to do even more work''.  Thanks to Robert Krug for providing
 the idea for this improvement and its initial implementation.  As is common
 with heuristic changes, you may find it necessary on occasion to rename some
 subgoals in your @(see hints).  And in this case, you might also find it
 necessary on rare occasions to add @(':do-not '(generalize)') @(see
 hints).</p>

 <p>A new function, @('mfc-relieve-hyp'), allows (for example) for more
 powerful @(tsee bind-free) hypotheses, by providing an interface to the
 rewriter's routine for relieving hypotheses.  See @(see
 extended-metafunctions).  Thanks to Robert Krug for providing the idea for
 this feature and its initial implementation.</p>

 <p>Two improvements have been made to non-linear arithmetic (see @(see
 non-linear-arithmetic)).  One allows for deducing strict inequality (@('<'))
 for the result of certain polynomial multiplications, where previously only
 non-strict inequality (@('<=')) was deduced.  A second allows the use of the
 product of two polynomials when at least one of them is known to be rational.
 We had previously restricted the use of the product to the case where both
 were known to be rational.  Thanks to Robert Krug for these improvements.</p>

 <p>(OpenMCL and Allegro CL only) Fixed ACL2's redefinitions of raw Lisp
 @('trace') and @('untrace') in OpenMCL and Allegro CL so that when given no
 arguments, they return the list of traced functions.  For @('trace'), this is
 an ANSI spec requirement.  Note that @(tsee trace$) and @(tsee untrace$)
 continue to return @('nil') in the ACL2 loop.</p>

 <p>Fixed a bug that was allowing the symbol @('&whole') to appear in other
 than the first argument position for a @(tsee defmacro) event, in violation of
 the Common Lisp spec (and leading to potentially surprising behavior).  Thanks
 to Peter Dillinger for bringing this bug to our attention.</p>

 <p>It had been illegal to use @(tsee make-event) under some calls of @(tsee
 ld).  This has been fixed.  Thanks to Jared Davis for bringing this issue to
 our attention with a simple example, in essence:</p>

 @({
  (ld '((defmacro my-defun (&rest args) `(make-event '(defun ,@args)))
        (my-defun f (x) x)))
 })

 <p>ACL2 no longer prohibits certain @(tsee make-event) forms when including
 uncertified @(see books).  Thanks to Peter Dillinger for first bringing this
 issue to our attention.</p>

 <p>Hard errors arose when using @(see break-rewrite) stack display commands,
 in particular @(':path') and @(':frame'), from inside the @(see
 proof-builder).  This has been fixed.</p>

 <p>Fixed a bug that could cause functions that call system built-ins
 @('f-put-global'), @('f-get-global'), or @('f-boundp-global') to cause a raw
 Lisp error even when proving theorems.  Thanks to Peter Dillinger, for
 reporting such a failure for the form @('(thm (w '(1 2 3)))').</p>

 <p>Renamed the formal parameters of function @('set-equal') in distributed
 book @('books/arithmetic-3/bind-free/normalize.lisp') so that more distributed
 books can be included together in the same session.  In particular books
 @('books/data-structures/set-theory') and
 @('books/arithmetic-3/extra/top-ext') can now be included together.  Thanks to
 Carl Eastlund for bringing this problem to our attention and to Robert Krug
 for suggesting the formals renaming as a fix.</p>

 <p>Metafunctions must now be executable.  See @(see meta).</p>

 <p>New utilities allow for user-defined simplifiers at the goal level, both
 verified and unverified (``trusted''), where the latter can even be defined by
 programs outside ACL2.  See @(see clause-processor), which points to a new
 directory @('books/clause-processors/') that contains examples of these new
 utilities, including for example a system (``SULFA'') contributed by Erik
 Reeber that implements a decision procedure (thanks, Erik).  Also see @(see
 proof-builder-commands) for the new @(see proof-builder) command
 @('clause-processor') (or for short, @('cl-proc')).</p>

 <p>The rewriter has been tweaked to run faster in some cases involving very
 large terms.  Thanks to Eric Smith and Jared Davis for providing a helpful
 example that helped us locate the source of this inefficiency.</p>

 <p>Added @('books/make-event/defspec.lisp').  This book shows how one can
 mimic certain limited forms of higher-order statements in ACL2 by use of
 macros, @(tsee make-event), and @(tsee table) events.  Thanks to Sandip Ray
 for his contribution.</p>

 <p>A new release of the RTL library, @('books/rtl/rel7/'), replaces the
 previous version, @('books/rtl/rel6/').  Thanks to Hanbing Liu and David
 Russinoff for providing this new version.</p>

 <p>We thank David Russinoff for providing a proof of the law of quadratic
 reciprocity.  See @('books/quadratic-reciprocity/Readme.lsp').</p>

 <p>Eliminated a slow array warning (see @(see slow-array-warning)) that could
 occur when exiting a @(see wormhole) after executing an @(tsee in-theory)
 event in that wormhole.  Thanks to Dave Greve for bringing this problem to our
 attention.</p>

 <p>A new accessor, @('(mfc-rdepth mfc)'), provides a new field, the remaining
 rewrite stack depth, which has been added to metafunction context structures;
 see @(see extended-metafunctions).  Thanks to Eric Smith for suggesting this
 addition.</p>

 <p>The algorithms were modified for collecting up rule names and other
 information used in proofs, into so-called ``tag-trees''.  Tag-trees are now
 free of duplicate objects, and this change can dramatically speed up some
 proofs that involve many different rules.  Thanks to Eric Smith for doing some
 profiling that brought this issue to our attention, and for reporting that
 this change reduced proof time on an example by about 47% (from 3681.46
 reported seconds down to 1954.69).</p>

 <p>All legal @('xargs') keywords may now be used in @(tsee verify-termination)
 @(see events).  In particular, this is the case for @(':normalize').</p>

 <p>(SBCL and CMUCL only) Fixed a problem with stobj array resizing functions
 that was causing a hard error in ACL2 images built on SBCL or CMUCL.</p>

 <p>A new @(see table), @(tsee evisc-table), allows you to introduce print
 abbreviations, for example for large constants.  Moreover, a new reader macro
 &mdash; @('#,') &mdash; makes it convenient to reference constants even inside
 a quote.  See @(see evisc-table).  Thanks to Bob Boyer and Warren Hunt for
 useful discussions leading to this feature.</p>

 <p>The macros in @('books/misc/expander.lisp') now have a new keyword
 argument, @(':simplify-hyps-p').  The default behavior is as before, but now
 case splitting from hypothesis simplification can be avoided.  For details,
 evaluate @('(include-book \"misc/expander\" :dir :system)') and then @(':doc!
 defthm?') and @(':doc! symsym').  Thanks to Daron Vroon for sending a question
 that prompted this additional functionality.</p>

 <p>ACL2 failed to apply @(':')@(tsee restrict) hints to rules of class
 @(':')@(tsee definition), except for the simplest sorts (see @(see simple)).
 This has been fixed.  Thanks to Jared Davis for pointing out this bug by
 sending a small example.</p>

 <p>Added a new @(':msg') argument to @('assert-event'); see @(see
 assert-event).  The implementation of @('value-triple') has been modified to
 support this change.</p>

 <p>Fixed a bug in macro @('io?') that now allows the @('commentp') argument to
 be @('t').  This provides a way other than @('cw') to print without modifying
 state, for example as follows.  (Warning: Certain errors may leave you in a
 @(see wormhole), in which case use @(':a!') to abort.)</p>

 @({
  ACL2 !>(prog2$ (io? event t state
                      ()
                      (fms \"Howdy~%\" nil *standard-co* state nil))
                 (+ 3 4))

  Howdy
  7
  ACL2 !>:set-inhibit-output-lst (proof-tree event)
   (PROOF-TREE EVENT)
  ACL2 !>(prog2$ (io? event t state
                      ()
                      (fms \"Howdy~%\" nil *standard-co* state nil))
                 (+ 3 4))
  7
  ACL2 !>
 })

 <p>ACL2 now disallows calls of @(tsee progn!) inside function bodies, just as
 it already disallowed such calls of @(tsee progn), since in both cases the
 Common Lisp meaning differs from the ACL2 meaning.</p>

 <p>Redefinition of system functions now always requires an active trust tag
 (see @(see defttag)).  This restriction was intended before, but there was a
 hole that allowed a second redefinition without an active trust tag.  Thanks
 to Peter Dillinger for pointing out this bug.</p>

 <p>@(tsee Verify-termination) has been disabled for a few more built-in
 functions that are in @(':')@(tsee program) mode.  (If you are curious about
 which ones they are, evaluate @('(f-get-global 'built-in-program-mode-fns
 state)').)  [Note added for Version_3.4: This state global has been changed to
 'program-fns-with-raw-code.]  Moreover, such functions now will execute only
 their raw Lisp code, so for example they cannot be called during
 macroexpansion.  Thanks to Peter Dillinger and Sandip Ray for useful
 discussions on details of the implementation of this restriction.</p>

 <p>New untouchable state global variables, @('temp-touchable-vars') and
 @('temp-touchable-fns'), can control the enforcement of untouchability.  See
 @(see remove-untouchable).  Thanks to Peter Dillinger for suggesting these
 features.</p>

 <p>The ``TTAG NOTE'' string was being printed by @(tsee encapsulate) events
 whenever an active trust tag was already in effect (see @(see defttag)), even
 if the encapsulate event contained no @(tsee defttag) event.  This has been
 fixed.  Thanks to Peter Dillinger for a query leading to this fix.</p>

 <p>Fixed a bug in @(tsee progn!) that could leave the user in raw-mode (see
 @(see set-raw-mode)).  This could occur when certifying a book with a
 @('compile-flg') value of @('t') (see @(see certify-book)), when that book
 contained a @(tsee progn!) event setting raw-mode to @('t') without setting
 raw-mode back to @('nil'):</p>

 @({
  (progn! (set-raw-mode t) ...)
 })")

(defxdoc |NOTE-3-2(R)|
  :parents (release-notes)
  :short "ACL2 Version  3.2(r) (April, 2007) Notes"
  :long "<p>Changed the default distributed @(see books) directory for ACL2(r)
 from @('books/') to @('books/nonstd/').  See @(see include-book), in
 particular the discussion of ``Distributed Books Directory''.</p>

 <p>Added directory @('books/arithmetic-3/') and its subdirectories to
 @('books/nonstd/').  (But a chunk of theorems from
 @('arithmetic-3/extra/ext.lisp') are ``commented out'' using
 #-:non-standard-analysis because they depend on @('books/rtl/rel7/'), which is
 not yet in @('books/nonstd/'); feel free to volunteer to remedy this!)</p>

 <p>Incorporated changes from Ruben Gamboa to some (linear and non-linear)
 arithmetic routines in the theorem prover, to comprehend the reals rather than
 only the rationals.</p>

 <p>Please also see @(see note-3-2) for changes to Version 3.2 of ACL2.</p>")

(defxdoc note-3-2-1

; Here is the proof of nil from Sol Swords referenced in the mbe bug discussion
; below.

;  (defun foo (a b)
;    (mbe :logic (mv a b)
;         :exec (mv a b)))
;
;  ;; (foo 'a 'b) returns (A NIL);
;  ;; should return (A B)
;
;  (defthm foo-1-nil
;    (equal (mv-nth 1 (foo 'a 'b)) nil)
;    :rule-classes nil)
;
;  (verify-guards foo)
;  ;; now the correct behavior returns:
;  ;; (foo 'a 'b) returns (A B).
;
;  (defthm foo-1-b
;    (equal (mv-nth 1 (foo 'a 'b)) 'b)
;    :rule-classes nil)
;
;  (thm
;   nil
;   :hints (("Goal" :use (foo-1-nil foo-1-b))))

; Modified warning$ a bit to avoid what appears to be a GCL compilation bug.

; Fixed *hons-primitives*, and hence *acl2-exports*, to be independent of
; whether or not #+hons.  This should make it possible to certify a book in the
; hons version and include it in the non-hons version, or vice-versa.

; Added patch for non-ANSI GCL to compiler::wrap-literals.

; Modified rune-< to comprehend the cddr of a rune.

; Added books/misc/misc2/ and put new book misc.lisp in it.

; Changed handling of built-in-program-mode-fns [called
; program-fns-with-raw-code starting in Version_3.4] outside boot-strap so that
; with guard-checking-on equal to :all or :none and safe-mode off, they behave
; the same as other functions.  Thanks to Peter Dillinger for this change.
; Also introduced two similar state globals -- logic-fns-with-raw-code and
; macros-with-raw-code -- and corresponding defconsts for the initial values of
; all three.  And, used the two *fns-with-raw-code state globals in place of
; *non-exec-fns* in compile-uncompiled-defuns, and eliminated *non-exec-fns*.

; Improved redefinition error message to show book in which redefinition is
; being attempted, in addition to already-shown book in which previous
; definition resides.

; Fixed books/clause-processors/Makefile so that "make clean" will also clean
; directories SULFA/c-files/ and SULFA/scripts/.

; Fixed error output redirection in books/Makefile-generic.  Now, for example,
; various tests under clause-processors/SULFA/ will now direct all output to
; .out files as expected, rather than producing some at the terminal.

; Here is the example promised in the release note below about "handling of
; computed hints related to the stable-under-simplificationp parameter".
; Consider a computed hint like the following (taken from an actual example).
;
; `(:computed-hint-replacement
;   ((adviser-default-hint id clause world stable-under-simplificationp))
;   :use ,(build-hints literals rules hyps nil)
;   :expand ,(build-expand-hint literals))
;
; Here is a new version, which after the fix causes the previous behavior.  The
; idea is that the bug caused ACL2 to go to the preprocess-clause ledge of the
; waterfall, rather than to the top where :use hints are processed.  Thus, the
; :expand hint was applied first, and then after a return to the top of the
; waterfall, the :use hint was applied.  With the new version just below, that
; behavior is encoded explicitly.
;
; `(:computed-hint-replacement
;   ('(:computed-hint-replacement
;      ((adviser-default-hint id clause world stable-under-simplificationp))
;      :use ,(build-hints literals rules hyps nil)))
;   :expand ,(build-expand-hint literals))

; Sped up checksums by perhaps 5% in GCL by avoiding some arithmetic and
; perhaps indirection or boxing in function 32-bit-integerp.

; Made trivial mod to books/Makefile-generic, thanks to Rockwell Collins, that
; could avoid problems when cert.acl2 ends with a line containing `;' and no
; newline.

; In a test of v3-2 vs. the development version (both GCL), with efficiency
; mods (those below through the add-include-book-dir mod), cut the time by 57%
; for this include-book (could be representative):
;  (time$ (include-book "rtl/rel7/support/support/top" :dir :system))
;  8.74 s vs. 3.73 s (3 run average, run-gbc + run time)

; Eliminated FAILED target from books/Makefile-generic, inlining its function
; instead.

; Added dependency to books/make-event/Makefile:
; defspec.cert: eval.cert

; Improved (not yet advertised) feature rewrite-equiv to avoid some loops.
; Thanks to Dave Greve for bringing this to our attention with a very helpful
; example, which has been incorporated (slightly modified) as a comment, with
; the fix, into rewrite-solidify-rec.

; Modified certify-book-fn to do a full GC (garbage collection) in GCL after
; world rollback, just before the include-book phase.  We have some hope that
; this could help reclaim the space taken by .o files from subsidiary books
; that are about to be re-included.

  :parents (release-notes)
  :short "ACL2 Version  3.2.1 (June, 2007) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>(OpenMCL and multi-threaded SBCL only) Fixed a soundness bug in the
 evaluation of @(tsee mbe) forms in the presence of Lisp feature
 @(':acl2-mv-as-values').  Thanks to Sol Swords for reporting this problem and
 sending a simple proof of @('nil') (which can be found in a comment in the
 ACL2 sources, in @('(deflabel note-3-2-1 ...)')).</p>

 <p>Added a new utility, @(tsee dmr) (Dynamically Monitor Rewrites), for
 watching the activity of the rewriter and some other proof processes.  See
 @(see dmr).  We thank Robert Krug for useful contributions.</p>

 <p>Fixed a bug in evaluation of calls of @(tsee with-prover-time-limit).</p>

 <p>Fixed the writing of executable scripts when building ACL2, so that the
 build-time value of environment variable @('ACL2_SYSTEM_BOOKS') is no longer
 written there.  Thanks to Dave Greve for discussing this change.</p>

 <p>Fixed bugs in @(':')@(tsee pl) (which are similarly present in the @(see
 proof-builder)'s @('sr') (@('show-rewrites')) command.  The first bug was
 evident from the following forms sent by Robert Krug, which caused an
 error.</p>

 @({
  (include-book \"arithmetic-3/floor-mod/floor-mod\" :dir :system)
  :pl (mod (+ 1 x) n)
 })

 <p>The second bug was due to a failure to take note of which rules are
 disabled, and could be seen by executing the following (very slow!).</p>

 @({
  (defstub modulus () t)
  (include-book \"arithmetic-3/floor-mod/floor-mod\" :dir :system)
  :pl (mod (+ x y) (modulus))
 })

 <p>Modified @(tsee certify-book) so that by default, all
 executable-counterpart functions (sometimes called ``*1* functions'') are
 compiled.  This is the behavior that was already supported with a
 @('compile-flg') argument of @(':all'); the change is that argument @('t') now
 has this behavior as well (and @(':all') is supported only for legacy
 purposes).  A new value for @('compile-flg'), @(':raw'), gives the behavior
 formerly produced by value @('t'), namely where executable-counterpart
 functions are not compiled.  The above changes are irrelevant if compilation
 is suppressed; see @(see compilation).  Finally, if environment variable
 @('ACL2_COMPILE_FLG') is set, then after converting to upper-case this
 environment variable's value of @('\"T\"'), @('\"NIL\"'), or @('\":RAW\"')
 will determine the value of the optional @('compile-flg') argument to be
 @('t'), @('nil'), or @(':raw'), respectively, when this argument is not
 explicitly supplied.</p>

 <p>Modified @(tsee include-book) so that @(':comp') argument now acts like
 @(':comp!'), i.e., compiling a file that includes the file together with all
 executable counterpart (so-called ``*1*'') functions.  A new argument,
 @(':comp-raw'), has the behavior that @(':comp') had formerly, i.e., compiling
 the actual book only.</p>

 <p>The function @(tsee nonnegative-integer-quotient) is now computed in raw
 Lisp by calling @(tsee floor) on its arguments.  This change was suggested by
 Peter Dillinger, in order to avoid stack overflows such as reported by Daron
 Vroon.  A new book, @('books/misc/misc2/misc.lisp'), contains a proof of
 equivalence of @(tsee nonnegative-integer-quotient) and @(tsee floor), and
 serves as a repository for other miscellaneous proofs, including those
 justifying ACL2 modifications such as this one.</p>

 <p>Enhanced @(tsee accumulated-persistence) to break down results by useful
 vs.  useless rule applications.  In particular, this provides information
 about which rules were ever applied successfully, as requested by Bill
 Young.</p>

 <p>Added coverage of @(':')@(tsee meta) rules to the @(tsee
 accumulated-persistence) statistics.</p>

 <p>Fixed a bug that was causing a @(':')@(tsee clause-processor) hint to fire
 on a subgoal of the goal to which it was attached, when the original
 application didn't change the clause.  Thanks to Dave Greve for pointing out
 this bug and providing a useful example.</p>

 <p>Fixed a bug in handling of computed @(see hints) related to the
 @('stable-under-simplificationp') parameter (see @(see computed-hints)).
 There were actually two bugs.  A minor but confusing bug was that the same
 goal was printed twice upon application of such a hint.  The major bug was
 that @(':use') @(see hints) (as well as other ``top'' hints: @(':by'),
 @(':cases'), and @(':clause-processor')) were not being applied properly.
 Thanks to Jared Davis for sending an example some time ago that showed the
 duplicate printing, and to Dave Greve for sending an example showing
 mis-application of @(':')@(tsee clause-processor) @(see hints).  Note that you
 may find that existing computed hints using the
 @('stable-under-simplificationp') parameter no longer have the same behavior;
 see a comment about computed hints in @('note-3-2-1'), ACL2 source file
 @('ld.lisp'), for an example of how you might want to fix such computed
 hints.</p>

 <p>David Russinoff has contributed an updated version of
 @('books/quadratic-reciprocity/') including minor modifications of the
 treatment of prime numbers and a proof that there exist infinitely many
 primes.  Thanks to David for contributing this work, and to Jose Luis
 Ruiz-Reina for posing the challenge.</p>

 <p>Reduced the sizes of some @(see certificate) (@('.cert')) files by relaxing
 the test that allows original @(tsee defpkg) @(see events) to be placed there,
 rather than evaluating the import list term into an explicit list of
 symbols.</p>

 <p>Improved execution efficiency slightly for function @('rcdp') in file
 @('books/misc/records.lisp'), by using @(tsee mbe) to introduce a
 tail-recursive body.</p>

 <p>The executable script generated by @(tsee save-exec) (and by the normal
 build process) now includes a time stamp as a comment.  Thanks to Jared Davis
 for suggesting this change in order to support his use of @('omake').  In the
 process, we also arranged that the startup banner for an executable created by
 @(tsee save-exec) shows all of the build (save) times, not just the one for
 the original image.</p>

 <p>Sped up most redundant @(tsee defpkg) @(see events) by avoiding evaluation
 and sorting of the imports list in the case of identical event forms.  And,
 for @(tsee defpkg) events that are not redundant, sped up their processing in
 Allegro CL (and perhaps other Lisps, but apparently not GCL) by using our own
 @('import') function.</p>

 <p>Modified @(tsee add-include-book-dir) so that it refuses to associate a
 keyword with a different directory string than one it is already bound to.
 See @(see delete-include-book-dir) for how to remove the existing binding
 first.  Thanks to Robert Krug for pointing out that without this change, one
 can find it difficult to debug a failure due to rebinding a keyword with
 @(tsee add-include-book-dir).</p>

 <p>Added a new value for the @(':do-not-induct') hint (see @(see hints)),
 @(':otf-flg-override'), which causes ACL2 to ignore the @(':')@(tsee otf-flg)
 when considering whether to abort the proof because of a @(':do-not-induct')
 hint.  Thanks to Daron Vroon for suggesting such an addition.</p>

 <p>Modified the printing of messages for entering and exiting raw mode (see
 @(see set-raw-mode)), so that in particular they are inhibited during @(tsee
 include-book) or whenever @('observation')s are inhibited (see @(see
 set-inhibit-output-lst)).  Thanks to Peter Dillinger for suggesting such a
 change.</p>

 <p>(For system hackers only.)  The handling of @(see events) of the form
 @('(progn! (state-global-let* ...))') had a bug that was causing bindings to
 be evaluated twice.  Moreover, the use of system function @(tsee
 state-global-let*) is suspect in raw Lisp.  We have eliminated special
 treatment of @('state-global-let*') by @('progn!') in favor of a new keyword
 argument, @('state-global-bindings'), that provides the intended
 functionality.  See @(see progn!).  Moreover, special handling that allowed
 @(tsee make-event) forms under @('state-global-let*') has been removed; the
 desired effect can be obtained using (progn! :state-global-bindings ...).
 Thanks to Peter Dillinger for pointing out the above bug and collaborating on
 these changes.</p>

 <p>Incorporated backward-compatible enhancements to
 @('books/misc/expander.lisp') from Daron Vroon (documented near the top of
 that file).</p>

 <p>The specification of @(':backchain-limit-lst') had required that only a
 single (@(':')@(tsee rewrite), @(':')@(tsee linear), or @(':')@(tsee meta))
 rule be generated.  We have weakened this restriction to allow more than one
 rule provided that each rule has the same list of hypotheses.  For example,
 the rule class @('(:rewrite :backchain-limit-lst 1)') is now legal for the
 corollary formula @('(implies (f x) (and (g x) (h x)))'), where this was not
 formerly the case.  Thanks to Dave Greve for bringing this issue to our
 attention.</p>")

(defxdoc |NOTE-3-2-1(R)|
  :parents (release-notes)
  :short "ACL2 Version  3.2.1(r) (June, 2007) Notes"
  :long "<p>Please also see @(see note-3-2-1) for changes to Version 3.2.1 of
  ACL2.</p>")

(defxdoc note-3-3

; Modified function error-trace-suggestion to suggest WET only for lisps that
; support it.

; Fixed emacs/log-emacs-code.el (not distributed) to try to be
; platform-independent.  Modified the following makefiles in support of that:
;   books/workshops/2003/hbl/support/Makefile
;   books/workshops/2004/sumners-ray/support/Makefile
;   books/workshops/2003/kaufmann/support/rtl/Makefile
;   books/workshops/1999/multiplier/Makefile
;   books/Makefile

; Book defpun-exec-domain-example.lisp was moved from misc to misc2, so that a
; form depending on make-event could be uncommented.

; Fixed spacing issue in defun messages: too many spaces before
; type-prescription message.

; Modified books/data-structures/structures.lisp to eliminate compiler warnings
; for ignored variables.

; Improved a heretofore misleading error message produced by guess-measure when
; no controller-alist is supplied with a :definition rule.  The message had
; made it appear (erroneously) that the function's original definition doesn't
; have a controller-alist.  Thanks to John Cowles for bringing this to our
; attention.

; Eliminated (defmacro checkpoints ...) and (defun print-checkpoints ...),
; which were defined merely to cause errors for those who used pstack features
; back in Version_2.7.

; Fixed a bug in parse-primes: eq was called for character comparison instead
; of eql, causing a violation during macroexpansion (because of safe-mode).

; Modified some command printing (see print-ldd-full-or-sketch) to recognize
; defund and defthmd.

; Fixed books/misc/bash.lisp so that state global 'guard-checking-on is bound
; to nil, as required by pc-prove (and now documented there).

; Modified message about abandoning induction when a "formula is subsumed by
; one of its parents", following a conversation initiated by Bill Legato.

; Changed name of function print-goal to print-pc-goal.

; Fixed dependencies in Makefiles under
; books/workshops/2003/kaufmann/support/, which were causing problems with
; "make -j 8".

; Fixed problem with error message in check-exact-free-vars.

; Changed calls of len to calls of length in newly-defined-top-level-fns.

; Modified and-list and or-list in books/clause-processors/equality.lisp in
; order to be a bit more efficient using guards.

; Added a type (essentially, fixnum) declaration for a return case in fmt0 (but
; it's not clear how much GCL boxing that will avoid), and added calls of
; the-fixnum in enabled-numep and enabled-arith-numep.

; Improved error message on encapsulate or include-book failure to give
; information when encountering a record-expansion form, to help in debugging
; problems related to user's make-event forms.

; Changed io? type in print-rule-storage-dependencies from 'prove to 'event.

; Error reporting has been improved slightly when mv is called with the wrong
; number of arguments in a function body.  Thanks to Warren Hunt for suggesting
; that the error message be improved.

; Changed names mod* and floor* to mod-induct-fn and floor-induct-fn,
; respectively, in books/arithmetic-3/floor-mod/floor-mod.lisp.  This change
; probably won't affect anyone, except to make arithmetic-3 more compatible
; with the rtl libraries (which define mod*), since these functions are only
; used to set up inductions.

; Eliminated an error when using state-global-let* with an empty binding list,
; e.g., (progn! :state-global-bindings nil).

; Fixed warning:
; ignoring old commands for target `clean-more'
; with 'make clean' in books/nonstd/workshops/1999/calculus/.

; Here are examples that illustrate bugs (1) through (3) mentioned in the
; paragraph on "Fixed the following issues with packages and book
; certificates".  Try these in Version_3.2.1 and you will see the bugs; but,
; these work fine in Version_3.3.  In the following, foo.lisp has just the
; forms (in-package "ACL2") and (defun foo (x) x).
;
; (1) After doing the following, foo.cert has needless defpkg forms among the
; portcullis commands in Version_3.2.1 but not in Version_3.3.
;
; (include-book "arithmetic/top" :dir :system)
; (certify-book "foo" 1)
;
; (2) Version_3.2.1 causes errors when following the directions below, but
; Version_3.3 does not.  Here, foo.lisp is as above and bar.lisp has only the
; forms (in-package "ACL2") and (defun bar (x) x).
;
; (defpkg "FOO" nil)
; (defconst *a* 'foo::a)
; (certify-book "foo" 2)
;
; [Restart ACL2]
; (encapsulate () (local (include-book "foo")) (defun h (x) x))
; (certify-book "bar" 1)
;
; (3) Watch (include-book "bar") fail at the end of the following instructions
; in Version_3.2.1, but not in Version_3.3.
;
; (set-ignore-ok :warn)
; (defpkg "FOO" (let ((x 3)) '(a b)))
; (certify-book "foo" 2)
;
; [Restart ACL2]
; (encapsulate () (local (include-book "foo")) (defun h (x) x))
; (certify-book "bar" 1)
;
; [Restart ACL2]
; (include-book "bar")

; Fixed books/clause-processors/Makefile to work on Sun/Solaris.

  :parents (release-notes)
  :short "ACL2 Version  3.3 (November, 2007) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 3.2.1 into new
 features, bug fixes, prover algorithm enhancements, and miscellaneous.  Also
 see @(see note-3-2-1) for other changes since Version 3.2.</p>

 <p><b>NEW FEATURES</b></p>

 <p>A new ``gag-mode'' provides less verbose, more helpful feedback from the
 theorem prover, in support of The Method (see @(see the-method)).  See @(see
 set-gag-mode).  We recommend the use of gag-mode, which may become the default
 in future ACL2 releases, and we welcome suggestions for improvement.  We thank
 Robert Krug and Sandip Ray for helpful feedback in the design of @(see
 gag-mode).  Note that when proofs fail, then even without gag-mode and even if
 proof output is inhibited, the summary will contain a useful listing of
 so-called ``key checkpoints'' (see @(see set-gag-mode)).</p>

 <p>Added support for a leading `@('~')' in filenames.  Thanks to Bob Boyer for
 suggesting this enhancement.  Note that since `@('~/')' depends on the user,
 it is disallowed in @(see books) to be certified (see @(see certify-book)),
 since otherwise an @(tsee include-book) form in a book, @('b'), could have a
 different meaning at certification time than at the time @(tsee include-book)
 is later executed on book @('b').</p>

 <p>Made a change to allow @('(time$ FORM)') and @('(with-prover-time-limit
 TIME FORM)') when @('FORM') includes @(tsee make-event) calls that change the
 ACL2 @(see world).  Thanks to Jared Davis for requesting such support for
 @(tsee time$).</p>

 <p>Computed @(see hints) (see @(see computed-hints)) may now produce a
 so-called ``error triple'', i.e., a result of the form @('(mv erp val
 state)'), where a non-@('nil') @('erp') causes an error, and otherwise
 @('val') is the value of the hint.  It remains legal for a computed hint to
 return a single ordinary value; indeed, the symbol form of a computed hint
 must still be a function that returns an ordinary single value.</p>

 <p>New hints provide additional control of the theorem prover, as follows.
 See @(see hints) for more details, and see new distributed book directory
 @('books/hints/') for examples, in particular file @('basic-tests.lisp') in
 that directory for simple examples.</p>

 <blockquote>

 <p>o The hint @(':OR (hints-1 ... hints-k)') causes an attempt to prove the
 specified goal using each @('hints-i') in turn, until the first of these
 succeeds.  If none succeeds, then the prover proceeds after heuristically
 choosing the ``best'' result, taking into account the goals pushed in each
 case for proof by induction.</p>

 <p>o A custom hint is a keyword that the user associates with a corresponding
 hint-generating function by invoking @(tsee add-custom-keyword-hint).  Thus, a
 custom hint may be viewed as a convenient sort of computed hint.</p>

 <p>o A custom hint, @(':MERGE'), is implemented in distributed book
 @('books/hints/merge.lisp').  It is useful for combining hints.</p>

 <p>o A sophisticated yet useful custom hint is the @(':CONSIDER') hint
 implemented in distributed book @('books/hints/consider-hint.lisp').  With
 this hint, you can for example give the equivalent of a @(':USE') hint without
 the need to supply an instantiation.  Include that book in order to see
 documentation online with @(':doc consideration'), and see the book
 @('books/hints/consider-hint-tests.lisp') for examples.</p></blockquote>

 <p>A new hint, @(':')@(tsee reorder), allows the specification of which
 subgoals are to be considered first.  Thanks to Sandip Ray for putting forward
 this idea.</p>

 <p>Enhanced @(tsee set-saved-output) by supporting a second argument of
 @(':same'), which avoids changing which output is inhibited.</p>

 <p>Added macros @('thm?') and @('not-thm?') to distributed book
 @('books/make-event/eval.lisp'), so that it's easy to test within a certified
 book that a proof attempt succeeds or that it fails.</p>

 <p>Added printing function @(tsee cw!), which is analogous to @(tsee cw) just
 as @(tsee fmt!) is to @(tsee fmt), i.e., printing so that the result can be
 read back in.  Thanks to Jared Davis for suggesting this enhancement (after
 doing his own implementation).</p>

 <p>The ACL2 customization file can now be specified using environment variable
 @('ACL2-CUSTOMIZATION') [note: starting with Version_4.0,
 @('ACL2_CUSTOMIZATION')].  See @(see acl2-customization).  Thanks to Peter
 Dillinger for requesting this feature.</p>

 <p>Added new emacs capabilities for proof trees (all documented in emacs):</p>

 <blockquote>

 <p>o New function start-proof-tree-noninteractive, for example<br></br>

   (start-proof-tree-noninteractive \"*shell*\")</p>

 <p>o C-z o Switch to another frame</p>

 <p>o C-z b Switch to prooftree buffer</p>

 <p>o C-z B Switch to prooftree buffer in \"prooftree-frame\"
 frame</p></blockquote>

 <p>Added Common Lisp function, @('search'), as a macro in @(tsee logic) mode,
 with limited support for keyword arguments.  Thanks to Warren Hunt for
 requesting this addition.</p>

 <p>Sandip Ray has contributed a book, @('books/make-event/defrefine.lisp'),
 that provides a collection of macros to aid in reasoning about ACL2 functions
 via refinement.</p>

 <p>Wrote and incorporated new utility for listing all the theorems in an
 included book.  See @('books/misc/book-thms.lisp').  Thanks to Jared Davis for
 requesting this functionality.</p>

 <p>The new distributed book @('misc/defp.lisp') generalizes the @(tsee defpun)
 macro to allow more general forms of tail recursion.</p>

 <p>(Low-level printing improvement) A new function,
 @('set-ppr-flat-right-margin'), allows the right margin for certain kinds of
 ``flat'' printing to exceed column 40.  Thanks to Jared Davis for pointing out
 that state global variables @(''fmt-hard-right-margin') and
 @(''fmt-soft-right-margin') are not alone sufficient to extend the right
 margin in all cases.</p>

 <p>The event @(tsee add-include-book-dir) can now take a relative pathname as
 an argument.  Formerly, it required an absolute pathname.</p>

 <p>A new book, @('books/misc/defopener.lisp'), provides a utility creating a
 theorem that equates a term with its simplification.</p>

 <p>ACL2 now provides limited support for the Common Lisp primitive @('FLET'),
 which supports local function bindings.  See @(see flet).  Thanks to Warren
 Hunt for requesting this feature.</p>

 <p>Added a definition of @(tsee boole$), a close analogue of Common Lisp
 function @('boole').  Thanks to Bob Boyer for providing an initial
 implementation.</p>

 <p><b>BUG FIXES</b></p>

 <p>Fixed @(tsee defstobj) to inhibit a potentially useless theory warning.</p>

 <p>Fixed a bug in the application of @(tsee certify-book) to relative
 pathnames for files in other than the current directory.  Thanks to Amr Helmy
 for bringing this bug to our attention.</p>

 <p>Fixed a bug in @(':')@(tsee pl) and @(':')@(tsee pr) for displaying rules
 of class @(':')@(tsee meta).  Thanks to Jared Davis for finding this bug and
 providing a fix.</p>

 <p>Formerly, @(tsee set-default-backchain-limit) was not a legal event form
 for @(tsee encapsulate) forms and @(see books).  This has been fixed.  Thanks
 to Robert Krug and Sandip Ray for bringing this bug to our attention.</p>

 <p>Fixed the handling of @(see hints) in @(see proof-builder) commands for the
 prover, such as @('bash') &mdash; see @(see proof-builder-commands) &mdash; so
 that the user can override the default settings of hints, in particular of
 @(':do-not') and @(':do-not-induct') hints attached to @('\"Goal\"').  This
 fix also applies to the distributed book @('misc/bash.lisp'), where Robert
 Krug noticed that he got an error with @(':hints ((\"Goal\" :do-not
 '(preprocess)))'); we thank Robert for pointing out this problem.</p>

 <p>Fixed a bug in handling of @(see stobj)s occurring in guards of functions
 whose @(see guard)s have been verified.  In such cases, a raw Lisp error was
 possible when proving theorems about non-''live'' @(see stobj)s.  We thank
 Daron Vroon for sending us an example that highlighted this bug.  The
 following (simpler) example causes such an error in previous versions of
 ACL2.</p>

 @({
  (defstobj st fld)
  (defun foo (st)
    (declare (xargs :stobjs st :guard (fld st)))
    st)
  (thm (equal (foo '(3))
              '(3)))
 })

 <p>The @(see dmr) feature for dynamic monitoring of rewrites had a bug, where
 the file used for communicating with emacs was the same for all users, based
 on who built the ACL2 executable image.  This has been fixed.  Thanks to
 Robert Krug for bringing this bug to our attention.</p>

 <p>Fixed a bug in some warnings, in particular the warning for including an
 uncertified book, that was giving an incorrect warning summary string.</p>

 <p>Inclusion of uncertified books erroneously re-used @(tsee make-event)
 expansions that were stored in stale @(see certificate)s.  This is no longer
 the case.  Thanks to Jared Davis for bringing this bug to our attention.</p>

 <p>Fixed a bug that was disallowing calls of @(tsee with-output) in @(see
 events) that were executing before calling @(tsee certify-book).</p>

 <p>Modified the functionality of @('binop-table') so other than binary
 function symbols are properly supported (hence with no action based on
 right-associated arguments).  See @(see add-binop).</p>

 <p>Fixed small @(see proof-builder) issues related to packages.  Emacs
 commands @('ctrl-t d') and @('ctrl-t ctrl-d') now work properly with colon
 (`@(':')') and certain other punctuation characters.  The @('p-top') command
 now prints ``@('***')'' regardless of the current package.</p>

 <p>Fixed a bug that allowed @(tsee certify-book) to succeed without specifying
 value @('t') for keyword argument @(':skip-proofs-okp'), even with @(tsee
 include-book) @(see events) in the certification @(see world) depending on
 events executed under @(tsee skip-proofs).</p>

 <p>Improved @(tsee show-accumulated-persistence) in the following two ways.
 Thanks to Robert Krug and Bill Young for requesting these improvements and for
 providing useful feedback.</p>

 <blockquote>

 <p>o It can provide more complete information when aborting a proof.</p>

 <p>o The @(':frames') reported for a rule are categorized as ``useful'' and
 ``useless'' according to whether they support ``useful'' or ``useless''
 @(':tries') of that rule, respectively.  See @(see accumulated-persistence)
 for further explanation.</p></blockquote>

 <p>Modified @(tsee make-event) so that the reported time and warnings include
 those from the expansion phase.  In analogy with @(tsee encapsulate) and
 @(tsee progn), the rules reported still do not include those from subsidiary
 events (including the expansion phase).  A related change to @(tsee ld) avoids
 resetting summary information (time, warnings) with each top-level form
 evaluation; @(see events) already handle this information themselves.</p>

 <p>Fixed @(tsee set-inhibit-output-lst) so that all warnings are inhibited
 when @('warning!') but not @('warning') is included in the list.  Formerly,
 only soundness-related warnings were inhibited in this case.  Thanks to Eric
 Smith for bringing this bug to our attention.</p>

 <p>Distributed directory @('doc/HTML/') now again includes installation
 instructions (which was missing in Version_3.2.1), in
 @('doc/HTML/installation/installation.html').</p>

 <p>Some fixes have been made for @(see proof-tree) support.</p>

 <blockquote>

 <p>o @(see Proof-tree) output is no longer inhibited automatically during
 @(tsee certify-book), though it continues to be inhibited by default (i.e.,
 ACL2 continues to start up as though @(tsee set-inhibit-output-lst) has been
 called with argument @(''(proof-tree)')).</p>

 <p>o Fixed a bug in Xemacs support for @(see proof-tree) help keys @('C-z h')
 and @('C-z ?').</p>

 <p>o Fixed a bug in @(see proof-tree)s that was failing to deal with the case
 that a goal pushed for proof by induction is subsumed by such a goal to be
 proved later.  Now, the proof-tree display regards such subsumed goals as
 proved, as is reported in the theorem prover's output.</p></blockquote>

 <p>Fixed a bug that was disallowing @(tsee value-triple) forms inside @(tsee
 encapsulate) forms in a certification @(see world) (see @(see
 portcullis)).</p>

 <p>If the @(':load-compiled-file') argument of a call of @(tsee include-book)
 is @(':comp'), then an existing compiled file will be loaded, provided it is
 more recent than the corresponding book (i.e., @('.lisp') file).  A bug was
 causing the compiled file to be deleted and then reconstructed in the case of
 @(':comp'), where this behavior was intended only for @(':comp!').</p>

 <p>Fixed a bug that was avoiding compilation of some executable counterparts
 (sometimes called ``*1* functions'') during @(tsee certify-book), and also
 during @(tsee include-book) with @(':load-compiled-file') value of @(':comp')
 or @(':comp!')).  Thanks to Eric Smith for sending a small example to bring
 this bug to our attention.</p>

 <p>Incorporated a fix from Eric Smith for a typo (source function
 @('ancestors-check1')) that could cause hard Lisp errors.  Thanks, Eric!</p>

 <p>Fixed the following issues with packages and book @(see certificate)s.  See
 @(see hidden-death-package) if you are generally interested in such issues,
 and for associated examples, see comments on ``Fixed the following issues with
 packages'' in @('note-3-3') in the ACL2 source code.</p>

 <blockquote>

 <p>o Reduced the size of @('.cert') files by eliminating some unnecessary
 @(tsee defpkg) events generated for the @(see portcullis).</p>

 <p>o Fixed a bug that has caused errors when reading symbols from a @(see
 portcullis) that are in undefined packages defined in locally included
 books.</p>

 <p>o Fixed a bug that could lead to failure of @(tsee include-book) caused by
 a subtle interaction between @(tsee set-ignore-ok) and @(tsee defpkg) events
 generated for the @(see portcullis) of a @(see certificate).</p></blockquote>

 <p><b>PROVER ALGORITHM ENHANCEMENTS</b></p>

 <p>Non-linear arithmetic (see @(see non-linear-arithmetic)) has been improved
 to be more efficient or more powerful in some cases.  Thanks to Robert Krug
 for contributing these improvements.</p>

 <p>Improved certain (so-called ``@(tsee type-set)'') reasoning about whether
 or not expressions denote integers.  Thanks to Robert Krug for contributing
 code to implement this change, along with examples illustrating its power that
 are now distributed in the book
 @('books/misc/integer-type-set-test.lisp').</p>

 <p>Improved ACL2's heuristics for relieving hypotheses, primarily to use
 linear reasoning on conjuncts and disjuncts of the test of an @(tsee if)
 expression.  For example, given a hypothesis of the form @('(if (or term1
 term2) ...)'), ACL2 will now use linear reasoning to attempt to prove both
 @('term1') and @('term2'), not merely for @('term2').  Thanks to Robert Krug
 for supplying examples illustrating the desirability of such an improvement
 and for useful discussions about the fix.</p>

 <p>Made a slight heuristic change, so that when a hypothesis with @(tsee let)
 or @(tsee mv-let) subterms (i.e. @(tsee lambda) subterms) rewrites to @('t'),
 then that hypothesis is necessarily eliminated.  Thanks to Jared Davis for
 sending an example that led us to develop this change, and thanks to Robert
 Krug for a helpful discussion.</p>

 <p><b>MISCELLANEOUS</b></p>

 <p>Added documentation on how to use @(tsee make-event) to avoid duplicating
 expensive computations, thanks to Jared Davis.  See @(see
 using-tables-efficiently).</p>

 <p>Modified the error message for calls of undefined functions to show the
 arguments.  Thanks to Bob Boyer for requesting this enhancement.</p>

 <p>Modified utilities @(':')@(tsee pr), @(':')@(tsee pr!), @(':')@(tsee pl), and
 @(':')@(tsee show-bodies) to incorporate code contributed by Jared Davis.
 That code defines low-level source functions @('info-for-xxx') that collect
 information about rules, which is thus available to advanced users.</p>

 <p>Dynamic monitoring of rewrites (see @(see dmr)) has been improved in the
 following ways, as suggested by Robert Krug.</p>

 <blockquote>

 <p>o Some stale entries from the rewrite stack are no longer printed, in
 particular above @('ADD-POLYNOMIAL-INEQUALITIES').</p>

 <p>o An additional rewrite stack entry is made when entering non-linear
 arithmetic (see @(see non-linear-arithmetic)).</p>

 <p>o An @('ADD-POLYNOMIAL-INEQUALITIES') entry is printed with a counter, to
 show how often this process is called.</p></blockquote>

 <p>Modified @(tsee save-exec) so that the newly-saved image will have the same
 raw Lisp package as the existing saved image.  This is a very technical change
 that will likely not impact most users; for example, the package in the ACL2
 read-eval-print loop (see @(see lp)) had already persisted from the original
 to newly-saved image.  Thanks to Jared Davis for suggesting this change.</p>

 <p>Changed @(tsee make-event) expansion so that changes to @(tsee
 set-saved-output), @(tsee set-print-clause-ids),
 @('set-fmt-soft-right-margin'), and @('set-fmt-hard-right-margin') will
 persist after being evaluated during @('make-event') expansion.
 (Specifically, @('*protected-system-state-globals*') has been modified; see
 @(see make-event-details).)  Thanks to Jared Davis for bringing this issue to
 our attention.</p>

 <p>Output from the @(see proof-builder) is now always enabled when invoking
 @(tsee verify), even if it is globally inhibited (see @(see
 set-inhibit-output-lst)).</p>

 <p>Improved the message printed when an @(':induct') hint fails, to give more
 information in some cases.  Thanks to Rex Page for suggesting where an
 improvement could be made and providing useful feedback on an initial
 improvement.</p>

 <p>Added a warning for @(see congruence) rules (see @(see defcong)) that
 specify @(tsee iff) as the second equivalence relation when @(tsee equal) can
 be used instead.  Those who heed these warnings can eliminate certain
 subsequent @(tsee double-rewrite) warnings for @(see rewrite) rules with
 conclusions of the form @('(iff term1 term2)'), and hence implicitly for
 Boolean conclusions @('term1') that are interpreted as @('(iff term1 t)').
 Thanks to Sarah Weissman for sending us an example that highlighted the need
 for such a warning.</p>

 <p>Modified macro @(':')@(tsee redef!) (which is for system implementors) so
 that it eliminates untouchables.</p>

 <p>Several improvements have been made to the experimental hons/memoization
 version of ACL2.  See @(see hons-and-memoization).</p>

 <p>The distributed books directory, @('(@ distributed-books-dir)'), is now
 printed in the start-up message.</p>")

(defxdoc |NOTE-3-3(R)|
  :parents (release-notes)
  :short "ACL2 Version  3.3(r) (November, 2007) Notes"
  :long "<p>Please also see @(see note-3-3) for changes to Version 3.3 of
  ACL2.</p>")

(defxdoc note-3-4

; Here is the example promised in :doc note-3-4 for a soundness bug, namely a
; proof of nil based on the use of mbe inside an encapsulate event.  The proof
; goes through for this example in Version_3.3 but not in Version_3.4.

;  (encapsulate
;   ((f (x) t))
;
;   (local (defun f (x)
;            (declare (xargs :guard t))
;            x))
;
;   (defun g (x)
;     (declare (xargs :guard t))
;     (mbe :logic (f x)
;          :exec  x)))
;
;  (defthm g-3-is-3
;    (equal (g 3) 3)
;    :rule-classes nil)
;
;  (defthm f-3-is-3
;    (equal (f 3) 3)
;    :hints (("Goal"
;             :in-theory (disable (g))
;             :use g-3-is-3)))
;
;  (defun foo (x)
;    (declare (ignore x))
;    4)
;
;  (defthm contradiction
;    nil
;    :hints (("Goal" :use ((:functional-instance f-3-is-3
;                                                (f foo)))))
;    :rule-classes nil)

; Fixed a hard error during an error message caused by the use of the wrong ~@
; argument in unknown-binding-msg.  Thanks to Eric Smith for pointing this out.

; The source function for "Fixed bugs in" proof-builder code was
; pc-relieve-hyp.

; The following events prove in GCL and Allegro builds of ACL2  3.3.  Both the
; new trace and fixes to the existing replacements for trace (i.e., now using
; :native t) will fix this.
;
;     (defun f (x y)
;       (mv x y))
;
;     (defthm fact-about-f
;       (equal (f 3 4)
;              (mv 3 4))
;       :rule-classes nil)
;
;     (defttag :trace)
;
;     (trace$ (f :exit
;                (mv-let (u v)
;                        (mv 7 8)
;                        (equal u v))))
;
;     ; But the call of mv in the :exit condition messes up multiple-value
;     ; handling by ACL2, and now (f 3 4) is (mv 3 8).
;
;     (defthm contradiction
;       nil
;       :hints (("Goal" :use fact-about-f))
;       :rule-classes nil)

; Fixed error message at the end of translate-hint-expression (thanks to Robert
; Krug for the fix) to acknowledge that STATE can be used.

; Here is the example Peter Dillinger sent for the bug in the interaction of
; proof-trees with :induct hint value :otf-flg-override.  The fix was to
; consider do-not-induct-otf-flg-override in the definition of aborting-p in
; the definition of increment-proof-tree.

;  (start-proof-tree)
;
;  (defun limit-induction-hint-fn (i)
;    `(or (and (length-exceedsp (car id) ,i)
;              (endp (cdadr id))
;              (eq (cddr id) 0)
;              '(:computed-hint-replacement
;                t
;                :do-not-induct :otf-flg-override))
;         (and (> (cddr id) 20)
;              '(:computed-hint-replacement
;                t
;                :do-not (eliminate-destructors eliminate-irrelevance
;                                               generalize fertilize)
;                :in-theory nil))))
;
;  (add-default-hints
;   `(,(limit-induction-hint-fn 1)))
;
;  (defun sum-from (i lst)
;    (if (and (natp i)
;             (< i (len lst)))
;      (+ (nth i lst) (sum-from (1+ i) lst))
;      0))

; Fixed warning messages (error messages too actually) for computed hints, so
; that mere warnings don't say that a value is illegal.  Thanks to Robert Krug
; for pointing out this problem and sending the following example:

;  (in-theory (disable mv-nth eq))
;
;  (thm
;   (equal (* x y) (+ x y))
;   :hints ((if stable-under-simplificationp
;               '(:in-theory (enable eq))
;             nil)))

; Changed constant *primitive-event-macros* into zero-ary function
; primitive-event-macros, in support of Peter Dillinger's desire to be able to
; change this function with ttags.

; Modified GNUmakefile to use ACL2_SUFFIX for saved_acl2 suffix.

; ACL2 source macro defrec can now be used in :logic mode even when the cheap
; flag is nil.  Formerly, the presence of record-error made that impossible,
; but now record-error is in :logic mode, and with guards verified by using (er
; hard? ...) instead of (er hard ...).

; Strengthened the guard for er-let*.

; Fixed walking and flying tour pages to put the gif linking to the next page
; at the top too, not just the bottom of the page.

; Sped up macroexpansion of with-output forms by changing how OR is called in
; with-output in the loop.

; Fixed a bug in :pso, specifically in its "So we now return to" messages,
; which were printing a goal that had just been proved for induction.  The fix
; involved handling of of jppl-flg values in functions pop-clause-msg1 and
; pop-clause-msg.

; The bug that could cause certify-book to fail with local make-event forms was
; fixed by changing eval-event-lst so that it always concludes by setting
; state-global 'last-make-event-expansion to nil.  Before that, certification
; failed for a book whose only form (other than the leading in-package) is
; (local (make-event '(defun foo (x) x))).

; Modified expansion-alist-pkg-names slightly; memory escapes just why, but
; notes suggest that it was to fix a bug reported by Eric Smith.

; Fixed a bug in the guard for find-clauses1.

; Modified acl2-traced-fns to work in versions of CCL after June 2008.

; Following Bob Boyer, added (debug 0) to the optimize form for CCL (OpenMCL)
; in acl2.lisp.

; The soundness bug in value-triple-fn could be exploited not only to prove nil
; but also to get a raw Lisp error, by way of these events at the top level or
; in a book:
;
; (defun foo (x)
;   (declare (xargs :mode :program :guard t))
;   (car x))
; (value-triple (foo 3))

; Moved #-acl2-loop-only code in getprop-default into the logic.

; Stopped creating io-record forms whose :io-marker is other than ctx or nil;
; see comment in io-record.

; Fixed get-hints1, get-guard-hints1, and get-std-hints1 to avoid raw Lisp
; errors for :hints values not satisfying true-listp.  So now we get a cleaner
; error, for example, on the following:
; (defun foo (x) (declare (xargs :hints 3)) x)

; For developers, "make" variable ACL2_SAFETY can be set in order to change the
; optimization safety setting from its default of 0; see GNUmakefile.  The
; OPTIMIZE form has been changed from a DECLAIM to a PROCLAIM to support this
; change.

; Edited :doc |Other Requirements| to remove MCL from the list of supported
; Lisps.  It was already the case that MCL was not included in
; installation/requirements.html.  If ACL2 works in MCL, it's just luck at this
; point.

; Fixed warning "Unable to determine USER environment variable for
; dmr-file-name", which has been seen on Windows, so that it only occurs at the
; first time in a session that dmr-start is run.  Also printed what to do in
; Emacs when that happens.

; Following an observation of Robert Krug, now a message "*** Note: No
; checkpoints to print. ***" is printed when a proof fails but no checkpoints
; have been generated.

; ACL2 source function trace-multiplicity now returns nil instead of 1 for
; functions not known to the ACL2 loop.

; In gag-mode, when a proof fails to produce checkpoints, we now see "*** Note:
; No checkpoints to print. ***".  Thanks to Robert Krug for requesting this
; additional output.  To get an infinite loop without checkpoints, to check
; this fix:
;
; (defstub foo (x) t)
; (defaxiom ax1
;   (implies (syntaxp (variablep x))
;            (equal (foo x) (foo (cons 3 x)))))
; (defaxiom ax2 (equal (foo (cons x y)) (foo y)))
; (thm (foo a)
;      :hints ((and stable-under-simplificationp
;                   '(:computed-hint-replacement t :in-theory (enable ax2)))
;              (and (not stable-under-simplificationp)
;                   '(:computed-hint-replacement t :in-theory (disable ax2)))))

; Jared's email leading to the expansion of *acl2-exports*, as noted below also
; led to fixing of our-abort to print in the ACL2 current-package.

  :parents (release-notes)
  :short "ACL2 Version  3.4 (August, 2008) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 3.3 into changes to
 existing features, new features, bug fixes, new and updated books, and Emacs
 support.  Each change is described just once, though of course many changes
 could be placed in more than one category.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>Fixed a long-standing potential infinite loop in the rewriter.  Thanks to
 Sol Swords for sending a concise example illustrating the looping behavior.
 (Those interested in details are welcome to look at the comment about loop
 behavior in source function @('rewrite-equal').)</p>

 <p>Incorporated a slight strengthening of non-linear arithmetic contributed by
 Robert Krug (thanks, Robert).  With non-linear arithmetic enabled, the problem
 was essentially that ACL2 made the following ``optimization'': given
 inequalities @('(< a u)') and @('(< b v)'), for positive rational constants
 @('a') and @('b') terms @('u') and @('v') of which at least one is known to be
 rational, infer @('(< (* a b) (* u v))').  Without this optimization, however,
 ACL2 now infers the stronger inequality obtained by direct multiplication of
 the two given inequalities.  To see the effect of this change, submit the
 event @('(set-non-linearp t)') followed by:</p>

 @({
  (thm (implies (and (rationalp x) (< 3 x)
                     (rationalp y) (< 4 y))
                (< 0 (+ 12 (* -4 x) (* -3 y) (* x y)))))
 })

 <p>The utility @(tsee set-checkpoint-summary-limit) has been modified in
 several ways: it now takes a single argument (no longer takes @(tsee state) as
 an argument); a natural number @('n') abbreviates the pair @('(n . n)'); the
 argument is no longer evaluated, but it still optionally may be quoted; and a
 new value, @('t'), suppresses all printing of the checkpoint summary.  Thanks
 to Jared Davis for suggesting most of these improvements.</p>

 <p>There was formerly a restriction on @(tsee mbe) that the @(':exec')
 argument may not contain a call of @(tsee mbe).  This restriction has been
 removed, thanks to a request from Jared Davis and Sol Swords.  Thanks also to
 Sandip Ray, who pointed out that this restriction may have been in place in
 order that @(tsee defexec) can guarantee termination using the @(':exec')
 code; its @(see documentation) has therefore been updated to clarify this
 situation.</p>

 <p>Rules of class @(':')@(tsee rewrite) are now stored by performing certain
 logical simplifications on the left side of the conclusion: @('(prog2$ X Y)')
 is replaced by @('Y'), @('(mbe :logic X :exec Y)') is replaced by @('X') (more
 precisely, the analogous change is made to the generated call of @(tsee
 must-be-equal)); and @('(the TYPE X)') is replaced by @('X') (again, the
 change is actually made on the macroexpanded form).  Thanks to Jared Davis and
 Sol Swords for requesting this change.  An analogous change has also been made
 for rules of class @(':')@(tsee forward-chaining).</p>

 <p>The @(tsee trace$) utility has been reimplemented to work independently of
 the underlying Lisp trace.  It thus works the same for every host Lisp, except
 as provided by an interface to the underlying host Lisp trace (the
 @(':native') option).  Note that the host Lisp trace continues to be modified
 for GCL, Allegro CL, and CCL (OpenMCL); see @(see trace).  See @(see trace$)
 for updated detailed documentation on tracing options, many of which are new,
 for example an @(':evisc-tuple') option that can be set to @(':no-print') if
 you want the function traced without the usual entry and exit printing.  The
 previous @(tsee trace$) had some issues, including the following, which have
 all been fixed.  Thanks to Peter Dillinger for assistance in determining
 desired functionality of the new @(tsee trace$) and for helping to test
 it.</p>

 <blockquote>

 <p>Recursive calls were not always shown in the trace for two reasons.  (1)
 Compiler inlining could prevent recursive calls from being shown in the trace,
 in particular in CCL (OpenMCL).  Thanks to Jared Davis and Warren Hunt for
 pointing out this issue and requesting a fix, and to Bob Boyer and Gary Byers
 for relevant helpful discussions.  (2) ACL2's algorithm for producing
 executable counterparts prevented tracing of recursive calls even after
 @('(set-guard-checking :none)').  Thanks to Peter Dillinger for requesting a
 fix.</p>

 <p>It was possible to exploit a bug in the interaction of multiple values and
 trace to prove a contradiction.  An example is in a comment in @('(deflabel
 note-3-4 ...)') in the ACL2 source code.</p>

 <p>Certain large structures could cause expensive computations for printing
 even when a @(':cond') condition was specified and evaluated to @('nil').</p>

 <p>@(tsee Trace!) now suppresses printing of the event summary, and returns
 the value that would be returned (if there is an active trust tag) by the
 corresponding call of @(tsee trace$).</p>

 <p>Some bugs have been fixed in the underlying native trace installed by ACL2
 for GCL, Allegro CL, and CCL (OpenMCL), including the following.  In GCL it
 had been impossible to use the variable @('ARGLIST') in a @(':cond')
 expression.  In Allegro CL and CCL, a @(tsee trace$) bug mishandled tracing
 non-ACL2 functions when directives such as @(':entry') and @(':exit') were
 supplied.  GCL trace now hides the world even when tracing non-ACL2 functions.
 Tracing in CCL no longer causes a Lisp error when untracing a traced function
 defined outside the ACL2 loop; for example @('(trace$ len1)') followed by
 @('(untrace$ len1)') no longer causes an error.</p></blockquote>

 <p>The macro @('wet') has been changed, for the better we think.  see @(see
 wet).</p>

 <p>The generation of goals for @(see forcing-round)s has been changed to avoid
 dropping assumptions formerly deemed ``irrelevant''.  (A simple example may be
 found in a comment in source function @('unencumber-assumption'), source file
 @('prove.lisp').)  Thanks to Jared Davis for sending us an example that led us
 to make this change.</p>

 <p>Modified the implementation of @(tsee make-event) so that in the @(see
 certificate) of a book, @(tsee local) events arising from @(tsee make-event)
 forms are elided.  For example, if @('(make-event <form>)') expands to
 @('(local <expanded-form>)'), then where the latter had been stored in the
 certificate, now instead @('(local (value-triple :ELIDED))') will be stored.
 Thanks to Eric Smith for requesting this improvement.  He has reported that a
 preliminary version of this improvement shrunk a couple of his @('.cert')
 files from perhaps 40MB each to about 140K each.</p>

 <p>Now, a @(tsee table) event that sets the entire table, @('(table tbl nil
 alist :clear)'), is redundant (see @(see redundant-events)) when the supplied
 @('alist') is equal to the current value of the table.  Thanks to Peter
 Dillinger for requesting this change.</p>

 <p>The event constructor @(tsee progn!) now returns the value that is returned
 by evaluation of its final form if no error occurs, except that it still
 returns @('nil') if the that final evaluation leaves ACL2 in raw-mode.</p>

 <p>@(':')@(tsee Pso) and @(':')@(tsee psog) have been improved so that they
 show the key checkpoint summary at the end of a failed proof.  (For a
 discussion of key checkpoints, see @(see set-gag-mode).)  As a result, a call
 of @(tsee set-checkpoint-summary-limit) now affects subsequent evaluation of
 @(':')@(tsee pso) and @(':')@(tsee psog).  In particular, you no longer need
 to reconstruct a proof (by calling @(tsee thm) or @(tsee defthm)) in order to
 see key checkpoints that were omitted due to the limit; just call @(tsee
 set-checkpoint-summary-limit) and then run @(':pso') or @(':psog').</p>

 <p>The @(see proof-builder) behaves a little differently under @(see
 gag-mode).  Now, proof-builder commands that call the theorem prover to create
 new proof-builder goals, such as @('bash') and @('induct') (see @(see
 proof-builder-commands)), will show key checkpoints when in @(see gag-mode).
 As before, proof-builder commands @('pso') and @('pso!') (and now, also
 @('psog')) &mdash; see @(see pso), see @(see psog), and see @(see pso!)
 &mdash; can then show the unedited proof log.  However, unlike proof attempts
 done in the ACL2 loop, such proof attempts will not show a summary of key
 checkpoints at the end, because from a prover perspective, all such goals were
 considered to be temporarily ``proved'' by giving them ``byes'', to be
 dispatched by later proof-builder commands.</p>

 <p>A little-known feature had been that a @(see measure) of @('0') was treated
 as though no measure was given.  This has been changed so that now, a @(see
 measure) of @('nil') is treated as though no measure was given.</p>

 <p>Expanded @('*acl2-exports*') to include every documented symbol whose name
 starts with @('\"SET-\"').  Thanks to Jared Davis for remarking that @(tsee
 set-debugger-enable) was omitted from @('*acl2-exports*'), which led to this
 change.</p>

 <p>The @(see trace) mechanism has been improved so that the @(':native') and
 @(':multiplicity') options can be used together for Lisps that support the
 trace @(':exit') keyword.  These Lisps include GCL and Allegro CL, whose
 native trace utilities have been modified for ACL2.  For SBCL and CCL
 (OpenMCL), which use the built-in Lisp mechanism for returning multiple values
 in ACL2 (see @(see mv)), the use of @(':multiplicity') with @(':native')
 remains unnecessary and will be ignored.  In support of this change, the
 modification of native Allegro CL tracing for ACL2 was fixed to handle
 @(':exit') forms correctly that involve @(tsee mv).</p>

 <p><b>NEW FEATURES</b></p>

 <p>The command @(':')@(tsee redef!) is just like @(':')@(tsee redef), but
 prints a warning rather than doing a query.  The old version of @(':redef!')
 was for system hackers and has been renamed to @(':')@(tsee redef+).</p>

 <p>Introduced a new utility for evaluating a function call using the so-called
 executable counterpart &mdash; that is, executing the call in the logic rather
 than in raw Lisp.  See @(see ec-call).  Thanks to Sol Swords for requesting
 this utility and participating in its high-level design.</p>

 <p>See @(see print-gv) for a new utility that assists with debugging guard
 violations. Thanks to Jared Davis for requesting more tool assistance for
 debugging guard violations.</p>

 <p>Improved the guard violation error message to show the positions of the
 formals, following to a suggestion of Peter Dillinger.</p>

 <p>Added new @(tsee guard-debug) capability to assist in debugging failed
 attempts at @(see guard) verification.  See @(see guard-debug).  Thanks to
 Jared Davis for requesting a tool to assist in such debugging and to him,
 Robert Krug, and Sandip Ray for useful discussions.</p>

 <p>New utilities provide the formula to be proved by @(tsee verify-guards).
 See @(see verify-guards-formula) and see @(see guard-obligation), Thanks to
 Mark Reitblatt for making a request leading to these utilities.  These
 utilities can be applied to a term, not just an event name; thanks to Peter
 Dillinger for correspondence that led to this extension.</p>

 <p>A new utility causes runes to be printed as lists in proof output from
 simplification, as is done already in proof summaries.  See @(see
 set-raw-proof-format).  Thanks to Jared Davis for requesting this utility.</p>

 <p>An experimental capability allows for parallel evaluation.  See @(see
 parallelism).  Thanks to David Rager for providing an initial implementation
 of this capability.</p>

 <p>Defined @(tsee xor) in analogy to @(tsee iff).  Thanks to Bob Boyer, Warren
 Hunt, and Sol Swords for providing this definition.</p>

 <p>Improved distributed file @('doc/write-acl2-html.lisp') so that it can now
 be used to build HTML documentation files for @(see documentation) strings in
 user @(see books).  See the comment in the definition of macro
 @('acl2::write-html-file') at the end of that file.  Thanks to Dave Greve and
 John Powell for requesting this improvement.</p>

 <p>It is now possible to specify @(':')@(tsee hints) for non-recursive
 function definitions (which can be useful when definitions are automatically
 generated).  See @(see set-bogus-defun-hints-ok).  Thanks to Sol Swords for
 requesting such a capability.</p>

 <p>Keyword argument @(':dir') is now supported for @(tsee rebuild) just as it
 has been for @(tsee ld).</p>

 <p>We relaxed the criteria for functional substitutions, so that a function
 symbol can be bound to a macro symbol that corresponds to a function symbol in
 the sense of @(tsee macro-aliases-table).  So for example, a functional
 substitution can now contain the doublet @('(f +)'), where previously it would
 have been required instead to contain @('(f binary-+)').</p>

 <p>We now allow arbitrary packages in raw mode (see @(see set-raw-mode))
 &mdash; thanks to Jared Davis for requesting this enhancement &mdash; and more
 than that, we allow arbitrary Common Lisp in raw mode.  Note however that for
 arbitrary packages, you need to be in raw mode when the input is read, not
 just when the input form is evaluated.</p>

 <p>Two new keywords are supported by the @(tsee with-output) macro.  A
 @(':gag-mode') keyword argument suppresses some prover output as is done by
 @(tsee set-gag-mode).  Thanks to Jared Davis for asking for a convenient way
 to set @(see gag-mode) inside a book, in particular perhaps for a single
 theorem; this keyword provides that capability.  A @(':stack') keyword allows
 sub-@(see events) of @(tsee progn) or @(tsee encapsulate) to ``pop'' the
 effect of a superior @(tsee with-output) call.  Thanks to Peter Dillinger for
 requesting such a feature.  See @(see with-output).</p>

 <p>The command @(tsee good-bye) and its aliases @(tsee exit) and @(tsee quit)
 now all take an optional status argument, which provides the Unix exit status
 for the underlying process.  Thanks to Florian Haftmann for sending a query to
 the ACL2 email list that led to this enhancement.</p>

 <p>Keyword commands now work for macros whose argument lists have lambda list
 keywords.  For a macro with a @('lambda') list keyword in its argument list,
 the corresponding keyword command reads only the minimum number of required
 arguments.  See @(see keyword-commands).</p>

 <p>It is now legal to @(tsee declare) variables @('ignorable') in @(tsee let*)
 forms, as in @('(let* ((x (+ a b)) ...) (declare (ignorable x)) ...)').
 Thanks to Jared Davis for requesting this enhancement.</p>

 <p>Added a warning when more than one hint is supplied explicitly for the same
 goal.  It continues to be the case that only the first hint applicable to a
 given goal will be applied, as specified in the user-supplied list of
 @(':hints') followed by the @(tsee default-hints-table).  Thanks to Mark
 Reitblatt for sending a question that led both to adding this clarification to
 the @(see documentation) and to adding this warning.</p>

 <p>You may now use @(tsee set-non-linear), @(tsee set-let*-abstraction),
 @('set-tainted-ok'), and @(tsee set-ld-skip-proofs) in place of their versions
 ending in ``@('p')''.  Thanks to Jared Davis for suggesting consideration of
 such a change.  All ``@('set-')'' utilities now have a version without the
 final ``@('p')'' (and most do not have a version with the final
 ``@('p')'').</p>

 <p>Added a \"Loop-Stopper\" warning when a @(':')@(tsee rewrite) rule is
 specified with a @(':')@(tsee loop-stopper) field that contains illegal
 entries that will be ignored.  Thanks to Jared Davis for recommending such a
 warning.</p>

 <p>Added a substantial documentation topic that provides a beginner's guide to
 the use of quantification with @(tsee defun-sk) in ACL2.  Thanks to Sandip Ray
 for contributing this guide, to which we have made only very small
 modifications.  See @(see quantifier-tutorial).</p>

 <p>@(tsee Defun-sk) now allows the keyword option @(':strengthen t'), which
 will generate the extra constraint that that is generated for the
 corresponding @('defchoose') event; see @(see defchoose).  Thanks to Dave
 Greve for suggesting this feature.</p>

 <p><b>BUG FIXES</b></p>

 <p>Fixed a soundness bug related to the use of @(tsee mbe) inside @(tsee
 encapsulate) events.  An example proof of @('nil') (before the fix) is in a
 comment in @('(deflabel note-3-4 ...)') in the ACL2 source code.  We therefore
 no longer allow calls of @(tsee mbe) inside @(tsee encapsulate) events that
 have non-empty @(see signature)s.</p>

 <p>Fixed a bug related to the definition of a function supporting the macro
 @(tsee value-triple).  Although this bug was very unlikely to affect any user,
 it could be carefully exploited to make ACL2 unsound:</p>

 @({
  (defthm fact
    (equal (caadr (caddr (value-triple-fn '(foo 3) nil nil)))
           'value) ; but it's state-global-let* in the logic
    :rule-classes nil)
  (defthm contradiction
    nil
    :hints ((\"Goal\" :use fact :in-theory (disable (value-triple-fn))))
    :rule-classes nil)
 })

 <p>Non-@(tsee LOCAL) definitions of functions or macros are no longer
 considered redundant with built-ins when the built-ins have special raw Lisp
 code, because ACL2 was unsound without this restriction!  A comment about
 redundant definitions in source function @('chk-acceptable-defuns') shows how
 one could prove @('nil') without this new restriction.  Note that system
 utility @(':')@(tsee redef+) removes this restriction.</p>

 <p>Although ACL2 already prohibited the use of certain built-in @(':')@(tsee
 program) mode functions for @(tsee verify-termination) and during
 macroexpansion, we have computed a much more complete list of functions that
 need such restrictions, the value of constant
 @('*primitive-program-fns-with-raw-code*').</p>

 <p>Modified what is printed when a proof fails, to indicate more clearly which
 event failed.</p>

 <p>Fixed a problem with @(tsee dmr) in CCL (OpenMCL) that was causing a raw
 Lisp break after an interrupt in some cases.  Thanks to Gary Byers for a
 suggestion leading to this fix.</p>

 <p>Fixed bugs in @(see proof-builder) code for dealing with free variables in
 hypotheses.</p>

 <p>Upon an abort, the printing of @(tsee pstack) and @(see gag-mode) summary
 information for other than GCL was avoided when inside a call of @(tsee ld).
 This has been fixed.</p>

 <p>(Windows only) Fixed bugs for ACL2 built on SBCL on Windows, including one
 that prevented @(tsee include-book) parameters @(':dir :system') from working,
 and one that prevented certain compilation.  Thanks to Peter Dillinger for
 bringing these to our attention and supplying a fix for the second.  Thanks
 also to Andrew Gacek for bringing @(tsee include-book) issues to our
 attention.  Also, fixed writing of file @('saved_acl2') at build time so that
 for Windows, Unix-style pathnames are used.</p>

 <p>Fixed a hard Lisp error that could occur with keywords as @(tsee table)
 names, e.g., @('(table :a :a nil :put)').  Thanks to Dave Greve for bringing
 this problem to our attention and providing this example.</p>

 <p>Fixed handling of @(':OR') @(see hints) so that proof attempts under an
 @(':OR') hint do not abort (reverting to induction on the original input
 conjecture) prematurely.  Thanks to Robert Krug for pointing out this problem
 and pointing to a possible initial fix.</p>

 <p>(SBCL and CLISP only) It is now possible to read symbols in the
 @('\"COMMON-LISP\"') package inside the ACL2 command loop (see @(see lp)).
 This could cause a raw Lisp error in previous versions of ACL2 whose host
 Common Lisp was SBCL or CLISP.  Thanks to Peter Dillinger for bringing this
 issue to our attention.</p>

 <p>Fixed a bug that was preventing certain @(see hints), such as @(':do-not')
 hints, from being used after the application of an @(':or') hint.  Thanks to
 Robert Krug for bringing this bug to our attention.</p>

 <p>(Hons version only) Fixed a bug in the interaction of @(tsee memoize)
 (@(tsee hons) version only) with event processing, specifically in interaction
 with failures inside a call of @(tsee progn) or @(tsee encapsulate).  Thanks
 to Jared Davis for bringing this bug to our attention and sending an example.
 A simplified example may be found in a comment in source function
 @('table-cltl-cmd'), source file @('history-management.lisp'); search for
 ``Version_3.3'' there.</p>

 <p>Fixed @(tsee cw-gstack) so that its @(':evisc-tuple') is applied to the top
 clause, instead of using @('(4 5 nil nil)') in all cases.  If no
 @(':evisc-tuple') is supplied then @('(term-evisc-tuple t state)') is used for
 the top clause, as it is already used for the rest of the stack.</p>

 <p>Fixed a bug in the interaction of @(see proof-tree)s with @(':induct') hint
 value @(':otf-flg-override').  Thanks to Peter Dillinger for reporting this
 bug and sending an example that evokes it.</p>

 <p>Fixed bugs in @(':')@(tsee pr) and @(tsee find-rules-of-rune) for the case
 of rule class @(':')@(tsee elim).  Thanks to Robert Krug and Jared Davis for
 bringing these related bugs to our attention.</p>

 <p>Improved failure messages so that the key checkpoints are printed only once
 when there is a proof failure.  Formerly, a proof failure would cause the key
 checkpoints to be printed for every @(tsee encapsulate) or @(tsee
 certify-book) superior to the proof attempt.</p>

 <p>Fixed a bug in generation of @(see guard)s for calls of @(tsee
 pkg-witness).  Thanks to Mark Reitblatt for sending an example showing this
 bug.  The bug can be in play when you see the message: ``HARD ACL2 ERROR in
 MAKE-LAMBDA-APPLICATION: Unexpected unbound vars (\"\")''.  A distillation of
 Mark's example that causes this hard error is as follows.</p>

 @({
  (defun foo (x)
    (declare (xargs :guard t))
    (let ((y x)) (pkg-witness y)))
 })

 <p>The @(tsee cond) macro now accepts test/value pairs of the form @('(T
 val)') in other than the last position, such as the first such pair in
 @('(cond (t 1) (nil 2) (t 3))').  Thanks to Jared Davis for sending this
 example and pointing out that ACL2 was sometimes printing goals that have such
 a form, and hence cannot be submitted back to ACL2.  A few macros
 corresponding to @(tsee cond) in some books under @('books/rtl') and
 @('books/bdd') were similarly modified.  (A second change will probably not be
 noticeable, because it doesn't affect the final result: singleton @(tsee cond)
 clauses now generate a call of @(tsee or) in a single step of macroexpansion,
 not of @(tsee if).  For example, @('(cond (a) (b x) (t y))') now expands to
 @('(OR A (IF B X Y))') instead of @('(IF A A (IF B X Y))').  See the source
 code for @('cond-macro') for a comment about this change.)</p>

 <p>Fixed a bug in the interaction of @(see proof-builder) command @('DV'),
 including numeric (``diving'') commands, with the @(tsee add-binop) event.
 Specifically, if you executed @('(add-binop mac fn)') with @('fn') having
 arity other than 2, a @(see proof-builder) command such as 3 or @('(dv 3)') at
 a call of @('mac') could have the wrong effect.  We also fixed a bug in diving
 with @('DV') into certain @('AND') and @('OR') calls.  Thanks for Mark
 Reitblatt for bringing these problems to our attention with helpful
 examples.</p>

 <p>Fixed a couple of bugs that were causing an error, ``HARD ACL2 ERROR in
 RENEW-NAME/OVERWRITE''.  Thanks to Sol Swords for bringing the first of these
 bugs to our attention.</p>

 <p>Fixed a bug that could cause @(tsee certify-book) to fail in certain cases
 where there are @(tsee local) @(tsee make-event) forms.</p>

 <p>Fixed a bug in @(tsee start-proof-tree) that could cause Lisp to hang or
 produce an error.  Thanks to Carl Eastlund for sending an example to bring
 this bug to our attention.</p>

 <p>Fixed a bug in the proof output, which was failing to report cases where
 the current goal simplifies to itself or to a set including itself (see @(see
 specious-simplification)).</p>

 <p>Fixed a bug in @(tsee with-prover-time-limit) that was causing a raw Lisp
 error for a bad first argument.  Thanks to Peter Dillinger for pointing out
 this bug.</p>

 <p>The following was claimed in @(':doc') @(tsee note-3-3), but was not fixed
 until the present release:<br></br>

 Distributed directory @('doc/HTML/') now again includes installation
 instructions, in @('doc/HTML/installation/installation.html').</p>

 <p>In certain Common Lisp implementations &mdash; CCL (OpenMCL) and LispWorks,
 at least &mdash; an interrupt could leave you in a break such that quitting
 the break would not show the usual summary of key checkpoints.  This has been
 fixed.</p>

 <p><b>NEW AND UPDATED BOOKS</b></p>

 <p>Updated @('books/clause-processors/SULFA/') with a new version from Erik
 Reeber; thanks, Erik.</p>

 <p>Added new books directory @('tools/') from Sol Swords.  See
 @('books/tools/Readme.lsp') for a summary of what these books provide.</p>

 <p>The distributed book @('books/misc/file-io.lisp') includes a new utility,
 @('write-list!'), which is like @('write-list') except that it calls @(tsee
 open-output-channel!) instead of @(tsee open-output-channel).  Thanks to
 Sandip Ray for requesting this utility and assisting with its
 implementation.</p>

 <p>Added @('record-update') macro supplied by Sandip Ray to distributed book
 @('books/misc/records.lisp').</p>

 <p>Sandip Ray has contributed books that prove soundness and completeness of
 different proof strategies used in sequential program verification.
 Distributed directory @('books/proofstyles/') has three new directories
 comprising that contribution: @('soundness/'), @('completeness/'), and
 @('counterexamples/').  The existing @('books/proofstyles/') directory has
 been moved to its subdirectory @('invclock/').</p>

 <p>Jared Davis has contributed a profiling utility for ACL2 built on CCL
 (OpenMCL).  See @('books/misc/oprof.lisp').  Thanks, Jared.</p>

 <p>ACL2 utilities @(tsee getprop) and @(tsee putprop) take advantage of
 under-the-hood Lisp (hashed) property lists.  The new book
 @('books/misc/getprop.lisp') contains an example showing how this works.</p>

 <p>Added the following new book directories: @('books/paco/'), which includes
 a small ACL2-like prover; and @('books/models/jvm/m5'), which contains the
 definition of one of the more elaborate JVM models, M5, along with other files
 including JVM program correctness proofs.  See files @('Readme.lsp') in these
 directories, and file @('README') in the latter.</p>

 <p>Added <i>books</i> about sorting in @('books/sorting').  See
 @('Readme.lsp') in that directory for documentation.</p>

 <p>Added book @('books/misc/computed-hint-rewrite.lisp') to provide an
 interface to the rewriter for use in computed hints.  Thanks to Jared Davis
 for requesting this feature.</p>

 <p>Jared Davis has provided a pseudorandom number generator, in
 @('books/misc/random.lisp').</p>

 <p>Robert Krug has contributed a new library, @('books/arithmetic-4/'), for
 reasoning about arithmetic.  He characterizes it as being more powerful than
 its predecessor, @('books/arithmetic-3/'), and without its predecessor's
 rewriting loops, but significantly slower than its predecessor on some
 theorems.</p>

 <p>Incorporated changes from Peter Dillinger to verify guards for functions in
 @('books/ordinals/lexicographic-ordering.lisp') (and one in
 @('ordinal-definitions.lisp') in that directory).</p>

 <p>A new directory, @('books/hacking/'), contains a library for those who wish
 to use trust tags to modify or extend core ACL2 behavior.  Thanks to Peter
 Dillinger for contributing this library.  Obsolete version
 @('books/misc/hacker.lisp') has been deleted.  Workshop contribution
 @('books/workshops/2007/dillinger-et-al/code/') is still included with the
 workshops/ tar file, but should be considered deprecated.</p>

 <p>In @('books/make-event/assert.lisp'), changed @('assert!') and
 @('assert!-stobj') to return @('(value-triple :success)') upon success instead
 of @('(value-triple nil)'), following a suggestion from Jared Davis.</p>

 <p><b>EMACS SUPPORT</b></p>

 <p>Changed @('emacs/emacs-acl2.el') so that the fill column default (for the
 right margin) is only set (still to 79) in lisp-mode.</p>

 <p>Modified Emacs support in file @('emacs/emacs-acl2.el') so that names of
 events are highlighted just as @(tsee defun) has been highlighted when it is
 called.  Search in the above file for @('font-lock-add-keywords') for
 instructions on how to eliminate this change.</p>

 <p>The name of the temporary file used by some Emacs utilities defined in file
 @('emacs/emacs-acl2.el') has been changed to have extension @('.lsp') instead
 of @('.lisp'); thus it is now @('temp-emacs-file.lsp').  Also, `make' commands
 to `clean' books will delete such files (specifically,
 @('books/Makefile-generic') has been changed to delete
 @('temp-emacs-file.lsp')).</p>")

(defxdoc |NOTE-3-4(R)|
  :parents (release-notes)
  :short "ACL2 Version  3.4(r) (August, 2008) Notes"
  :long "<p>Please also see @(see note-3-4) for changes to Version 3.4 of
  ACL2.</p>

 <p>Fixed makefiles, @('books/nonstd/Makefile') and @('GNUmakefile').  The old
 set-up seemed to work fine as long as all books certified, but it was really
 broken, for example only certifying some of the books in
 @('books/nonstd/nsa/'), and then only when required by books in other
 directories.  Also fixed the ``@('clean')'' target to clean links rather than
 to make links.</p>")

(defxdoc note-3-5

; See the long comment just after this (deflabel note-3-5 ...) for a discussion
; of changes made March 9-16 for more efficient handling of certificates, etc.

; Added ignorable declaration to (expansion of) er-progn, anticipating
; optimizations in GCL 2.7.0 when it is ready.  (Camm Maguire reported warnings
; that er-progn-not-to-be-used-elsewhere-val is unused.)

; Replaced sloop::sloop by loop.

; :Doc at the terminal had sometimes suggested using :more when there's nothing
; more to print.  This has been fixed.  Thanks to Bob Boyer for bringing this
; issue to our attention.

; Regarding "~il[Gag-mode] now suppresses some messages" below: Search for the
; following comment to find code to modify if we want to undo this change:
;
; Suppress printing for :OR splits; see also other comments with this header.

; Regarding "sped up ~il[guard] generation for some functions", the change was
; in built-in-clausep to delay the call to trivial-clause-p.

; Note that we changed set-debugger-enable-fn so that it no longer sets
; *debugger-hook*.  Instead, our-abort is always called (in other than non-ansi
; GCL) but if the debugger is enabled, then only print-proof-tree-finish (along
; perhaps with print-call-history) is invoked.

; For hons version: Fixed typos 'current-acl2-wrld in function
; memoize-table-chk (should have been 'current-acl2-world), which has no
; functional impact but might improve performance of memoize commands.

; The item "Added a restriction in the linear arithmetic procedure for
; deleting" relates to a change to poly-weakerp, which necessitated (for
; non-linear arithmetic) a corresponding change to bounds-poly-with-var
; (formerly called bounds-polys-with-var1).

; The item "Fixed a bug that could cause simplifications to fail" pertains to a
; change to process-equational-polys.

; Fixed an apparent bug in translate-expand-term1, where after translating a
; form we tested if the UNtranslated form was a variablep or fquotep.

; Regarding "Fixed a bug in processing of ~c[:]~ilc[type-set-inverter] rules",
; below:  Changed call of if-tautologyp to tautologyp in
; chk-acceptable-type-set-inverter-rule.  Examples that now work and didn't
; before:
; (defun my-consp (x) (consp x))
; (defthm foo (equal (my-consp x) (consp x))
;   :rule-classes :type-set-inverter)
; Alternatively (but disable foo before trying this):
; (defthm bar (equal (my-consp x) (consp x))
;   :rule-classes ((:type-set-inverter
;                   :corollary (equal (my-consp x) (consp x))
;                   :type-set 1536)))

; Modified save-acl2-in-sbcl-aux and save-acl2-in-cmulisp-aux to store an
; absolute pathname for the underlying Lisp, after John Erickson reported
; problems with making an sbcl-based ACL2 image using a relative pathname for
; LISP= in the ACL2 make.

; Followed Jared Davis's suggestion of fixing message "To enable breaks into
; the debugger..." to print the suggested (SET-DEBUGGER-ENABLE T) correctly for
; the current package.

; Dropped the deceased-packages (second) argument of bad-lisp-objectp and
; chk-bad-lisp-object.

; Eliminated *read-object-eof* in favor of a dynamic-extent cons (in
; read-object), thanks to Bob Boyer.

; Eliminated constant *acl2-files* from the logic; it is now a constant defined
; in acl2.lisp.

; Regarding "Fixed a soundness bug in the handling of inequalities by the
; ~il[type-set] mechanism": The fix is in the handling of lambda applications
; inside type-set (see the comment "The pot-lst is not valid....").
; Here is how to see that bug in action.  The following theorem proves "using
; trivial observations", but the instance of it below evaluates to nil.

;  (thm
;   (IMPLIES (AND (< (CAR Y) (CADR X))
;                 (TRUE-LISTP X)
;                 (TRUE-LISTP Y)
;                 (< (CAR X) (CAR Y)))
;            (LET ((X Y) (Y X))
;                 (AND (TRUE-LISTP X)
;                      (TRUE-LISTP Y)
;                      (< (CAR X) (CAR Y))))))
;
;  (let ((x '(1 7 3)) (y '(4 5 6)))
;    (IMPLIES (AND (< (CAR Y) (CADR X))
;                  (TRUE-LISTP X)
;                  (TRUE-LISTP Y)
;                  (< (CAR X) (CAR Y)))
;             (LET ((X Y) (Y X))
;                  (AND (TRUE-LISTP X)
;                       (TRUE-LISTP Y)
;                       (< (CAR X) (CAR Y))))))

; A trace of type-set before the fix shows some odd behavior, a simpler version
; of which is below.  The pot-lst represents (< (car x) (car y)), which should
; be irrelevant inside the body of the lambda, but (erroneously) is used to
; return a type-set of *ts-t*.

;  (TYPE-SET '((LAMBDA (X Y)
;                      (< (CAR X) (CAR Y)))
;              Y X)
;            NIL NIL
;            '((Y 576) (X 512))
;            NIL (ENS STATE) (W STATE) NIL
;            '(((0)
;               (CAR Y)
;               ((((((CAR Y) . 1) ((CAR X) . -1))
;                  (3)
;                  (PT . 3))
;                 0 < NIL))))
;            NIL)
; ; From (trace$ type-set), notice the use of the pot-lst inside the body of the
; ; lambda:
;   2> (TYPE-SET ((LAMBDA (X Y) (< (CAR X) (CAR Y))) Y X)
;                NIL NIL ((Y 576) (X 512))
;                NIL |some-enabled-structure|
;                |current-acl2-world| NIL
;                (((0)
;                  (CAR Y)
;                  ((((((CAR Y) . 1) ((CAR X) . -1))
;                     (3)
;                     (PT . 3))
;                    0 < NIL))))
;                NIL)
;  ...
;     3> (TYPE-SET (< (CAR X) (CAR Y))
;                  NIL NIL ((X 576) (Y 512))
;                  T |some-enabled-structure|
;                  |current-acl2-world| NIL
;                  (((0)
;                    (CAR Y)
;                    ((((((CAR Y) . 1) ((CAR X) . -1))
;                       (3)
;                       (PT . 3))
;                      0 < NIL))))
;                  NIL)

; Changed fixnum declarations in some array functions to (signed-byte 32) and
; (unsigned-byte 31) declarations.

; The :multiplicity trace$ option was added in order to support break-on-error,
; so that raw-ev-fncall could be traced without using :native, so that the
; :cond option could be used.

; The fourth argument of observation1 is now a Boolean rather than an
; evisc-tuple.  We don't advertise this mod since observation1 is not
; advertised.

; Added suitable environment variable settings to ACL2 scripts saved for CCL
; (OpenMCL) and SBCL, thanks (respectively) to assistance from Gary Byers and
; Nikodemus Siivola.  In particular, profiling is now available for ACL2 in
; CCL using CHUD (see
; http://ccl.clozure.com/ccl-documentation.html#Profiling-Using-Apples-CHUD-metering-tools)
; and in SBCL, at least for SBCL 1.0.23 and later, e.g.:
;
; :q
; (require :sb-sprof)
; (sb-sprof:with-profiling (:max-samples 100000
;                           :alloc-interval 1
;                           :mode :alloc
;                           :sample-interval .00001
;                           :report :graph
;                           :loop nil
;                           :threads :all
;                           :show-progress nil)
;            (ld '((mini-proveall))))

; The modification pertaining to the mention of term-order below was carried
; out by eliminating code for variants of var-fn-count/var-fn-count-lst and
; arith-term-order, by generalizing the term-order algorithm so that
; arith-term-order is a special case.  See term-order1.  The main change to
; arith-term-order (which is used in linear arithmetic) is that it is now
; sensitive to the "pseudo function count", which (roughly speaking) is the
; number of implicit constructor function calls in constants.  These counts are
; compared for two terms after their variable counts and function call counts,
; but before the terms are compared lexicographically.

; Made tiny change to get-os in case :unix and :apple features (for example)
; are both present.

; Moved state-global-let* bindings of guard-checking-on and in-prove-flg down
; from prove to prove-loop0.  Note that proof-builder calls prove-loop; a
; comment in pc-prove in fact clarified that guard-checking-on is already bound
; to nil by pc-single-step-primitive, but this new way seems a safer way to go
; (maybe others will call prove-loop), and besides, now in-prove-flg is set,
; which is better for break-on-error.

; Added to GNUmakefile ACL2_SIZE for ACL2 package size, implementing an idea
; from Jared Davis.

; Eliminated a skip-proofs warning caused by chk-embedded-event-form when in a
; make-event but not an encapsulate, include-book, or certify-book.

; Note that the new ruler-extenders feature handles prog2$ slightly differently
; than before, since merging of base cases can now take place under a prog2$
; where before it did not.  But don't really say that in the :doc string below,
; because it seems too subtle to be worth the distraction.  Also notice that
; although ec-call is now a default ruler-extender where before it was not
; (unlike prog2$), nevertheless, since ec-call was likely not applied to calls
; of if, lambdas, or prog2$, it seems unlikely that the inclusion of ec-call as
; a default ruler-extender should have any effect.

; Regarding the "subtle soundness bug in the forming of constraints from
; deduced type prescriptions": This simplified iteratively-grow-constraint1,
; but the following is even more significant.  Now, the constraints are based
; entirely on the lexical content of the events, not on which runes are enabled
; in the current world -- see constraints-introduced and
; definitional-constraints.  This change may address other lurking soundness
; bugs, evoked using functional instantiation on the same encapsulated
; functions but for different worlds, of which we haven't even been aware.

  :parents (release-notes)
  :short "ACL2 Version  3.5 (May, 2009) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 3.4 into the following
 categories: changes to existing features, new features, heuristic
 improvements, bug fixes, new and updated books, Emacs support, and
 experimental @(tsee hons) version.  Each change is described in just one
 category, though of course many changes could be placed in more than one
 category.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>Many improvements have been made to ACL2's ``evisceration'' mechanism for
 hiding substructures of objects before they are printed, and to related
 documentation:</p>

 <blockquote>

 <p>o A new documentation topic explains evisc-tuples.  See @(see
 evisc-tuple).</p>

 <p>o A new interface, @(tsee set-evisc-tuple), has been provided for setting
 the four global evisc-tuples.  See @(see set-evisc-tuple).</p>

 <p>o A new mode, ``iprinting'', allows eviscerated output to be read back in.
 See @(see set-iprint).</p>

 <p>o Function @('default-evisc-tuple') has been deprecated and will probably
 be eliminated in future releases; use @('abbrev-evisc-tuple') instead.  Also
 eliminated is the brr-term-evisc-tuple (also the user-brr-term-evisc-tuple).
 The term-evisc-tuple controls printing formerly controlled by the
 brr-term-evisc-tuple or user-brr-term-evisc-tuple.</p>

 <p>o ACL2 output is done in a more consistent manner, respecting the intention
 of those four global evisc-tuples.  In particular, more proof output is
 sensitive to the term-evisc-tuple.  Again, see @(see set-evisc-tuple).</p>

 <p>o A special value, @(':DEFAULT'), may be provided to @(tsee
 set-evisc-tuple) in order to restore these @(see evisc-tuple)s to their
 original settings.</p>

 <p>o (Details for heavy users of the evisc-tuple mechanism) (1) There are no
 longer @(see state) globals named @('user-term-evisc-tuple') or
 @('user-default-evisc-tuple').  (2) Because of the above-mentioned
 @(':DEFAULT'), if you have referenced state globals directly, you should use
 accessors instead, for example @('(abbrev-evisc-tuple state)') instead of
 @('(@ abbrev-evisc-tuple)').  (3) For uniformity, @(tsee
 set-trace-evisc-tuple) now takes a second argument,
 @('state').</p></blockquote>

 <p>Improved @(tsee break-on-error) in several ways.  First, it breaks earlier
 in a more appropriate place.  Thanks to Dave Greve for highlighting this
 problem with the existing implementation.  Also, @(tsee break-on-error) now
 breaks on hard errors, not only soft errors (see @(see er), options @('hard')
 and @('hard?')).  Thanks to Warren Hunt and Anna Slobodova for sending an
 example that showed a flaw in an initial improvement.  Finally, new options
 cause printing of the call stack for some host Common Lisps.  See @(see
 break-on-error).  Thanks to Bob Boyer for requesting this feature.</p>

 <p>@(tsee Trace!) may now be used in raw Lisp (though please note that all
 soundness claims are off any time you evaluate forms in raw Lisp!).  Thanks to
 Bob Boyer for feedback that led to this enhancement.</p>

 <p>ACL2 now searches for file @('acl2-customization.lsp') in addition to (and
 just before) its existing search for @('acl2-customization.lisp'); See @(see
 acl2-customization).  Thanks to Jared Davis for suggesting this change, which
 supports the methodology that files with a @('.lisp') extension are
 certifiable books (thus avoiding the need to set the @('BOOKS') variable in
 makefiles; see @(see books-certification-classic)).</p>

 <p>Improved the error message for illegal @(tsee declare) forms of the form
 @('(type (satisfies ...))').  Thanks to Dave Greve for sending an example
 highlighting the issue.</p>

 <p>If trace output is going to a file (because @(tsee open-trace-file) has
 been executed), then a note will be printed to that effect at the time that a
 call of @(tsee trace$) or @(tsee trace!) is applied to one or more @(see
 trace) specs.</p>

 <p>The notion of redundancy (see @(see redundant-events)) has been made more
 restrictive for @(tsee mutual-recursion) events.  Now, if either the old or
 new event is a @(tsee mutual-recursion) event, then redundancy requires that
 both are @(tsee mutual-recursion) events that define the same set of function
 symbols.  Although we are not aware of any soundness bugs fixed by this
 modification, nevertheless we believe that it reduces the risk of soundness
 bugs in the future.</p>

 <p>The definition of @('trace*') has been moved to a book,
 @('misc/trace1.lisp').  A new version, used in ACL2s, is in book
 @('misc/trace-star.lisp').  @(see Trace) utilities @(tsee trace$) and @(tsee
 trace!) are still built into ACL2.  [Note: File @('misc/trace1.lisp') was
 deleted after Version 4.2.]</p>

 <p>Certain @(see certificate) files will now be much smaller, by printing in a
 way that takes advantage of structure sharing.  Certifying the following
 example produces a @('.cert') file of over 3M before this change, but less
 than 1K after the change.</p>

 @({
  (defun nest (i)
    ;; Makes an exponentially-sized nest of conses i deep.
    (if (zp i)
        nil
      (let ((next (nest (1- i))))
        (cons next next))))

  (make-event
   `(defconst *big* ',(nest 20)))
 })

 <p>Thanks to Sol Swords for providing the above example and to him as well as
 to Bob Boyer, Jared Davis, and Warren Hunt for encouraging development of this
 improvement.  We have also applied this improvement to the printing of
 function definitions to files on behalf of @(tsee certify-book) and @(tsee
 comp).</p>

 <p>Names of symbols are now printed with vertical bars according to the Common
 Lisp spec.  Formerly, if the first character of a symbol name could be the
 first character of the print representation of a number, then the symbol was
 printed using vertical bars (@('|..|')) around its name.  Now, a much more
 restrictive test for ``potential numbers'' is used, which can result in fewer
 such vertical bars.  Base 16 is now carefully considered as well; see @(see
 set-print-base).  Thanks to Bob Boyer for requesting this improvement.  Note
 that macros @('set-acl2-print-base') and @('set-acl2-print-case') have been
 replaced by functions; see @(see set-print-base) and see @(see
 set-print-case).</p>

 <p>The ACL2 reader now supports `@('#.')' syntax in place of the `@('#,')
 syntax formerly supported.  Thanks to Bob Boyer for requesting this change.
 See @(see sharp-dot-reader).  NOTE that because of this change, `@('#.')' no
 longer causes an abort; instead please use @('(a!)') or optionally, if in the
 ACL2 loop, @(':a!'); see @(see a!).</p>

 <p>Some small changes have been made related to @(see gag-mode):</p>

 <blockquote>

 <p>o @(see Gag-mode) now suppresses some messages that were being printed upon
 encountering disjunctive splits from @(':OR') @(see hints).  Thanks to Sol
 Swords for suggesting this improvement.</p>

 <p>o ACL2 had printed ``@('Q.E.D.')'' with all output suppressed and @(tsee
 gag-mode) enabled.  Now, ``@('Q.E.D.')'' will be suppressed when @('PROVE')
 and @('SUMMARY') output are suppressed, even if @('gag-mode') is enabled.</p>

 <p>o The use of @(tsee set-gag-mode) had drastic effects on the inhibited
 output (see @(see set-inhibit-output-lst)), basically inhibiting nearly all
 output (even most warnings) when turning on gag-mode and enabling all output
 except @('proof-tree') output when turning off gag-mode.  Now, @(tsee
 set-gag-mode) only inhibits or enables proof (@('PROVE')) output, according to
 whether gag-mode is being turned on or off (respectively).  The related
 utility @(tsee set-saved-output) has also been modified, basically to
 eliminate @(':all') as a first argument and to allow @('t') and @(':all') as
 second arguments, for inhibiting prover output or virtually all output,
 respectively (see @(see set-saved-output)).</p></blockquote>

 <p>A @(tsee defstub) event @(see signature) specifying output of the form
 @('(mv ...)') now introduces a @(':')@(tsee type-prescription) rule asserting
 that the new function returns a @(tsee true-listp) result.  Thanks to Bob
 Boyer for sending the following example, which motivated this change.</p>

 @({
  (defstub census (*) => (mv * *))
  (defn foo (x)
    (mv-let (a1 a2)
            (census x)
            (list a1 a2)))
 })

 <p>Improved the efficiency of @(tsee string-append) so that in raw Lisp, it
 calls @(tsee concatenate).  Thanks to Jared Davis for suggesting this change,
 including the use of @(tsee mbe).  A minor change was made to the definition
 of @(tsee concatenate) to support this change, and the lemma
 @('append-to-nil') was added (see below).</p>

 <p>The checksum algorithm used for @(see certificate) files of @(see books)
 has been changed.  Thanks to Jared Davis for contributing the new code.  This
 change will likely not be noticed unless one is using the experimental @(tsee
 hons) version of ACL2, where it can greatly speed up book certification and
 inclusion because of function memoization (of source function
 @('fchecksum-obj')).</p>

 <p>Fewer calls are made to the checksum algorithm on behalf of @(tsee
 certify-book) and a few other operations.  Thanks to Jared Davis for providing
 data that helped lead us to these changes.</p>

 <p>Formatted printing directives @('~p'), @('~q'), @('~P'), and @('~Q') are
 deprecated, though still supported.  See @(see fmt).  Instead, please use
 @('~x'), @('~y'), @('~X'), and @('~Y') (respectively).  As a by-product, rule
 names in proof output are no longer hyphenated.</p>

 <p>A new keyword, @(':multiplicity'), is available for tracing raw Lisp
 functions using the ACL2 @(see trace) utility.  See @(see trace$).</p>

 <p>Users may now control whether or not a slow array access results in a
 warning printed to the screen (which is the default, as before), and if so,
 whether or not the warning is followed by a break.  See @(see
 slow-array-warning).</p>

 <p>On linux-like systems (including Mac OS X and SunOS), @(':')@(tsee comp)
 will now write its temporary files into the @('\"/tmp\"') directory, which is
 the value of @(tsee state) global @(''tmp-dir').  You can change that
 directory with @('(assign tmp-dir \"<your_temp_directory_path>\")').</p>

 <p>The messages printed for uncertified books have been enhanced.  Thanks to
 Jared Davis for requesting such an improvement.</p>

 <p>A function definition that would be redundant if in @(':')@(tsee logic)
 mode is now considered redundant even if it (the new definition) is in
 @(':')@(tsee program) mode.  That is, if a definition is ``downgraded'' from
 @(':logic') to @(':program') mode, the latter (@(':program') mode) definition
 is considered redundant.  Previously, such redundancy was disallowed, but we
 have relaxed that restriction because of a scenario brought to our attention
 by Jared Davis: include a book with the @(':logic') mode definition, and then
 include a book with the @(':program') mode definition followed by @(tsee
 verify-termination).  Thanks, Jared.</p>

 <p>The ACL2 reader no longer accepts characters other than those recognized by
 @(tsee standard-char-p) except for @('#\\Tab'), @('#\\Page'), and
 @('#\\Rubout') (though it still accepts strings containing such characters).
 As a result, no @(tsee make-event) expansion is allowed to contain any such
 unacceptable character or string.  Thanks to Sol Swords for sending an example
 that led us to make this restriction.  A simple example is the following
 book:</p>

 @({
  (in-package \"ACL2\")
  (defconst *my-null* (code-char 0))
  (make-event `(defconst *new-null* ,*my-null*))
 })

 <p>For this book, a call of @(tsee certify-book) formerly broke during the
 compilation phase, but if there was no compilation, then a call of @(tsee
 include-book) broke.  Now, the error occurs upon evaluation of the @(tsee
 make-event) form.</p>

 <p>ACL2 now collects up @(see guard)s from @(tsee declare) forms more as a
 user might expect, without introducing an unexpected ordering of conjuncts.
 We thank Jared Davis for sending us the following illustrative example,
 explained below.</p>

 @({
  (defun f (x n)
    (declare (xargs :guard (and (stringp x)
                                (natp n)
                                (= (length x) n)))
             (type string x)
             (ignore x n))
    t)
 })

 <p>Formerly, a guard was generated for this example by unioning the conjuncts
 from the @(':guard') onto a list containing the term @('(string x)') generated
 from the @('type') declaration, resulting in an effective guard of:</p>

 @({
  (and (natp n)
       (= (length x) n)
       (stringp x))
 })

 <p>The guard of this guard failed to be verified because @('(stringp x))') now
 comes after the call @('(length x)').  With the fix, contributions to the
 guards are collected up in the order in which they appear.  So in the above
 example, the effective guard is the specified @(':guard'); the contribution
 @('(stringp x)') comes later, and is thus dropped since it is redundant.  NOTE
 by the way that if @(':guard') and @(':stobjs') are specified in the same
 @(tsee xargs) form, then for purposes of collecting up the effective guard as
 described above, @(':stobjs') will be treated as through it comes before the
 @(':guard').</p>

 <p>Modified @(tsee close-output-channel) to try to do a better job flushing
 buffers.  Thanks to Bob Boyer for helpful correspondence.</p>

 <p>The notion of ``subversive recursion'' has been modified so that some
 functions are no longer marked as subversive.  See @(see
 subversive-recursions), in particular the discussion elaborating on the notion
 of ``involved in the termination argument'' at the end of that @(see
 documentation) topic.</p>

 <p>Formerly, @(':')@(tsee type-prescription) rules for new definitions inside
 @(tsee encapsulate) forms were sometimes added as @(see constraint)s.  This is
 no longer the case.  See also discussion of the ``soundness bug in the forming
 of constraints'', which is related.</p>

 <p><b>NEW FEATURES</b></p>

 <p>It is now possible to affect ACL2's termination analysis (and resulting
 induction analysis).  Thanks to Peter Dillinger for requesting this feature.
 The default behavior is essentially unchanged.  But for example, the following
 definition is accepted by ACL2 because of the use of the new
 @(':ruler-extenders') features; See @(see ruler-extenders).</p>

 @({
    (defun f (x)
      (declare (xargs :ruler-extenders :all))
      (cons 3
            (if (consp x)
                (f (cdr x))
              nil)))
 })

 <p>The following lemma was added in support of the improvement to @(tsee
 string-append) described above:</p>

 @({
  (defthm append-to-nil
    (implies (true-listp x)
             (equal (append x nil)
                    x)))
 })

 <p>A mechanism has been provided for users to contribute documentation.  See
 @(see managing-acl2-packages) for an example, which contains a link to an
 external web page on effective use of ACL2 packages, kindly provided by Jared
 Davis.  ACL2 @(see documentation) strings may now link to external web pages
 using the new symbol, @('~url'); see markup.  Of course, those links
 appear in the web version of the documentation, but you made need to take a
 bit of action in order for these to appear as links in the Emacs Info version;
 see @(see documentation).</p>

 <p>Added @(tsee intersectp) (similar to @(tsee intersectp-eq) and @(tsee
 intersectp-equal)).</p>

 <p>The user now has more control over how ACL2 prints forms; See @(see
 print-control).  Thanks to Bob Boyer for useful discussions leading to this
 enhancement.</p>

 <p>Some Common Lisp implementations only allow the syntax
 @('pkg-name::expression') when @('expression') is a symbol.  The ACL2 reader
 has been modified to support a package prefix for arbitrary expressions; see
 @(see sharp-bang-reader).  Thanks to Hanbing Liu for a query that led to this
 feature and to Pascal J. Bourguignon for suggesting an implementation.</p>

 <p>Ill-formed @(see documentation) strings need not cause an error.  See
 @('set-ignore-doc-string-error').  Thanks to Bob Boyer for requesting this
 feature.</p>

 <p>Type declarations are now permitted in @('let*') forms; see @(see let*),
 see @(see declare), and see @(see type-spec).</p>

 <p>(For Lisp programmers) Macro @('with-live-state') has been provided for
 programmers who refer to free variable @('STATE'), for example with macros
 that generate uses of @('STATE'), and want to avoid compiler warnings when
 evaluating in raw Lisp.  For example, the following form can be submitted
 either inside or outside the ACL2 loop to get the desired effect (see
 @('doc-string')): @('(with-live-state (f-put-global 'doc-prefix \" \"
 state))').  For another example use of this macro, see the definition of
 @('trace$') (ACL2 source file @('other-events.lisp')).</p>

 <p>(System hackers only) Added @(':')@(tsee redef-) to undo the effect of
 @(':')@(tsee redef+).  See @(see redef-).</p>

 <p>Function @(tsee random$) is a built-in random number generator.  See @(see
 random$).  Thanks to Sol Swords for requesting this feature and providing an
 initial implementation.</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>Sped up @(see guard) generation for some functions with large if-then-else
 structures in their bodies.  Thanks to Sol Swords for sending an illustrative
 example.</p>

 <p>Sped up @(see guard) generation in some cases by evaluating ground
 (variable-free) subexpressions.  Thanks to Bob Boyer for sending a motivating
 example: @('(defn foo (x) (case x ((1 2) 1) ((3 4) 3) ... ((999 1000)
 999)))').</p>

 <p>Modified slightly a heuristic association of ``size'' with constants, which
 can result in significant speed-ups in proofs involving constants that are
 very large @('cons') trees.</p>

 <p>Added a restriction in the linear arithmetic procedure for deleting
 polynomial inequalities from the linear database.  Formerly, an inequality
 could be deleted if it was implied by another inequality.  Now, such deletion
 requires that certain heuristic ``parent tree'' information is at least as
 restrictive for the weaker inequality as for the stronger.  Thanks to Dave
 Greve for bringing a relevant example to our attention and working with us to
 figure out some surprising behavior, and to Robert Krug for making a key
 observation leading to the fix.</p>

 <p>(GCL especially) Improved compiled code slightly by communicating to raw
 Lisp the output type when a function body is of the form @('(the character
 ...)').  This tiny improvement will probably only be observed in GCL, if at
 all.</p>

 <p>Applied a correction suggested by Robert Krug to the variant of @(tsee
 term-order) used in parts of ACL2's arithmetic reasoning.</p>

 <p><b>BUG FIXES</b></p>

 <p>Fixed bugs in the handling of @(tsee flet) expressions, one of which had
 the capability of rendering ACL2 unsound.  Thanks to Sol Swords for pointing
 out two issues and sending examples.  One example illustrated how ACL2 was in
 essence throwing away outer @(tsee flet) bindings when processing an inner
 @('flet').  We have exploited that example to prove a contradiction, as
 follows: this book was certifiable before this fix.</p>

 @({
  (in-package \"ACL2\")

  (defun a (x)
    (list 'c x))

  ; Example from Sol Swords, which failed to be admitted (claiming that
  ; function A is undefined) without the above definition of A.
  (defun foo1 (x y)
     (flet ((a (x) (list 'a x)))
       (flet ((b (y) (list 'b y)))
         (b (a (list x y))))))

  (defthm not-true
    (equal (foo1 3 4)
           '(b (c (3 4))))
    :hints ((\"Goal\"
             :in-theory
             (disable (:executable-counterpart foo1))))
    :rule-classes nil)

  (defthm contradiction
    nil
    :hints ((\"Goal\" :use not-true))
    :rule-classes nil)
 })

 <p>Sol's second example, below, pointed to a second bug related to computing
 output signatures in the presence of nested @('flet') expressions, which we
 have also fixed: this form failed before the fix.</p>

 @({
  :trans (flet ((foo (a) (list (flet ((bar (b) b)) a)))) x)
 })

 <p>Fixed a subtle soundness bug in the forming of constraints from deduced
 type prescriptions.  As a result, when ACL2 prints a warning message labeling
 encapsulated functions as ``subversive'', ACL2 will no longer deduce
 @(':')@(tsee type-prescription) rules for those functions.  Examples that
 exploit the bug in ACL2 Version_3.4 may be found in comments in ACL2 source
 function @('convert-type-set-to-term') (file @('other-processes.lisp')) and
 especially in function @('putprop-type-prescription-lst') (file
 @('defuns.lisp')).  For more on the general issue of ``subversive
 recursions,'' see @(see subversive-recursions).)</p>

 <p>Fixed a soundness bug in the handling of inequalities by the @(see
 type-set) mechanism, which was using the inequality database inside the body
 of a @(tsee lambda).</p>

 <p>Fixed a long-standing soundness bug in @(tsee compress1) and @(tsee
 compress2), whose raw Lisp code gave the logically incorrect result in the
 case of a single entry other than the @(tsee header), where that entry mapped
 an index to the @(tsee default) value.  Also fixed soundness bugs in @(tsee
 compress1), in the case of @(':order >'), where the raw Lisp code could drop
 the @(tsee header) from the result or, when the input alist had entries in
 ascending order, fail to return an alist in descending order.  For example,
 the following book certified successfully.</p>

 @({
  (in-package \"ACL2\")
  (defthm true-formula-1
    (equal (compress1 'a '((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5
                                    :DEFAULT 1 :NAME A :ORDER <)
                           (1 . 1)))
           '((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5
                      :DEFAULT 1 :NAME A :ORDER <)))
    :hints ((\"Goal\" :in-theory (disable (compress1))))
    :rule-classes nil)
  (defthm ouch-1
    nil
    :hints ((\"Goal\" :use true-formula-1))
    :rule-classes nil)
  (defthm true-formula-2
    (equal (compress1 'a '((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5
                                    :DEFAULT NIL :NAME A :ORDER >)
                           (1 . 1)
                           (2 . 2)))
           '((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5
                      :DEFAULT NIL :NAME A :ORDER >)
             (2 . 2)
             (1 . 1)))
    :hints ((\"Goal\" :in-theory (disable (compress1))))
    :rule-classes nil)
  (defthm ouch-2
    nil
    :hints ((\"Goal\" :use true-formula-2))
    :rule-classes nil)
  (defthm true-formula-3
    (equal (compress1 'a '((:HEADER :DIMENSIONS (3) :MAXIMUM-LENGTH 4
                                    :NAME A :ORDER >)
                           (1 . B)
                           (0 . A)))
           '((:HEADER :DIMENSIONS (3) :MAXIMUM-LENGTH 4
                      :NAME A :ORDER >)
             (1 . B)
             (0 . A)))
    :hints ((\"Goal\" :in-theory (disable (compress1))))
    :rule-classes nil)
  (defthm ouch-3
    nil
    :hints ((\"Goal\" :use true-formula-3))
    :rule-classes nil)
 })

 <p>Fixed a soundness bug involving measured subsets and @(tsee
 verify-termination), by changing @(tsee verify-termination) so that it uses
 @(tsee make-event).  See @(see verify-termination), in particular the
 discussion about @(tsee make-event) near the end of that @(see documentation)
 topic.  Peter Dillinger first raised the idea to us of making such a change;
 when we found this soundness bug, we were certainly happy to do so!</p>

 <p>Fixed a bug that could cause a hard Lisp error but not, apparently,
 unsoundness.  The bug was in the lack of attention to the order of guard and
 type declarations when checking for redundancy.  In the following example, the
 second definition was redundant during the first pass of the @(tsee
 encapsulate) form.  The second definition, however, was stored on the second
 pass with a guard of @('(and (consp (car x)) (consp x))'), which caused a hard
 Lisp error when evaluating @('(foo 3)') due to a misguided attempt to evaluate
 @('(car 3)') in raw Lisp.  The fix is to restrict redundancy of definitions so
 that the guard and type declarations must be in the same order for the two
 definitions.</p>

 @({
  (encapsulate
   ()
   (local (defun foo (x)
            (declare (xargs :guard (consp x)))
            (declare (xargs :guard (consp (car x))))
            x))
   (defun foo (x)
     (declare (xargs :guard (consp (car x))))
     (declare (xargs :guard (consp x)))
     x))
  ; Now we get a hard Lisp error from evaluation of the guard of foo:
  (foo 3)
 })

 <p>Fixed a bug in the guard violation report for function @(tsee
 intern-in-package-of-symbol).  Thanks to Dave Greve for bringing this bug to
 our attention.</p>

 <p>Made a change to allow certain @(see hints), in particular certain
 @(':')@(tsee clause-processor) hints, that had previously caused errors during
 termination proofs by viewing the function being defined as not yet existing.
 Thanks to Sol Swords for bringing this issue to our attention with a nice
 example.</p>

 <p>ACL2 now properly handles interrupts (via control-c) issued during printing
 of the checkpoint summary.  Previously it was possible on some platforms to
 make ACL2 hang when interrupting both during a proof and during the ensuing
 printing of the checkpoint summary.  Thanks to Jared Davis and Sol Swords for
 bringing this problem to our attention.</p>

 <p>Fixed a bug that was preventing, inside some book @('\"b\"'), the use of a
 @(':dir') argument to @(tsee include-book) that refers to a directory defined
 using @(tsee add-include-book-dir) earlier in the book @('\"b\"').  (We found
 this ourselves, but we thank John Cowles for observing it independently and
 sending us a nice example.)</p>

 <p>(GCL and CCL only) Fixed a bug in certain under-the-hood type inferencing.
 Thanks to Sol Swords for sending an example using @(see stobj)s defined with
 the @(':inline') keyword, along with a helpful backtrace in CCL, and to Gary
 Byers for his debugging help.</p>

 <p>Fixed a bug in @(tsee print-gv), which was mishandling calls of functions
 with more than one argument.</p>

 <p>Fixed a bug in the handling of @(tsee AND) and @(tsee OR) terms by the
 @(see proof-builder) command @('DV'), including numeric (``diving'') commands.
 Thanks for Mark Reitblatt for bringing this problems to our attention with a
 helpful example.</p>

 <p>Fixed printing of goal names resulting from the application of @(':OR')
 @(see hints) so that they aren't ugly when working in other than the
 @('\"ACL2\"') package.  Thanks to Sol Swords for bringing this issue to our
 attention.</p>

 <p>Fixed @(see proof-tree) printing so that interrupts will not cause problems
 with hiding ordinary output because of incomplete proof-tree output.  Thanks
 to Peter Dillinger for pointing out this issue.</p>

 <p>Fixed a hard error that could be caused by mishandling a @(tsee force)d
 hypothesis during @(see forward-chaining).  Thanks to Peter Dillinger for
 bringing this bug to our attention by sending a useful example.</p>

 <p>Fixed a bug that could cause simplifications to fail because of alleged
 ``specious simplification.''  This bug could appear when deriving an equality
 from the linear arithmetic database, and then attempting to add this equality
 to the current goal's hypotheses when it was already present.  Thanks to Eric
 Smith for sending a helpful example (in July 2005!) that helped us debug this
 issue.</p>

 <p>Fixed a bug in processing of @(':')@(tsee type-set-inverter) rules.</p>

 <p>Fixed a bug that was causing an error, at least for an underlying Lisp of
 CCL (OpenMCL), when @(tsee ec-call) was applied to a term returning multiple
 values.  Thanks to Sol Swords for sending an example that brought this bug to
 our attention.</p>

 <p>Fixed handling of array orders to treat keyword value @(':order :none')
 correctly from an array's @(tsee header).  Previously, there were two
 problems.  One problem was that @(':order :none') was treated like the default
 for @(':order'), @('<'), while @(':order nil') was treated in the manner
 specified by @(':order :none') (see @(see arrays)).  Now, both @(':order
 :none') and @(':order nil') are treated as @(':order nil') had been treated,
 i.e., so that there is no reordering of the alist by @(tsee compress1).  The
 other problem with this case of @(':order') was that the @(':maximum-length')
 field of the @(tsee header) was not being respected: the length could grow
 without bound.  Now, as previously explained (but not previously implemented)
 &mdash; see @(see arrays) &mdash; a @(tsee compress1) call made on behalf of
 @('aset1') causes a hard error if the header of the supplied array specifies
 an @(':order') of @(':none') or @('nil').</p>

 <p>An @('ignorable') @(tsee declare) form had caused an error in some contexts
 when it should have been allowed.  In particular, this problem could arise
 when using an @('ignorable') declaration at the top level in a @(tsee
 defabbrev) form.  It could also arise upon calling @(tsee verify-termination)
 when the corresponding @(tsee defun) form contained an @('ignorable')
 declaration at the top level.  These bugs have been fixed.</p>

 <p>Contrary to existing documentation (see @(see make-event-details)), the
 value of ``@(tsee ld) special variable'' @(tsee ld-skip-proofsp) was always
 set to @('nil') during @(tsee make-event) expansion, not merely when the
 @('make-event') form has a non-@('nil') value for keyword parameter
 @(':check-expansion').  This has been fixed.  Thanks to Sol Swords for
 bringing this issue to our attention.</p>

 <p>We have disallowed the certification of a book when not at the top-level,
 either directly in the top-level loop or at the top level of @(tsee ld).
 Before this restriction, the following would certify a book with a definition
 such as @('(defun foo (x) (h x))') that calls function @('h') before defining
 it, if the certification was by way of the form such as:</p>

 @({
  (er-progn (defun h (x) x) (certify-book \"my-book\"))
 })

 <p>But a subsequent @(tsee include-book) of @('\"my-book\"') would then fail,
 because @('h') is not defined at the top level.</p>

 <p>Printing with @(tsee fmt) directive @('~c') now works properly even when
 the print-base is other than 10.  Thanks to Sol Swords for reporting this bug
 and providing a fix for it.</p>

 <p>(SBCL, CMUCL, and CCL only) Fixed a bug in @(tsee sys-call-status) in the
 case that the underlying Common Lisp is SBCL, CMUCL, or CCL (OpenMCL).  Thanks
 to Jun Sawada for bringing this bug to our attention and providing a fix.</p>

 <p>Fixed a bug that was preventing @(tsee local) @(tsee defstobj) events in
 @(tsee encapsulate) events.  Thanks to Jared Davis for bringing this bug to
 our attention.</p>

 <p>Fixed a bug evidenced by error message ``Unexpected form in certification
 world'', which could result from attempting to certify a book after evaluating
 an @(tsee encapsulate) form with a local @(tsee defmacro).  Thanks to Jared
 Davis for pointing out this bug and sending the example:</p>

 @({
  (encapsulate
   ()
   (local (defmacro foo (x) `(table foo 'bar ,x)))
   (local (foo 3)))
 })

 <p>Formerly, evaluating a @(tsee trace$) form inside a @(see wormhole) such as
 the @(see break-rewrite) loop could leave the user in a bad state after
 returning to the top level, in which that function could not be untraced.
 This has been fixed.  Note however that when you proceed from a break in the
 @(see break-rewrite) loop, the tracing state will be the same as it was when
 you entered that break: all effects of calling @(tsee trace$) and @(tsee
 untrace$) are erased when you proceed from the break.</p>

 <p>A @(':')@(tsee guard) of @('(and)') is no longer ignored.  Thanks to Sol
 Swords for bringing this bug to our attention.</p>

 <p>A bug has been fixed that could result in needlessly weak induction schemes
 in the case that a recursive call is made in the first argument of @(tsee
 prog2$).  This has been fixed by including @(tsee prog2$) as a default
 ruler-extender in the new ruler-extenders feature (see above, and see @(see
 ruler-extenders)).  For details on this bug see Example 11 in distributed book
 @('books/misc/misc2/ruler-extenders-tests.lisp').</p>

 <p>(For CCL/OpenMCL on Windows) ACL2 should now build on CCL (OpenMCL) on
 Windows.  Thanks to David Rager for bringing this issue to our attention and
 helping with a fix that worked for CCL 1.2, and to the CCL team for improving
 handling of Windows-style filenames in CCL 1.3.</p>

 <p><b>NEW AND UPDATED BOOKS</b></p>

 <p>See <a
 href='https://code.google.com/p/acl2-books/wiki/ReleaseVersionNumbers'>ReleaseVersionNumbers</a>
 for a list of books in Version 3.5 of ACL2 but not Version 3.4.</p>

 <p>Run the shell command</p>

 <code> @('svn log -r 94:HEAD') </code>

 <p>to see all changes to @('books/') since the release of Version 3.4.</p>

 <p>Here are just a few highlights.</p>

 <p>Thanks largely to Jared Davis, many @('Makefile')s have been improved to do
 automatic dependency analysis.  See @(see books-certification-classic) for how
 to get your own @('Makefile')s to do this by adding a line: @('-include
 Makefile-deps').</p>

 <p>Libraries @('books/arithmetic-4/') and @('books/rtl/rel7/') have been
 eliminated from the default book certification (@('make regression')), in
 favor of new libraries @('books/arithmetic-5/') and @('books/rtl/rel8/')
 contributed by Robert Krug and Hanbing Liu, respectively.  They and Jun Sawada
 have arranged the compatibility of these libraries; i.e., it is possible to
 evaluate both of the following in the same session:</p>

 @({
  (include-book \"arithmetic-5/top\" :dir :system)
  (include-book \"rtl/rel8/lib/top\" :dir :system)
 })

 <p>Library @('books/rtl/rel1/') is no longer certified by default (though it
 is still distributed in support of ACL2(r); see @(see real)).</p>

 <p><b>EMACS SUPPORT</b></p>

 <p>Slightly modified @('Control-t e') (defined in @('emacs/emacs-acl2.el')) to
 comprehend the notion of an ``ACL2 scope'', and added @('Control-t o') to
 insert a superior @(tsee encapsulate) defining such a scope.  See the Emacs
 documentation for @('Control-t e') (generally obtained after typing
 @('Control-h k')).</p>

 <p>Modified distributed file @('emacs/emacs-acl2.el') so that if you put the
 following two forms in your @('~/.emacs') file above the form that loads
 @('emacs/emacs-acl2.el'), then Emacs will not start up a shell.  Thanks to
 Terry Parks for leading us to this modification.</p>

 @({
  (defvar acl2-skip-shell nil)
  (setq acl2-skip-shell t)
 })

 <p><b>EXPERIMENTAL HONS VERSION</b></p>

 <p>Bob Boyer and others have contributed numerous changes for the experimental
 ``@('hons')'' version of ACL2 (see @(see hons-and-memoization)).</p>

 <p>The ACL2 @(tsee state) can now be queried with @('(@ hons-enabled)') so
 that a result of @('t') says that one is in the experimental @('hons')
 version, while @('nil') says the opposite.</p>")

(defxdoc |NOTE-3-5(R)|
  :parents (release-notes)
  :short "ACL2 Version  3.5(r) (May, 2009) Notes"
  :long "<p>Please also see @(see note-3-5) for changes in Version 3.5 of
  ACL2.</p>

 <p>This release incorporates improvements from Ruben Gamboa in support for
 non-standard analysis in ACL2(r), in the following ways:</p>

 <p>ACL2(r) now supports non-classical objects that are not also numeric, e.g.,
 non-classical cons pairs.  Consequently, the built-in @('standard-numberp')
 has been replaced with @(tsee standardp).</p>

 <p>If @('f') is a classical function, the value @('(f x1 ... xn)') is
 guaranteed to be standard when the @('xi') are standard.  ACL2(r) can now
 recognize this fact automatically, using @('defun-std').  For example, the
 following can be used to assert that the square root of 2 is a standard
 value.</p>

 @({
  (defthm-std sqrt-2-rational
    (standardp (acl2-sqrt 2)))
 })

 <p>More generally, the expression @('(f x1 ... xn)') can contain free
 variables, but the result is guaranteed to be standard when the variables take
 on standard variables, as in the following:</p>

 @({
  (defthm-std sqrt-x-rational
    (implies (standardp x)
             (standardp (acl2-sqrt x))))
 })

 <p>A potential soundness bug in @(tsee encapsulate) was fixed.  Specifically,
 when a classical, constrained function is instantiated with a lambda
 expression containing free variables, it may produce non-standard values
 depending on the values of the free variables.  This means that the functional
 instantiation cannot be used to justify a non-classical theorem.  For example,
 consider the following sequence:</p>

 @({
  (encapsulate
    ((f (x) t))
    (local (defun f (x) x)))
  (defthm-std f-x-standard
    (implies (standardp x)
             (standardp (f x))))
  (defthm plus-x-standard
    (implies (standardp x)
             (standardp (+ x y)))
    :hints ((\"Goal\"
             :use ((:functional-instance f-x-standard
                                         (f (lambda (x) (+ x y))))))))
  (defthm plus-x-eps-not-standard
    (implies (standardp x)
             (not (standardp (+ x (/ (i-large-integer)))))))
  (defthm nil-iff-t
    nil
    :hints ((\"Goal\"
            :use ((:instance plus-x-standard
                             (y (/ (i-large-integer))))
                  (:instance plus-x-eps-not-standard)))))
 })

 <p>ACL2(r) also supports the introduction of non-classical functions with
 @(tsee defchoose).  These behave just as normal functions introduced with
 @(tsee defchoose), but they have a non-classical choice property.</p>

 <p>Finally, ACL2(r) now comes with a revamped library supporting non-standard
 analysis, still distributed separately as @('books/nonstd/').  The new library
 uses @(tsee defchoose) to state more natural and useful versions of the IVT,
 MVT, etc.  It also supports the introduction of inverse functions, e.g.,
 logarithms.  Finally, the library has much more extensive support for
 differentiation.</p>")

(defxdoc note-3-6

; Introduced qfuncall to avoid CCL warnings.

; Regarding "Fixed a bug in reporting failures when monitoring rewrite rules
; with free variables in the hypotheses": the bug was in
; tilde-@-failure-reason-free-phrase, taking a car before checking we had a
; consp.  However, we also found a bug (by inspection, never evoking it) in
; relieve-hyps1-free-2, and we added comments to relieve-hyps1-free-1 and
; relieve-hyps1-free-2 to explain better what we are returning.

; Some code has been refactored in the following functions in support of Daron
; Vroon's work on CCG analysis: put-induction-info, chk-acceptable-defuns,
; defuns-fn0, and defuns-fn.

; Delete dead code, redundant-event-tuplep and (now dead) good-defun-mode-p.

; Here is the proof of nil (using ACL2 Version  3.5) promised below regarding
; the soundness bug related to redundancy", as a certifiable book.
;;;;; start proof of nil ;;;;;
; (in-package "ACL2")
;
; (encapsulate
;  ()
;
;  (set-ruler-extenders :all)
;
;  (local
;   (encapsulate
;    ()
;    (defun f (x)
;      (if (equal x 17)
;          x
;        (cons (if (consp x) (f (cdr x)) x)
;              10)))))
;
;  (set-ruler-extenders :basic)
;
;  (encapsulate
;   ()
;   (defun f (x)
;     (if (equal x 17)
;         x
;       (cons (if (consp x) (f (cdr x)) x)
;             10)))))
;
; (defthm bad
;   (implies (true-listp x)
;            (consp x))
;   :hints (("Goal" :induct (f x))))
;
; (defthm contradiction
;   nil
;   :hints (("Goal" :use ((:instance bad (x nil)))))
;   :rule-classes nil)
;;;;; end proof of nil ;;;;;

; Here are the proofs of nil (using ACL2 Version  3.5) promised below regarding
; the "soundness bugs related to the handling of ~il[subversive-recursion]", as
; certifiable books.  The first exploits the bug in subversive-cliquep, while
; the second exploits the bug in subversivep.

;;;;; start proof of nil ;;;;;
; (in-package "ACL2")
;
; (encapsulate
;  ((my-test (x) t))
;  (local (defun my-test (x)
;           (declare (ignore x))
;           nil))
;  (set-bogus-mutual-recursion-ok t)
;  (mutual-recursion (defun f (x)
;                      (if (consp x)
;                          (f (cdr x))
;                        x))
;                    (defun g (x)
;                      (declare (xargs :measure (acl2-count x)))
;                      (if (my-test x)
;                          (not (g x))
;                        x))))
;
; (defthm my-test-is-nil
;   (null (my-test x))
;   :hints (("Goal" :use g))
;   :rule-classes nil)
;
; (defthm contradiction
;   nil
;   :hints (("Goal" :use ((:instance (:functional-instance my-test-is-nil
;                                                          (my-test identity))
;                                    (x t)))))
;   :rule-classes nil)
;;;;; end proof of nil ;;;;;

; As promised above, the following exploits the bug in subversivep in ACL2
; Version  3.5.
;;;;; start proof of nil ;;;;;
; (in-package "ACL2")
;
; (encapsulate
;  ((my-test (x) t))
;  (local (defun my-test (x)
;           (declare (ignore x))
;           nil))
;  (defun g (x)
;    (declare (xargs :measure (acl2-count x)))
;    (if (equal x (cons x x))
;        (g x)
;      (if (my-test x)
;          (not (g x))
;        x))))
;
; (defthm my-test-is-nil
;   (null (my-test x))
;   :hints (("Goal" :use g))
;   :rule-classes nil)
;
; (defthm contradiction
;   nil
;   :hints (("Goal" :use ((:instance (:functional-instance my-test-is-nil
;                                                          (my-test identity))
;                                    (x t)))))
;   :rule-classes nil)
;;;;; end proof of nil ;;;;;

; Peter Dillinger contributed a small refactoring of the code for relocating
; certificate files, including function make-certificate-file-relocated.

; Made a couple of changes in messages printed by our-abort, which is
; responsible for throwing one back to the top-level ACL2 loop in the event of
; a hard Lisp error.  We incorporated Peter Dillinger's request that the
; set-debugger-enable suggested be inhibited if set-debugger-enable-fn is
; untouchable.  Also, we no longer print "(Use (a!) ..."; see the comment
; there.

; Commented out a dynamic-extent declaration in read-object in case it is
; responsible for random Allegro CL failures related to reading certificates.

  :parents (release-notes)
  :short "ACL2 Version  3.6 (August, 2009) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 3.5 into the following
 categories of changes: existing features, new features, heuristic
 improvements, bug fixes, distributed books, Emacs support, and experimental
 @(see hons-and-memoization) version.  Each change is described in just one
 category, though of course many changes could be placed in more than one
 category.</p>

 <p>Note that (starting with ACL2 Version 3.5) LispWorks is no longer supported
 as a platform for ACL2, as the LispWorks compiler could not handle the ACL2
 sources; see comments in the ACL2 sources about ``function size'' being ``too
 large''.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>In the @(tsee xargs) @(tsee declare) form, the function symbol (or symbols,
 plural, in the case of @(tsee mutual-recursion)) being defined may now be used
 in the specified @(':measure') and @(':')@(tsee guard) terms.  Note that, the
 definition(s) of the new symbol(s) are still not used in the termination
 proof.  Thanks to Daron Vroon for discussions leading to this addition for the
 measure and to Dave Greve for requesting such an enhancement for the
 guard.</p>

 <p>Processing of the @(':guard-hints') in an @(tsee xargs) @(tsee declare)
 form is now delayed until the start of @(see guard) verification.  As a
 result, the function symbol(s) being defined may now be used as one might
 expect in such hints, for example in an @(':in-theory') form.  Thanks to Jared
 Davis for suggesting that we make such an improvement and providing an
 example.</p>

 <p>Made a low-level change to @(tsee make-event) in support of the ACL2s
 utility ``@('dynamic-make-event')''.  Thanks to Peter Dillinger for explaining
 the issue leading to this change.</p>

 <p>Modified the failure message printed when a measure conjecture fails to be
 proved, to indicate whether or not the hint @(':ruler-extenders :all') would
 create a different measure conjecture.  Thanks to Peter Dillinger for
 suggesting such a modification.</p>

 <p>A call of @(tsee add-default-hints) had added hints to the end of the
 current list of default hints.  Now, it adds them to the beginning of that
 list, so that they are tried first.  However, @(tsee add-default-hints) now
 takes a keyword argument, @(':at-end').  If that argument is supplied and
 evaluates to other than @('nil'), then the previous behavior occurs.</p>

 <p>When @(tsee save-exec) is used to save ACL2 images, the build dates are now
 printed on separate lines at startup and in the executable script.  Thanks To
 Bob Boyer for requesting some newlines.</p>

 <p>@(tsee Forward-chaining) rules are now generated so that every @(tsee let)
 (also @(tsee let*) and @(tsee lambda)) expression is expanded away, as is
 every call of a so-called ``guard holder'' (@(tsee must-be-equal), @(tsee
 prog2$), @(tsee ec-call), @(tsee the)).  These were formerly only expanded
 away in the conclusion.  Thanks to Konrad Slind for a helpful email leading to
 this change.</p>

 <p>@(tsee Current-theory) now causes a hard error when applied to a name not
 found in the current ACL2 logical @(see world), rather than simply returning
 @('nil').</p>

 <p>When the underlying Common Lisp is GCL, ACL2 no longer uses the @('#n=')
 reader macro when writing out certain files, including @(see certificate)
 files.  In all other Lisps, it now uses the @('#n=') ``print-circle'' feature
 not only for @(see certificate) files and ``@('expansion.lsp')'' files written
 for example in support of @(tsee make-event), but also for files written in
 support of @(':')@(tsee comp).  This is all managed with new @(see state)
 global variable @('print-circle-files'); see @(see print-control).  Thanks to
 Dave Greve for pointing out that GCL is limited by default to 1024 indices for
 @('#n=').</p>

 <p><b>NEW FEATURES</b></p>

 <p>A documentation topic explains in some detail how @(see hints) work with
 the ACL2 proof ``waterfall'': see @(see hints-and-the-waterfall).  This topic
 may be useful to those who write computed hints (see @(see computed-hints)) or
 other advanced hints.</p>

 <p>Added a new hint keyword, @(':no-thanks'), that avoids printing the usual
 ``Thanks'' message for @(see hints).  Thanks to Peter Dillinger for requesting
 this feature.</p>

 <p>Added a new hint keyword, @(':backtrack'), that checks the goals produced
 by processing a goal, and can cause the goal to be re-processed using a new
 hint.  See @(see hints).  Thanks to Pete Manolios for a conversation that led
 to the idea of this hint.</p>

 <p>Added a new class of hints, @(see override-hints), that is similar to @(see
 default-hints), except that override-hints are always applied, even if the
 user has supplied a hint explicitly for the goal.  See @(see override-hints).
 Thanks to Pete Manolios and Harsh Raju Chamarthi for useful discussions on
 this topic, including its application to testing.</p>

 <p>When a goal ready to be pushed for proof by induction is given the new hint
 ``@(':do-not-induct :otf')'', it is indeed pushed for proof by induction,
 rather than causing immediate failure as in the case of the hint
 ``@(':do-not-induct t')''.  Instead, the proof fails when the goal is later
 picked to be proved by induction.  Thanks to Peter Dillinger for discussions
 leading to this feature.</p>

 <p>Related to computed hints only: Each history entry in the list stored in
 variable @('HIST') (see @(see computed-hints)) now has a @(':CLAUSE') field,
 which provides access to a goal's parent, parent's parent, and so on (within
 the same induction and forcing round only).</p>

 <p>It is now possible to inhibit warnings produced by @(tsee in-theory) @(see
 events) and @(see hints) that occur when certain built-in definitions and
 executable-counterparts are disabled: just evaluate @('(assign
 verbose-theory-warning nil)').  Thanks to Jared Davis (and probably others in
 the past) for requesting such a mechanism.</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>A source function (@('linearize-lst')) was replaced by tail-recursive code,
 which can avoid a stack overflow.  Thanks to Dave Greve for sending a helpful
 example.</p>

 <p>The heuristics for limiting @(see forward-chaining) have been slightly
 relaxed, to allow derivations based on the occurrence of all arguments of the
 forward-chaining rule's conclusion in the goal (after stripping leading calls
 of @('NOT')).  Thanks to Dave Greve for contributing this improvement and
 providing a motivating example.</p>

 <p>We simplified induction schemes by eliminating each hypothesis of the form
 @('(not (equal term (quote const)))') for which some other hypothesis in the
 same case equates term with some (presumably other) quoted constant.  Thanks
 to Dave Greve for requesting an improvement of this sort.</p>

 <p><b>BUG FIXES</b></p>

 <p>Fixed a soundness bug related to redundancy of @(tsee encapsulate) events
 (see @(see redundant-events)) and @(see ruler-extenders).  A proof of @('nil')
 in ACL2 Version 3.5 appears in a comment in @('(deflabel note-3-6 ...)') in
 the ACL2 source code.  The fix is to insist that in order for one @(tsee
 encapsulate) event to be redundant with another, they must be evaluated with
 the same @(see default-ruler-extenders).  Analogous to this issue of @(see
 default-ruler-extenders) for @(tsee encapsulate)s is an issue of the @(see
 default-verify-guards-eagerness), which has similarly been fixed.</p>

 <p>Fixed soundness bugs related to the handling of @(see
 subversive-recursions) for @(see constraint)s.  Proofs of @('nil') in ACL2
 Version 3.5 appear in a comment in @('(deflabel note-3-6 ...)') in the ACL2
 source code.</p>

 <p>Fixed a bug that could cause the following error during calls of @(tsee
 certify-book) in the presence of calls of @(tsee skip-proofs) in the book:</p>

 @({
     ACL2 Warning [Skip-proofs] in

     HARD ACL2 ERROR in FMT0: Illegal Fmt Syntax.  The tilde-@ directive at
     position 0 of the string below is illegal because its variable evaluated
     to 0, which is neither a string nor a list.

     \"~@0\"
 })

 <p>Thanks to Dave Greve for reporting this bug and making available a very
 helpful test case.</p>

 <p>The @(':corollary') of a rule (see @(see rule-classes)) failed to use the
 @(tsee default-hints) of the logical @(see world).  This has been fixed.</p>

 <p>(CCL only) We removed a call, for CCL 1.3 (and beyond) only, of foreign
 function @('sync') in the closing of output channels.  Thanks to Daron Vroon
 for reporting issues with such a call on a non-Intel platform.</p>

 <p>Fixed a bug in reporting failures when monitoring rewrite rules with free
 variables in the hypotheses, that could cause a hard Lisp error (from which
 ACL2 continues, however).  Thanks to Eric Smith for sending a very helpful
 example with his bug report.</p>

 <p>Fixed the handling of @(':induct') @(see hints), which had thrown away hint
 information from parent goals.  For example, the @(tsee thm) form below failed
 to prove even though the second hint is in some sense superfluous; induction
 occurs automatically at @('\"Goal'\"') even without the hint on that.  The
 failure was due to discarding the hint information on @('\"Goal\"').</p>

 @({
  (in-theory (disable append))
  (thm (equal (cdr (cons a (append (append x y) z))) (append x y z))
       :hints
       ((\"Goal\" :in-theory (enable append))
        (\"Goal'\" :induct t) ; failed unless this line is commented out
        ))
 })

 <p>Fixed a bug in the @(tsee args) command that was failing to show the
 formals of primitives (built-in functions like @('consp') that do not come
 with explicit definitions).  Thanks to John Cowles for pointing out this bug.
 (At a lower level, the bug was that primitives failed to have @(''stobjs-in')
 or @(''stobjs-out') properties.)</p>

 <p>Fixed bugs in the utility supporting moving directories of certified books,
 sometimes used in Debian builds (as described in source function
 @('make-certificate-file')).  Thanks to Alan Dunn for pointing out such a bug,
 in paths associated with @(tsee defpkg) events in @(see portcullis) commands
 in @(see certificate)s (which are used for error reporting).  There were also
 bugs, now fixed, that prevented renaming some book paths.  Please note that
 this mechanism is not guaranteed to be sound; in particular, it can probably
 misbehave when macros are used to generate portcullis events.  However, it
 seems likely that such issues will be very rare.</p>

 <p>Eliminated warnings that could arise when tracing a function with @(tsee
 trace$).  Now, when @(tsee trace$) is applied to a function without option
 @(':native'), that function's declarations and documentation are
 discarded.</p>

 <p>Fixed a bug that could cause a failure when building an executable image
 using SBCL as the underlying Common Lisp.  Thanks to Jun Sawada for reporting
 this failure.  We made a similar fix for CMUCL.</p>

 <p>Fixed a bug in @(tsee save-exec) in the case that an absolute pathname is
 supplied.  Thanks to Jared Davis for bringing this bug to our attention.</p>

 <p>Fixed a bug in the use of @(tsee trace$) with the @(':native') and
 @(':multiplicity') options that caused hard errors for some underlying
 Lisps.</p>

 <p>Fixed a bug in the interaction of @(tsee trace$) and @(':')@(tsee comp),
 which caused error as @(tsee comp) tried to re-trace functions that it
 temporarily untraced.</p>

 <p><b>NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE</b></p>

 <p>See <a
 href='https://code.google.com/p/acl2-books/wiki/ReleaseVersionNumbers'>ReleaseVersionNumbers</a>
 for a list of books in Version 3.6 of ACL2 but not Version 3.5.  For
 <i>changes</i> to existing books rather than <i>additions</i>, see the <a
 href='http://code.google.com/p/acl2-books/source/list'>log entries</a>
 starting with revision r286 up through revision r329.</p>

 <p>It is no longer required to specify a value for environment (or `make')
 variable @('ACL2_SYSTEM_BOOKS') when running `make' in the distributed book
 directory, even when that directory is not under the directory containing the
 ACL2 executable.  Thanks to Peter Dillinger for providing this improvement, by
 modifying @('books/Makefile-generic') and, as needed, distributed book
 Makefiles.</p>

 <p>Thanks to Peter Dillinger, some books in support of the ACL2 Sedan (ACL2s)
 are more easily available for ACL2 users who do not use ACL2s.  See @(see
 acl2-sedan).</p>

 <p><b>EMACS SUPPORT</b></p>

 <p>If the following form is evaluated before the load of
 @('emacs/emacs-acl2.el'), then variables are now set to reflect the directory
 containing that file.</p>

 @({
  (if (boundp '*acl2-sources-dir*)
      (makunbound '*acl2-sources-dir*))
 })

 <p>Fixed info-dir-entry line in generated info file (by patching
 @('doc/write-acl2-texinfo.lisp')).  Thanks to Alan Dunn for providing this
 patch.</p>

 <p><b>EXPERIMENTAL HONS VERSION</b></p>

 <p>Bob Boyer and others have contributed numerous changes for the experimental
 ``@('hons')'' version of ACL2 (see @(see hons-and-memoization)).  A number of
 these have been crafted to work specifically with CCL (Clozure Common Lisp,
 formerly OpenMCL), which is now required as the underlying Lisp for the
 ``@('hons')'' version of ACL2.</p>

 <p>A heuristic (source function @('too-many-ifs') has been made more scalable
 (for the non-HONS version as well, in fact), but with no functional change.
 Thanks to Jared Davis for noticing performance issues and suggesting
 fixes.</p>

 <p>Other changes including the following, quoting Bob Boyer:</p>

 <blockquote><p>The CCL CASE macro now does better than a dumb linear search in
 some CASEes.</p>

 <p>SH and CSH are functions to talk to the underlying Gnu-Linux from CCL.
 Good for repeated calling when you simply cannot afford the copying cost of a
 FORK because you are using, say, a dozen gigabytes.</p>

 <p>Added CCL compiler-macros for IF and OR, to support some 'coverage'
 analysis, cf. IF-REPORT, extending the profiling.</p>

 <p>Introduced the type 'mfixnum' so that things like counting honses and
 counting calls to memoized or profiled functions can run fast in CCL 64 bits
 and yet still run at all under 32 bits.</p>

 <p>Moved all HONSes to CCL's newish static space, which permits the address of
 a cons to be used as a hash key, as in most Lisps.  (CCL moves most conses and
 most everything when it does a compacting-gc.)</p>

 <p>Quite a few changes in the memoize-fn reporting.</p>

 <p>Added a timer facility, cf. call-with-timeout.  Good for running under
 throttle some gross thoughts like 'Is it true that you can't fit 12 pigeons
 into 11 holes' on some propositional calculus systems/functions.</p>

 <p>Added rwx-size, pid-owner-cmdlines, rss, and proc-stat to help see what is
 really going on virtually in Gnu-Linux.</p>

 <p>Fixed at least one bug in compact-print-file and helped make its
 integration into ACL2's read-object$ a little more sound.  Still worried some
 about *print-readably* vs. readtable-case.  Does anyone else stay awake late
 at night worrying about readtable-case?</p>

 <p>Revised how the *watch-dog-process* interrupts the main process for the
 thousandth time, cf. watch.  Haven't changed it in weeks, which means that (a)
 it is getting tolerable or (b) I've run out of gas.</p></blockquote>")

(defxdoc |NOTE-3-6(R)|
  :parents (release-notes)
  :short "ACL2 Version  3.6(r) (August, 2009) Notes"
  :long "<p>Please also see @(see note-3-6) for changes in Version 3.6 of
  ACL2.</p>")

(defxdoc note-3-6-1
  :parents (release-notes)
  :short "ACL2 Version  3.6.1 (September, 2009) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>The essential changes to ACL2 since Version 3.6 are the two bug fixes
 described below.  There was also some functionality-neutral code refactoring,
 as requested by Daron Vroon in support of the ACL2 Sedan (see @(see
 acl2-sedan)).  Also see <a
 href='https://code.google.com/p/acl2-books/wiki/ReleaseVersionNumbers'>ReleaseVersionNumbers</a>
 for a list of books in Version 3.6.1 of ACL2 but not Version 3.6.  For
 <i>changes</i> to existing books rather than <i>additions</i>, see the <a
 href='http://code.google.com/p/acl2-books/source/list'>log entries</a>
 starting with revision r329 up through revision 350.</p>

 <p>Fixed a soundness bug in the handling of @(see ruler-extenders),
 specifically in the handling of @(tsee LET)-expressions.  Thanks to Pete
 Manolios, who sent us a proof of @('nil'), essentially as follows.  In the
 termination proof for @('foo') below, the binding of @('x') to @('(cons t x)')
 was not substituted into the recursive call of @('foo') for purposes of the
 termination proof.</p>

 @({
  (defun foo (x)
    (declare (xargs :ruler-extenders :all))
    (let ((x (cons t x)))
      (if (endp (cdr x))
          x
        (cons t (foo (cdr x))))))

  (defthm foo-bad
    nil
    :hints ((\"Goal\"
             :use ((:instance foo (x '(3))))
             :in-theory (disable foo (foo))))
    :rule-classes nil)
 })

 <p>Fixed a typo in code supporting @(see ruler-extenders) (specifically,
 swapped arguments in a recursive call of ACL2 source function
 @('get-ruler-extenders2'), which could cause problems for functions defined
 using @(tsee mutual-recursion)).  Thanks to Daron Vroon for bringing this bug
 to our attention, pointing out the swapped arguments.</p>")

(defxdoc note-4-0

; Thanks to Alan Dunn for contributing improvements to :doc markup and :doc
; truncate.

; Regarding "Fixed a bug in ~c[:]~ilc[pso] during the printing of failure
; messages for termination proofs.": The bug was the duplication of NAMES in
; the VARS for an IO? form in prove-termination.  The macro IO? now has a guard
; prohibiting such duplicates.

; Modified *1*-symbol (also, but probably less important, *1*-symbol? and
; global-symbol) to use find-package-fast, resulting in about 2% performance
; improvement for a hons-based include-book that can take a couple of minutes.

; Regarding the change in the too-many-ifs heuristic: See the Essay on
; Too-many-ifs.

; We improved the error provided when certify-book or include-book fails
; because :skip-proofs-okp or other keywords need to be non-nil.

; We improved The error provided when computing with a live
; stobj with :guard-checking :none, to suggest (set-guard-checking nil).
; Thanks to Harsh Raju Chamarthi for related helpful conversations.

; In support of the new :case-split-limitations hint (see :doc below), the the
; rewrite-constant record was modified, and clausify now takes an sr-limit
; instead of the world.

; In support of the change allowing user control over compilation of books by
; default, raw Lisp variable *suppress-compile* has been renamed
; *suppress-compile-build-time* and state global 'suppress-compile has been
; replaced by state global 'compiler-enabled, which has the opposite parity.

; Removed the prohibition of eval-when for #+cmu; not an issue at least as far
; back as CMUCL 19e.

; Used with-standard-io-syntax for ACL2 source macro write-exec-file so that
; executable scripts can be printed correctly even when implementation-specific
; print variables, such as ccl::*print-string-length*, are set.  Thanks to Bob
; Boyer for suggesting that some such change might be a good idea.

; Added a missing return-from in the raw Lisp GCL code for mod-expt.

; Fixed a bug that was leaving documentation strings in raw Lisp for functions
; that have ACL2 documentation strings.

; Fixed bug in two attempts to coerce a character (instead of a list of one
; character) to a string in bad-lisp-objectp.  Thanks to David Rager for
; pointing out a compiler warning printed by SBCL 1.0.34.2.

; Load-compiled now takes an optional verbosity argument, which is occasionally
; used to print a message saying that a compiled file is being loaded.

; Some changes to include-book should be invisible to the user, but include a
; default for :load-compiled-file of :default instead of :warn.  See :doc
; include-book, which has been improved.

; Weakened the definition of legal-acl2-character-p, in response to a helpful
; email from Jared Davis.

; Eliminated any checks for integers in bad-lisp-objectp, as explained in a
; comment there.

; We now print symbols in suitable packages for some :brr messages, thanks to
; feedback from Jared Davis.

; The directory stored for :dir :system is now always an absolute pathname
; (Unix style).

; In support of using portcullis commands in check-sum computations,
; eliminated the final check-sum-alist message from certify-book,
; which didn't seem appropriate anyhow.

; To prove nil in ACL2 Version_3.6.1 by exploiting the fact that portcullis
; commands were not included in check-sum computations, evaluate (ld
; "script.lsp") in a directory with contents shown below.

;;; % cat sub1.lisp
;;; (in-package "ACL2")
;;;
;;; ; Possible portcullis command:
;;; ; (defun f () 1)
;;;
;;; (defun g () 0)
;;;
;;; % cat sub2.lisp
;;; (in-package "ACL2")
;;;
;;; ; Possible portcullis command:
;;; ; (defun f () 2)
;;;
;;; (defun h () 0)
;;; % cat top1.lisp
;;; (in-package "ACL2")
;;;
;;; (include-book "sub1")
;;; (include-book "sub2")
;;;
;;; ; Certify with sub1's portcullis command.
;;; (defthm f-val-1
;;;   (equal (f) 1))
;;; % cat top2.lisp
;;; (in-package "ACL2")
;;;
;;; (include-book "sub1")
;;; (include-book "sub2")
;;;
;;; ; Certify with sub2's portcullis command.
;;; (defthm f-val-2
;;;   (equal (f) 2))
;;; % cat top.lisp
;;; (in-package "ACL2")
;;;
;;; (include-book "top1")
;;; (include-book "top2")
;;;
;;; (defthm contradiction
;;;   nil
;;;   :rule-classes nil
;;;   :hints (("Goal" :use (f-val-1 f-val-2)
;;;            :in-theory (theory 'ground-zero))))
;;; % cat script.lsp
;;; ; (ld "script.lsp")
;;;
;;; (defun f () 1)
;;; (certify-book "sub1" 1)
;;; (u)
;;; (u)
;;; (certify-book "sub2")
;;; (u)
;;; (certify-book "top1")
;;; (u)
;;;
;;; (defun f () 2)
;;; (certify-book "sub2" 1)
;;; (u)
;;; (u)
;;; (certify-book "sub1")
;;; (u)
;;; (certify-book "top2")
;;; (u)
;;;
;;; (certify-book "top")
;;; %

; Added .NOTPARALLEL to the dependencies of GNUmakefile target, large.  We hope
; this eliminates some build errors when using the -j option.

; Fixed a bug in "make copy-distribution" in GCL builds, where the presence of
; a filename that extends the designated directory string caused an error,
; erroneously stating that the directory already exists.

; Regarding "Fixed a bug that could make ~c[:]~ilc[oops] cause an error.": The
; fix is to use equal instead of eq in retract-world1; see the comment there.
; We similarly modified extend-world1.

; Fixed replace-colons so that something like ~ilc[:oops] in a :doc string
; doesn't cause an error when calling write-texinfo-file.

; Added small optimization in relevant-constraints1, to avoid a call of
; event-responsible-for-proved-constraint.

; Made small changes in doc/write-acl2-texinfo.lisp to avoid warnings when
; building the documentation.

; Improved make clean-doc.

; Eliminated unbound-macro-function and *unbound-macro-function*.  We now check
; in fmakunbound! that fmakunbound really does work on macros.

; Eliminated certify-book-disabledp.

; Fixed a small output bug, by modifying tilde-@-lmi-phrase to account properly
; for the case that functional instances were previously proved only by
; nameless events.  Here is an example:

;   (encapsulate
;    ((f1 (x) t)
;     (f2 (x) t))
;    (local (defun f1 (x) x))
;    (local (defun f2 (x) x))
;    (defthm f1-f2
;      (equal (f1 x) (f2 x))))
;
;   (encapsulate
;    ((g1 (x) t)
;     (g2 (x) t))
;    (local (defun g1 (x) x))
;    (local (defun g2 (x) x))
;    (defthm g1-g2
;      (equal (g1 x) (g2 x))))
;
;   (defthm f-thm1
;     (equal (f1 (cons x x))
;            (f2 (cons x x))))
;
;   (defun k1 (x)
;     (declare (xargs :guard (equal (g1 (cons x x))
;                                   (g2 (cons x x)))))
;     x)
;
;   (defun k2 (x)
;     (k1 x))
;
;   (verify-guards k2
;                  :hints (("Goal" :by (:functional-instance f-thm1
;                                                            (f1 g1)
;                                                            (f2 g2)))))

; Added Essay on the proved-functional-instances-alist, to clarify the life
; cycle of entries in world global 'proved-functional-instances-alist
; (supporting the caching of proved functional instances).

; There is a new source file, multi-threading-raw.lisp, which is loaded only
; when feature :acl2-par is present (see acl2::*acl2-files*).  It was
; contributed by David Rager to support the version of ACL2 that allows
; parallel evaluation (see :doc parallelism).

; Made a small change to the code for exit-lisp.

; In CCL, set ccl::*record-source-file* to nil after discussion with Gary
; Byers, to avoid paying the cost of recording source file information that can
; cause slowdown and isn't typically exploited by ACL2 users.  The HONS version
; still sets this variable to T.

; We now clean up stale values of 'redundant-raw-lisp-discriminator property
; when undoing a defconst or defstobj event, which could free up memory.

; Eliminated the notion of "era" in the ACL2 sources.

; Improved the message after the Q.E.D. for hints :by nil, because the old
; message was a bit misleading in the case of defun (where the goals may not
; actually pass translate).  Thanks to Jared Davis for pointing out this
; issue.

; The function iteratively-grow-constraint was significantly rewritten, and
; since its algorithm was no longer described by that name, we renamed it to
; encapsulate-constraint.

; Changed set-w! to call find-longest-common-retraction with event-p = t in all
; cases, not just when certifying or including books.  Thanks to Sol Swords for
; sending a relevant failure that led us to this change; see the comments in
; set-w!.

; Substantially improved the Essay on Correctness of Meta Reasoning.

  :parents (release-notes)
  :short "ACL2 Version  4.0 (July, 2010) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 3.6.1 into the
 following categories of changes: existing features, new features, heuristic
 improvements, bug fixes, distributed books, Emacs support, and experimental
 versions.  Each change is described in just one category, though of course
 many changes could be placed in more than one category.  Also see @(see
 note-3-6-1) for other changes since Version 3.6.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>There have been extensive changes to the handling of compiled files for
 books, which may generally be invisible to most users.  The basic idea is that
 when compiled files are loaded on behalf of @(tsee include-book), they are now
 loaded before events in the book are processed, not afterwards.  This can
 speed up calls of @('include-book'), especially if the underlying Lisp
 compiles all definitions on the fly (as is the case for CCL and SBCL).  One
 functional change is that for keyword argument @(':load-compiled-file') of
 @(tsee include-book), the values @(':comp-raw'), @(':try'), and @(':comp!')
 are no longer legal.  (Note that the handling of @(':comp-raw') was actually
 broken, so it seems that this value wasn't actually used by anyone; also, the
 handling of @(':comp!') formerly could cause an error in some Lisp platforms,
 including SBCL.)  Another change is that if @(tsee include-book) is called
 with @(':load-compiled-file t'), then each sub-book must have a compiled file
 or a so-called ``expansion file''; see @(see book-compiled-file).  In the
 unlikely event that this presents a problem, the makefile provides a way to
 build with compilation disabled; see @(see compilation).  Users of raw mode
 (see @(see set-raw-mode)) will be happy to know that @(tsee include-book) now
 works if there an up-to-date compiled file for the book, since @(tsee
 portcullis) commands are now incorporated into that compiled file.  The
 mechanism for saving expansion files has changed, and the @(':save-expansion')
 argument of @(tsee certify-book) has been eliminated; see @(see certify-book).
 More discussion of ACL2's new handling of book compilation is described in a
 new documentation topic; see @(see book-compiled-file).</p>

 <p>It was possible to get a hard Lisp error when certifying a book with a
 redundant @(tsee defconst) form whose term is not identical to the existing
 @(tsee defconst) form for the same name.  The following example illustrates
 the problem, which has been fixed (as part of the change in handling of
 compiled files for books, described above).  Imagine that after the initial
 @('(in-package \"ACL2\")') form, file @('foo.lisp') has just the form
 @('(defconst *a* (append nil nil))').  Then before the fix, we could have:</p>

 @({
    ACL2 !>(defconst *a* nil)
    [[output omitted]]
    ACL2 !>(certify-book \"foo\" 1)
    [[initial output omitted]
    * Step 5:  Compile the functions defined in \"/v/joe/foo.lisp\".
    Compiling /v/joe/foo.lisp.
    End of Pass 1.
    End of Pass 2.
    OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
    Finished compiling /vjoe/foo.lisp.
    Loading /v/joe/foo.lisp

    Error: Illegal attempt to redeclare the constant *A*.
 })

 <p>The @(tsee wormhole) facility has been changed to repair a bug that allowed
 guard violations to go undetected.  The major change has to do with the
 treatment of what used to be called the ``pseudo-flag'' argument which has
 been replaced by a quoted lambda expression.  See @(see
 note-4-0-wormhole-changes) for help in converting calls of @(tsee wormhole).
 Also see see @(see wormhole) and see @(see wormhole-eval).</p>

 <p>The function @('assign-wormhole-output') has been eliminated but its
 functionality can be provided by @(tsee wormhole-eval).</p>

 <p>The ACL2 tutorial has been greatly expanded, for example to include a
 self-contained discussion of rewriting.  See @(see acl2-tutorial).</p>

 <p>Formerly, the @(tsee mbe) macro and @(tsee must-be-equal) function were
 disallowed in any definition within an encapsulate having a non-empty
 signature.  Now, these are allowed provided the definition has been declared
 to be non-executable (see @(see defun-nx)).  As a result, @(tsee defevaluator)
 @(see events) may now include @(tsee must-be-equal) among the function symbols
 known by the evaluator; this had not previously been allowed.  Thanks to Sol
 Swords for discussions leading to this relaxation for @(tsee
 defevaluator).</p>

 <p>@(tsee Princ$) now prints strings more efficiently.  Thanks to Jared Davis
 for suggesting the improvements to @('princ$').</p>

 <p>The use of @(tsee xargs) declaration @(':non-executable t') no longer
 requires the absence of @(tsee state) or declared @(tsee stobj)s among the
 formal parameters of a function definition.  As before, the use of
 @(':non-executable t') turns off single-threadedness checking for the body,
 and also as before, attempts to execute the function will fail.  Thanks to Sol
 Swords for requesting this relaxation (for automatic generation of so-called
 ``flag functions'' for definitions using @(tsee mutual-recursion)).</p>

 <p>The @(see documentation) has been improved for explaining to advanced users
 the details of the ACL2 hint mechanism; see @(see hints-and-the-waterfall),
 and see the example about @('nonlinearp-default-hint') in distributed book
 @('books/hints/basic-tests.lisp').  Thanks to Robert Krug for useful
 discussions, in particular suggesting the above example as one to be explained
 with the documentation.</p>

 <p>The @('time$') macro has been enhanced to allow user control of the timing
 message that is printed, and of when it is printed.  See @(see time$).  Thanks
 to Jared Davis for providing the essential design, helpful documentation
 (largely incorporated), and an initial implementation for raw Lisp.</p>

 <p>The @(':ttags') argument to @(tsee include-book) had been required when
 including a certified book that uses trust tags.  This is no longer the case:
 essentially, @(':ttags') defaults to @(':all') except that warnings will be
 printed.  Thanks to Jared Davis for requesting such a relaxation, and to him
 and Sandip Ray for useful discussions.</p>

 <p>The definition of @(tsee mv-let) has been modified so that the single-step
 macroexpansion (see @(see trans1)) of its calls can be evaluated.  Thanks to
 Pete Manolios for bringing this evaluation issue to our attention and ensuing
 discussions.</p>

 <p>All calls of so-called ``guard-holders'' &mdash; @(tsee prog2$), @(tsee
 must-be-equal) (from calls of see @(see mbe)), @(tsee ec-call), and @(tsee
 mv-list) &mdash; are now removed before storing hypotheses of rules of class
 @(':')@(tsee rewrite) or @(':')@(tsee linear).  Thanks to Sol Swords for
 requesting this enhancement and sending the following example in the case of
 @(see rewrite) rules.</p>

 @({
  (defthm foo
    (prog2$ (cw \"asdf\")
            (and (equal (car (cons x y)) x)
                 (equal (cdr (cons x y)) y))))
 })

 <p>The handling of @(tsee fmt) directive @('~s') has been modified so that if
 the argument is a symbol that would normally be printed using vertical bars
 (@('|')), then that symbol is printed as with @('~f').  Thanks to Jared Davis
 for providing the following example showing that treatment of @('~s') was a
 bit unexpected: @('(cw \"~s0.~%\" '|fo\\|o|)').</p>

 <p>Error messages have been improved for ill-formed terms (in ACL2's so-called
 ``translation'' routines).  Thanks to Jared Davis for requesting such an
 enhancement.</p>

 <p>Modified @(tsee defun-sk) so that it executes in @(':')@(tsee logic) mode.
 Previously, evaluation of a @(tsee defun-sk) event in @(':')@(tsee program)
 mode caused a somewhat inscrutable error, but now, @(':')@(tsee program) mode
 is treated the same as @(':')@(tsee logic) mode for purposes of @(tsee
 defun-sk).</p>

 <p>The ``system hacker'' commands @('(')@(tsee redef+)@(')') and @('(')@(tsee
 redef-)@(')') are now embedded event forms (see @(see embedded-event-form)),
 hence may be used in @(see books) as well as in @(tsee progn) and @(tsee
 encapsulate) @(see events).  Also, these two commands are now no-ops in raw
 Lisp.</p>

 <p>The function symbol @('worldp') (in the @('\"ACL2\"') package) has been
 renamed to @('plist-worldp').</p>

 <p>The function @('gc$-fn') (resulting from macroexpansion of @(tsee gc$)) is
 now in @(':')@(tsee logic) mode.  Thanks to Jared Davis for requesting this
 change.</p>

 <p>The user now has control over whether compilation is used, for example
 whether or not @(tsee certify-book) compiles by default, using function
 @('set-compiler-enabled').  See @(see compilation).</p>

 <p>Modified the conversion of relative to absolute pathnames in @(see
 portcullis) @(see command)s for book certification.  Now, more pathnames
 remain as relative pathnames.</p>

 <p>The @('\"Ttags\"') warning that can be printed by @(tsee include-book) is
 now given even if @(tsee set-inhibit-output-lst) has specified `@('warning')'.
 To suppress it, specify @('warning!') instead, for example,
 @('(set-inhibit-output-lst '(acl2::warning! acl2::proof-tree))').</p>

 <p>On occasion, ACL2 prints the message ``Flushing current installed world''
 as it cleans up when certain actions (installing a @(see world)) are
 interrupted.  This operation has been sped up considerably.  If your session
 includes many @(see events), you can probably speed up any such operation
 further by invoking @(tsee reset-prehistory).  Thanks to Jared Davis for
 sending a query that led us to make this improvement.</p>

 <p>Calls of the form @('(ec-call (must-be-equal logic exec))') are no longer
 allowed, since we do not have confidence that they would be handled
 correctly.</p>

 <p>The underlying function for @(tsee good-bye) (and hence for @(tsee exit)
 and @(tsee quit)) is now in @(':')@(tsee logic) mode.  Thanks to Jared Davis
 for requesting this enhancement.</p>

 <p>We now require that every function symbol in the @(see signature) of an
 @(tsee encapsulate) event have a @(':')@(tsee logic) mode definition at the
 end of the first pass, not merely a @(':')@(tsee program) mode definition
 (which formerly was sufficient).  You can still define such a function in
 @(':program') mode, provided it is followed by a @(':logic') mode definition
 (where of course both definitions are @(see local), since we are discussing
 functions is introduced in the @(see signature)).  Thanks to Carl Eastlund for
 bringing this issue to our attention.  (Note: An analogous modification has
 been made for @(':')@(tsee bdd) @(see hints) as well.)</p>

 <p>The following functions now have raw Lisp implementations that may run
 faster than their ACL2 definitions: @(tsee assoc-eq), @(tsee assoc-equal),
 @(tsee member-eq), @(tsee member-equal), @('subsetp-eq'), @(tsee
 subsetp-equal), @(tsee remove-eq), @(tsee remove-equal), @(tsee position-eq),
 and @(tsee position-equal).  Thanks to Jared Davis for suggesting that we
 consider such an improvement.</p>

 <p>We now avoid infinite loops caused when tracing functions that implement
 @(tsee trace$).  Thanks to Rob Sumners and Eric Smith for useful
 discussions.</p>

 <p>The implementation of @(tsee trace!) has been modified slightly, to
 accommodate the fix for ``some holes in the handling of trust tags'' described
 later, below.</p>

 <p>This item applies unless the host Lisp is GCL.  An interrupt (control-c)
 will now cause a proof to exit normally in most cases, by simulating a
 timeout, as though @(tsee with-prover-time-limit) had been called with a
 time-limit of 0.  If the first interrupt doesn't terminate the proof, a second
 one should do so (because a different, more ``severe'' mechanism is used after
 the first attempt).  As a result, @(tsee redo-flat) should work as one might
 expect even if a proof is interrupted.  Thanks to Dave Greve for requesting
 this enhancement to @(tsee redo-flat).  Technical note: for reasons related to
 this change, time-limits are no longer checked in evaluator functions
 (@('ev-fncall'), @('ev'), @('ev-lst'), @('ev-fncall-w'), @('ev-w'), and
 @('ev-w-lst')).</p>

 <p>It is now legal for @(see proof-builder) @(see macro-command)s to appear in
 @(':')@(tsee instructions) that are used in place of @(':')@(tsee hints).
 Thanks to Sandip Ray for (most recently) requesting this feature.</p>

 <p>The value of @(':command-conventions') for @(tsee ld) special variable
 @('ld-post-eval-print') is now treated as though it were @('t') if the value
 @(tsee ld) special variable @('ld-error-triples') is @('nil').  The following
 example illustrates this change.</p>

 @({
  ACL2 !>(ld-post-eval-print state) ; default
  :COMMAND-CONVENTIONS
  ACL2 !>(ld-error-triples state) ; default
  T
  ACL2 !>(set-ld-error-triples nil state)
  *** Then, before the change:
  ACL2 !>(mv t 3 state)
   3
  *** Instead, after the change:
  ACL2 !>(mv t 3 state)
  (T 3 <state>)
 })

 <p>The default behavior of @(tsee ld) has been changed.  Formerly when an
 error occurred that halted a subsidiary call of @('ld'), then the parent
 @('ld') would continue.  That is no longer the case.  Consider the following
 example.</p>

 @({
  (ld '((ld '((defun f (x) x)
              (defun bad (x)) ; ERROR -- missing the body
              ))
        (defun g (x) x)))
 })

 <p>Formerly, @('g') would be defined in the resulting logical @(see world).
 Now, the error halts not only the inner @('ld') but also the outer @('ld').
 See @(see ld), and for details of the new default value for
 @(':ld-error-action'), @(':RETURN!'), see @(see ld-error-action).  Also see
 the paragraph below about a new utility, @(':')@(tsee p!).  Thanks to Robert
 Krug and Sandip Ray for helpful discussions.</p>

 <p>Environment variable @('ACL2-CUSTOMIZATION') has been replaced by
 @('ACL2_CUSTOMIZATION') &mdash; that is, the hyphen has been replaced by an
 underscore &mdash; so that it can be set conveniently in the @('bash') shell.
 See @(see acl2-customization).</p>

 <p>The ``@('Warnings:')'' summary is now omitted when there are no warnings,
 where formerly ``@('Warnings: None')'' was printed.  Thanks to Jared Davis for
 suggesting this change.</p>

 <p>We have modified the generation of @('constraint')s for @(tsee encapsulate)
 @(see events) in two primary ways, neither of them likely to affect many
 users.  One change is that the virtual movement of definitions and theorems to
 in front of an @(tsee encapsulate) event, or of definitions to behind that
 event, is no longer inhibited in the case of nested encapsulates with
 non-empty @(see signature)s.  The following example illustrates the other
 change, as discussed below.</p>

 @({
  (encapsulate
   ((f (x) t))
   (local (defun f (x) x))
   (defun g (x) (cons x (f x)))
   (defun h (x) (g x))
   (defthm h-is-f (equal (car (h x)) x)))
 })

 <p>Previously, the @(see constraint) on @('f') and @('h') was essentially the
 conjunction of the definition of @('h') and the theorem @('h-is-f').  Now, the
 definition of @('g') is conjoined as well; moreover, @('g') receives the same
 @(see constraint) as do @('f') and @('h'), where previously @('g') was only
 constrained by its definition.  While we are not aware of a soundness bug
 caused by the previous approach, the new approach follows more precisely the
 intended notion of @(see constraint).</p>

 <p>The use of @(tsee trace$) (or @(tsee trace!)) option @(':multiplicity') had
 been required when option @(':native') was supplied.  This is no longer the
 case.  Also, a bug has been fixed that had prevented @(':multiplicity') from
 working properly in GCL and Allegro CL.</p>

 <p>Several errors have been eliminated that formerly occurred when the
 constraints for a function symbol were unknown because it was constrained
 using a dependent clause-processor (see @(see
 define-trusted-clause-processor).  Now, it is assumed that the @('supporters')
 argument in a @(tsee define-trusted-clause-processor) event is such that every
 ancestor of any function symbol constrained by the ``promised encapsulate'' of
 that event among, or ancestral in, those @('supporters').  Thanks to Sol
 Swords, Sandip Ray, and Jared Davis for helpful discussions.</p>

 <p>The notion of @(see constraint) for functions introduced by @(tsee defun)
 has been modified slightly.  No longer do we remove from the body of the
 definition calls of so-called ``guard-holders'': @(tsee prog2$), @(tsee
 must-be-equal), @(see ec-call), and @(see mv-list), and uses of @('the-error')
 generated by @(tsee the).  Also, we now expand calls of @('the-error') with
 the same aggressive heuristics applied to a number of other functions
 (technically, adding it to the list
 @('*expandable-boot-strap-non-rec-fns*')).</p>

 <p><b>NEW FEATURES</b></p>

 <p>A new event, @(tsee defattach), allows evaluation of calls of constrained
 (@(tsee encapsulate)d) functions.  In particular, users can now, in principle,
 soundly modify ACL2 source code; please feel free to contact the ACL2
 implementors if you are interested in doing so.  See @(see defattach).</p>

 <p>Eric Smith has noticed that if you exit the @(see break-rewrite) loop using
 @(':')@(tsee a!) during an @(tsee ld) of a file, then all changes to the
 logical @(see world) are discarded that were made during that call of @(tsee
 ld).  A new utility, @(':')@(tsee p!), pops just one level instead, and avoids
 discarding that work.  (This change is related to an item above, ``The default
 behavior of @(tsee ld) has been changed.'')  Thanks to Eric for pointing out
 this issue.</p>

 <p>New function @(tsee mv-list) is the identity function logically, but
 converts multiple values to lists.  The first argument is the number of
 values, so an example form is as follows, where @('foo') returns three values:
 @('(mv-list 3 (foo x y))').  Thanks to Sol Swords for requesting this feature
 and for reporting a soundness bug in one of our preliminary
 implementations.</p>

 <p>A new @(tsee state) global variable, @('host-lisp'), has as its value a
 keyword whose value depends on the underlying Common Lisp implementation.  Use
 @('(@ host-lisp)') to see its value.</p>

 <p>It is now possible to write @(see documentation) for HTML without error
 when there are links to nonexistent documentation topics.  See the comments in
 macro @('acl2::write-html-file') at the end of file
 @('doc/write-acl2-html.lisp').  When there are such errors, they should be
 easier to understand than previously.  Thanks to Alan Dunn for providing the
 initial modifications.</p>

 <p>It is now possible to inhibit specified parts of the Summary printed at the
 conclusion of an event.  See @(see set-inhibited-summary-types).  Also see
 @(see with-output), in particular the discussion of the new @(':summary')
 keyword.  Thanks to Sol Swords for requesting more control over the
 Summary.</p>

 <p>A new @(':')@(tsee hints) keyword, @(':case-split-limitations'), can
 override the default case-split-limitations settings (see @(see
 set-case-split-limitations)) in the simplifier.  Thanks to Ian Johnson for
 requesting this addition and providing an initial implementation.</p>

 <p>It is now possible to defer and avoid some ttag-related output; see @(see
 set-deferred-ttag-notes).  Thanks to Jared Davis for requesting less verbosity
 from ttag-related output.</p>

 <p>A new @(see command), @(':')@(tsee pl2), allows you to restrict the rewrite
 rules printed that apply to a given term.  See @(see pl2).  Thanks to Robert
 Krug for requesting such a capability.</p>

 <p>ACL2 now provides a utility for canonicalizing filenames, so that soft
 links are resolved; see @(see canonical-pathname).  Moreover, ACL2 uses this
 utility in its own sources, which can eliminate some issues.  In particular,
 @(tsee include-book) with argument @(':ttags :all') no longer breaks when
 given a book name differing from the book name that was used at certification
 time; thanks to Sol Swords for reporting that problem.  Also, certain errors
 have been eliminated involving the combination of packages in the
 certification world and trust tags; thanks to Jared Davis for sending an
 example of that problem.</p>

 <p>You can now suppress or enable guard-checking for an individual form; see
 @(see with-guard-checking).  Thanks to Sol Swords for requesting this
 feature.</p>

 <p>The @(tsee walkabout) utility has been documented (thanks to Rob Sumners
 for suggesting this documentation).  This utility can make it easy to explore
 a large @('cons') tree.  New interactive commands @('(pp n)') and @('(pp
 print-level print-length)') have been added to restrict how much of the
 current object is displayed.  See @(see walkabout).</p>

 <p>Rules of class @(':')@(tsee type-prescription) may now be provided a
 @(':backchain-limit-lst') keyword.  The default behavior is unchanged, but now
 @(tsee type-set) is sensitive not only to the new @(':backchain-limit-lst') of
 a @(':')@(tsee type-prescription) rule (if supplied) but to the @(tsee
 default-backchain-limit) of the current logical @(see world).  Setting of
 backchain-limits can now specify either the new (type-set) limit or the old
 limit (for rewriting); see @(see set-default-backchain-limit) and see @(see
 set-backchain-limit).  Moreover, the functions @(tsee default-backchain-limit)
 and @(tsee backchain-limit) now take a second argument of @(':ts') or
 @(':rewrite') to specify which backchain-limit is desired.</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>The so-called ``too-many-ifs'' heuristic has been modified.  Such a
 heuristic has been employed in ACL2 (and previous Boyer-Moore provers) for
 many years, in order to limit the introduction of calls of @(tsee IF) by
 non-recursive functions.  Most users need not be concerned with this change,
 but two proofs in the regression suite (out of thousands) needed trivial
 adjustment, so user proofs could need tweaking.  In one application, this
 modification sped up proofs by 15%; but the change in runtime for the
 regression suite is negligible, so such speedups may vary.  Thanks to Sol
 Swords for providing a test from ACL2 runs at Centaur Technology, which was
 useful in re-tuning this heuristic.</p>

 <p>Guard proof obligations could have size quadratic in the number of clauses
 in a @(tsee case) statement.  This inefficiency has been removed with a change
 that eliminates a hypothesis of the form @('(not (eql term constant))') when
 there is already a stronger hypothesis, equating the same term with a
 different constant.  Thanks to Sol Swords for bringing this problem to our
 attention and suggesting an alternate approach to solving it, which we may
 consider in the future if related efficiency problems persist.</p>

 <p>We adjusted the heuristics for determining induction schemes in the
 presence of @(see ruler-extenders), when handling calls of a function symbol
 that is a ruler-extender, in either of two cases: either the function takes
 only one argument; or the function is @(tsee prog2$) or @(tsee ec-call), and
 the first argument contains no recursive call.  These cases are treated more
 directly as though the ruler-extender call is replaced by the unique (in the
 case of @(tsee prog2$) and @(tsee ec-call), the second) argument.</p>

 <p>A new @(':')@(tsee type-prescription) rule, @('true-listp-append'), has
 been added:</p>

 @({
  (implies (true-listp b)
           (true-listp (append a b)))
 })

 <p>If you are interested in the motivation for adding this rule, see comments
 in @('true-listp-append') in ACL2 source file @('axioms.lisp').</p>

 <p>The use of @(':forward-chaining') lemmas has been improved slightly.  In
 previous versions, a conclusion derived by forward chaining was discarded if
 it was derivable by type-set reasoning, since it was ``already provable.''
 But this heuristic prevented the conclusion from triggering further forward
 chaining.  This has been fixed.  Thanks to Dave Greve for pointing out this
 problem.</p>

 <p>The fundamental utility that turns an @('IF') expression into a set of
 clauses has been optimized to better handle tests of the form @('(equal x
 'constant)') and their negations.  This eliminates an exponential explosion in
 large case analyses.  But it comes at the inconvenience of sometimes reordering
 the clauses produced.  The latter aspect of this change may require you to
 change some Subgoal numbers in proof hints.  We apologize for the
 inconvenience.</p>

 <p>Certification can now run faster (specifically, the compilation phase) for
 books with very large structures generated by @(tsee make-event), when there
 is significant sharing of substructure, because of a custom optimization of
 the Lisp reader.  Thanks to Sol Swords for bringing this efficiency issue to
 our attention.</p>

 <p>Jared Davis reported inefficiency in certain @(tsee make-event) evaluation
 due to a potentially expensive ``bad lisp object'' check on the expansion
 produced by the @('make-event').  This check has been eliminated except in the
 case that the expansion introduces packages (for example, by including a book
 during the expansion phase that introduces packages).  Thanks to Jared for
 providing a helpful example.</p>

 <p>The application of rules of class @(':')@(tsee induction) had the potential
 to loop (as commented in ACL2 source function @('apply-induction-rule')).
 This has been fixed.  Thanks to Daron Vroon and Pete Manolios for sending nice
 examples causing the loop.</p>

 <p>Heuristics have been tweaked so that false goals may be simplified to
 @('nil') that had formerly been left unchanged by simplification, perhaps
 resulting in useless and distracting proofs by induction.  Thanks to Pete
 Manolios for pointing out this issue by sending the following example: @('(thm
 (<= (+ 1 (acl2-count x)) 0))').  (Technical explanation: When every literal in
 a clause simplifies to @('nil'), even though we might not normally delete one
 or more such literals, we will replace the entire clause by the false
 clause.)</p>

 <p>Improved the efficiency of the built-in function, @(tsee take).  Thanks to
 Bob Boyer for suggesting this improvement.</p>

 <p>ACL2 can now use evaluation to relieve hypotheses when applying
 @(':')@(tsee type-prescription) rules.  Thanks to Peter Dillinger and Dave
 Greve for requesting this enhancement, and to Robert Krug for a relevant
 discussion long ago.</p>

 <p>Evaluation has been sped up during theorems for calls of @(tsee mv-let), by
 avoiding repeated evaluation of the expression to which its variables are
 bound.  Thanks to Sol Swords for requesting this improvement and sending an
 illustrative example.</p>

 <p>Modified a heuristic to avoid the opening up non-recursive function calls
 on calls of @(tsee hide) involving @(tsee if)-expressions.  For example, the
 @(tsee thm) form below is now admitted</p>

 @({
  (defun bar (x)
    (cons x x))
  (thm (equal (bar (hide (if a b c)))
       (cons (hide (if a b c)) (hide (if a b c)))))
 })

 <p><b>BUG FIXES</b></p>

 <p>Fixed a soundness bug in destructor elimination, which was preventing some
 cases from being generated.  Thanks to Eric Smith for reporting this bug and
 sending a helpful example.  (Technical detail: the fixes were in ACL2 source
 functions @('apply-instantiated-elim-rule') and
 @('eliminate-destructors-clause1'), and comments in the former contain Eric's
 example.)</p>

 <p>Fixed a bug that supported a proof of @('nil') by exploiting the fact that
 @(see portcullis) @(see command)s were not included in check-sum computations
 in a book's @(see certificate).  For such a proof of @('nil'), see the
 relevant comment in the ACL2 source file @('ld.lisp') under @('(deflabel
 note-4-0 ...)').</p>

 <p>Changed the implementation of @(tsee add-include-book-dir).  The previous
 implementation could allow relative pathnames to be stored in the @(see
 portcullis) @(see command)s of @(see certificate)s of @(see books), which
 perhaps could lead to unsoundness (though we did not try to exploit this to
 prove @('nil')).  Thanks to Jared Davis for reporting a bug in our first new
 implementation.  An additional change to both @(tsee add-include-book-dir) and
 @(tsee delete-include-book-dir) is that these now work in raw-mode (see @(see
 set-raw-mode)).  (Thanks to Dave Greve for suggesting a reduction in the
 warnings we produced related to raw-mode.)  Note that it is no longer
 permitted to make a direct call of the form @('(table acl2-defaults-table
 :include-book-dir-alist ...)'); use @(tsee add-include-book-dir) instead.</p>

 <p>Fixed a soundness bug related to @(tsee xargs) keyword
 @(':non-executable').  New macros, @('defun-nx') and @('defund-nx'), have been
 provided for declaring functions to be non-executable; see @(see defun-nx).
 While we expect this bug to occur only rarely if at all in practice, the
 following example shows how it could be evoked.</p>

 @({
    ;;;;;;;;;;;;;;;;;;;;
    ;;; Book sub.lisp
    ;;;;;;;;;;;;;;;;;;;;
    (in-package \"ACL2\")
    (defun f ()
      (declare (xargs :guard t
                      :non-executable t))
      (mv-let (a b c)
              (mv 3 4)
              (declare (ignore a b))
              c))
    (defun g ()
      (declare (xargs :guard t))
      (prog2$ (mv-let (x y z)
                      (mv 2 3 4)
                      (declare (ignore x y z))
                      nil)
              (f)))
    (defthm g-nil
      (equal (g) nil)
      :hints ((\"Goal\" :in-theory (disable (f))))
      :rule-classes nil)
    ;;;;;;;;;;;;;;;;;;;;
    ;;; Book top.lisp
    ;;;;;;;;;;;;;;;;;;;;
    (in-package \"ACL2\")
    (include-book \"sub\")
    (defthm contradiction
      nil
      :hints ((\"Goal\" :use g-nil))
      :rule-classes nil)
 })

 <p>The modification described above pertaining to @(tsee defun-nx) also
 prevents execution of non-executable functions that have been @(see trace)d.
 The following example illustrates the problem; now, the following @(tsee
 defun) of @('g') is illegal, and the problem disappears if @(tsee defun-nx) is
 used instead.</p>

 @({
  (defun g (x) ; Use defun-nx to avoid an error after Version_3.6.1.
    (declare (xargs :guard t :non-executable t))
    x)
  (g 3) ; causes error, as expected
  (trace$ g)
  (g 3) ; returned 3 before the bug fix; after fix, causes error as expected
 })

 <p>A hard error was possible when attempting to include an uncertified book
 containing @(see events) of the form @('(make-event '(local ...))').  This has
 been fixed.  Thanks to Sol Swords for bringing this issue to our
 attention.</p>

 <p>Fixed a bug in the heuristic improvement described for Version_3.6 (see
 @(see note-3-6)) as ``We simplified induction schemes....''  The bug had
 prevented, in unusual cases such as the following (notice the impossible
 case), a proof by induction.</p>

 @({
  (defun foo (a x)
    (and (consp x)
         (case a
           (0 (foo (car x) (cdr x)))
           (1 (foo (cdr x) (car x)))
           (0 (foo a (cons x x))))))
  (in-theory (disable (:type-prescription foo)))
  (thm (atom (foo a x)))
 })

 <p>Macro @(tsee cw-gstack) did not work with an @(':evisc-tuple') argument.
 This has been fixed by changing @('cw-gstack') so that it now evaluates its
 arguments.  Thanks to Sol Swords for bringing this bug to our attention.</p>

 <p>Fixed a bug in @(':')@(tsee pso) during the printing of failure messages
 for termination proofs.</p>

 <p>Fixed a bug in the handling of @('#.') (see @(see sharp-dot-reader)).
 Thanks to Bob Boyer for bringing this bug to our attention.</p>

 <p>Replaced a hard Lisp error with a clean error, in certain cases that a
 @(':')@(tsee hints) value is erroneously supplied as a non-@('nil') atom.
 Example: @('(thm (equal x x) :hints 3)').</p>

 <p>Fixed a bug in the interaction of function tracing with conversion of a
 function from @(':')@(tsee program) to @(':')@(tsee logic) mode.  The
 following example illustrates what had been wrong.</p>

 @({
  (defun f (x)
    (declare (xargs :mode :program))
    (car x))
  (f 3) ; raw Lisp hard error
  (trace$ f)
  (f 3) ; raw Lisp hard error (still)
  (defun f (x) (car x)) ; upgrade f to :logic mode
  (f 3) ; clean guard violation; f is no longer traced
  (trace$) ; uh oh - f is shown as traced
  (untrace$ f)
  (f 3) ; OUCH: hard Lisp error because old :program mode definition of
        ; the executable counterpart (sometimes called *1*f) was restored!
 })

 <p>Made a fix so that when building ACL2 with `make' option
 @('ACL2_SAFETY=3'), there will no longer be any safety-0 compiled code
 generated.  Thanks to Gary Byers for bringing this bug to our attention.</p>

 <p>Fixed a bug in the handling of @(see override-hints) that generate custom
 keyword hints (see @(see custom-keyword-hints)) involving the variable
 @('stable-under-simplificationp').  Thanks to Ian Johnson for bringing this
 bug to our attention with explanation that included a helpful example,
 included as comment in the ACL2 source code for function
 @('apply-override-hint').</p>

 <p>The @('saved_acl2') script in CLISP could contain unexpected characters
 where simple newlines were expected.  Dave Greve found this in a Cygwin
 environment on Windows.  Thanks to Dave for reporting this bug and
 experimenting with a fix, and thanks to the CLISP folks for providing helpful
 information.</p>

 <p>Fixed a bug that could make @(':')@(tsee oops) cause an error.  Also, the
 @(tsee oops) command can no longer take you back before a @(tsee
 reset-prehistory) event.</p>

 <p>(GCL only) Fixed a bug that could occur when calling @('trace') in raw Lisp
 in GCL.</p>

 <p>Proof summaries have been improved, so that they account for @(see rune)s
 used in rewriting that takes place when generating goals to be proved in a
 forcing round.  Thanks to Jared Davis for sending us an example illustrating
 this issue.</p>

 <p>Fixed a bug that (at least in CCL) could put extra backslashes (`@('\\')')
 in a pathname that ACL2 writes out to the executable script created by a
 build.  Thanks to Gary Byers for explaining that the CCL behavior is legal
 (for our previous use of Common Lisp function @('merge-pathnames')).</p>

 <p>We closed some holes in the handling of trust tags (also known as
 ``ttags''; see @(see defttag)) by @(tsee include-book).  The following example
 illustrates this rather subtle situation.  Consider the following book.</p>

 @({
  (in-package \"ACL2\")
  (make-event
   (er-progn
    (encapsulate
     ()
     (defttag :foo)
     (value-triple \"Imagine something bad here!\"))
    (value '(value-triple :some-value)))
   :check-expansion t)
 })

 <p>Formerly, the following commands succeeded.</p>

 @({
  (certify-book \"test3\" 0 t :ttags :all)
  :u
  (include-book \"test3\" :ttags nil)
 })

 <p>But because of @(tsee make-event) keyword argument @(':check-expansion t'),
 we know that the event @('(defttag :foo)') is evaluated by the above @(tsee
 include-book) form, and hence the @(':ttags') argument of @('include-book'),
 above, should have specified @(':foo').  The problem was that @(tsee defttag)
 forms evaluated during @(tsee make-event) expansion did not contribute to the
 trust tag information stored in the book's @(see certificate).  Note: Because
 of this change, one should avoid using @(tsee make-event) with
 @(':check-expansion t') when the expansion would introduce a @(tsee defttag)
 event during @(tsee include-book) but not @(tsee certify-book) time.  For an
 example illustrating this issue, see @(see make-event-details), specifically
 the new version of the section labeled ``A note on ttags'' at the end of that
 @(see documentation) topic.</p>

 <p>Closed a small loophole that had the potential, in rare circumstances, to
 violate atomicity of under-the-hood updates for ACL2 @(see arrays).</p>

 <p>The following example was formerly allowed, but resulted in a
 guard-verified function (here, @('g')) whose guard proof obligation is not a
 theorem outside the @(tsee encapsulate) event.  We now disallow @(see guard)
 verification for functions introduced non-@(see local)ly inside an @(tsee
 encapsulate) event unless we determine that the proof obligations hold outside
 the @(tsee encapsulate) event as well.</p>

 @({
  (encapsulate
   ((f (x) t))
   (local (defun f (x) (declare (xargs :guard t)) (consp x)))
   ;; ERROR!
   (defun g (x)
     (declare (xargs :guard (f x)))
     (car x)))
 })

 <p>The use of @(':')@(tsee comp) on @(see stobj) functions had potentially
 caused a hard Lisp error; for example, this could occur when @('(defstobj foo
 fld)') was followed by @(':comp foop').  This has been fixed.</p>

 <p>Fixed a bug that could cause a raw Lisp error when the first argument of
 @(tsee with-local-stobj) is not a symbol.</p>

 <p>It had been possible to use the reserved keyword
 :computed-hints-replacement as the name of a custom keyword hint (see @(see
 custom-keyword-hints)).  This has been fixed.  Thanks to Dave Greve, who
 pointed out a confusing hint error message (which has also been fixed) that
 led us to this issue.</p>

 <p>Fixed a bug that could cause a hard Lisp error, instead of a graceful ACL2
 error, if keyword @(':backchain-limit-lst') in a rule class is given a cons
 that is not a true list, such as @('(1 . 1)').</p>

 <p>Eliminated an error that could occur when redefining a function as a macro
 and then compiling, as in the example below.</p>

 @({
  (defun foo (x) x)
  :redef!
  (defmacro foo (x) x)
  :comp t
 })

 <p>Thanks to Eric Smith for sending the above example in his bug report.</p>

 <p>Fixed a bug that could result in an assertion when a @(see
 clause-processor) causes an error.</p>

 <p><b>NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE</b></p>

 <p>See the <a href='http://code.google.com/p/acl2-books/source/list'>log
 entries</a> for a record of books changed or added since the preceding
 release, with log entries.</p>

 <p>We note in particular the new @('system/') directory, which begins to
 specify ACL2 system code in anticipation of opening the architecture of ACL2
 (see @(see defattach) for a relevant tool).  Some system functions were
 changed slightly (but with the expectation of not generally affecting ACL2
 behavior) in support of the development of this directory.  Those interested
 in contributing to further such efforts are invited to contact the ACL2
 implementors.</p>

 <p>New utilities have been provided for certifying most of the distributed
 books with more `make'-level parallelism.  For example, we have obtained close
 to a 12x reduction in time by using `@('make -j 24 regression-fast')' on a
 24-processor machine.  For more information see @('books/make-targets'), or to
 include the @('books/workshops') in the regression run, see
 @('books/regression-targets').  Thanks to Sol Swords for providing these nice
 utilities.</p>

 <p>The top-level makefile, @('GNUmakefile'), has been fixed so that the build
 processes (which are inherently sequential) will ignore the @('-j') option of
 `make'.  Note that regressions can still, however, be done in parallel, as the
 @('-j') option will be passed automatically to the appropriate `make'
 command.</p>

 <p><b>EMACS SUPPORT</b></p>

 <p><b>EXPERIMENTAL VERSIONS</b></p>

 <p>The HONS version, supported primarily by Bob Boyer and Warren Hunt (see
 @(see hons-and-memoization)), has undergone numerous improvements.  For
 example, keyword argument @(':FORGET') is now supported when calling @(tsee
 memoize) from within the ACL2 loop, and system function @('worse-than') is
 @(see memoize)d with the @(':condition') that both terms are function
 applications (clearing the memo-table after each prover invocation).  Thanks
 to Jared Davis and Sol Swords for investigating the memoization of
 @('worse-than'), and with suitable @('condition').  Thanks also to Jared Davis
 for contributing structural modifications to the implementation of @(tsee
 hons).</p>

 <p>David Rager contributed modifications to the parallel version (see @(see
 parallelism)), which include taking advantage of atomic increments available
 at least since Version 1.0.21 of SBCL and Version 1.3 of CCL.</p>")

(defxdoc |NOTE-4-0(R)|
  :parents (release-notes)
  :short "ACL2 Version  4.0(r) (July, 2010) Notes"
  :long "<p>Please see @(see note-4-0) for changes in Version 4.0 of ACL2.</p>")

(defxdoc note-4-0-wormhole-changes
  :parents (note-4-0)
  :short "How to convert calls of wormhole for Version  4.0"
  :long "<p>Here we describe how to convert an ``old-style'' call of @(tsee
 wormhole) &mdash; that is, a call suitable for ACL2 versions preceding 4.0
 &mdash; in which the @('pseudo-flag') was @('t').  In order to convert such a
 call</p>

 @({
  (wormhole t 'name input form ...)
 })

 <p>to a new-style call, the following steps must be carried out.  Note that
 the wormhole name must always be quoted now.</p>

 <p>First, eliminate the first argument, @('t'), and add a new second argument
 that is the quoted lambda expression</p>

 @({
  '(lambda (whs) (set-wormhole-entry-code whs :ENTER))
 })

 <p>Setting the entry code to @(':ENTER') is not necessary if you maintain the
 invariant (after initialization) that it is always @(':ENTER').  In that case,
 the simpler quoted lambda will suffice:</p>

 @({
  '(lambda (whs) whs)
 })

 <p>Second, change the @('form') argument so that instead of talking about the
 state-global variable @('wormhole-output') it talks about the state-global
 variable @('wormhole-status').  Look for @('(@ wormhole-output)'), @('(assign
 wormhole-output ...)'), @('(f-get-global 'wormhole-output ...)') and
 @('(f-put-global 'wormhole-output ...)') in @('form') and replace them with
 expressions involving @('wormhole-status').</p>

 <p>However, remember that the old data stored in @('wormhole-output') is now
 in the @('wormhole-data') component of the @('wormhole-status').  Thus, for
 example, an old use of @('(@ wormhole-output)') will typically be replaced by
 @('(wormhole-data (@ wormhole-status))') and an old use of @('(assign
 wormhole-output ...)') will typically be replaced by</p>

 @({
  (assign wormhole-status (set-wormhole-data (@ wormhole-status) ...))
 })

 <p>In summary, an old-style call like</p>

 @({
  (wormhole t 'name
            input
            '(...1 (@ wormhole-output) ...2
              ...3 (assign wormhole-output ...4) ...5)
            ...6)
 })

 <p>can become</p>

 @({
  (wormhole 'name
            '(lambda (whs) (set-wormhole-entry-code whs :ENTER))
            input
            '(...1 (wormhole-data (@ wormhole-status)) ...2
              ...3 (assign wormhole-status
                          (set-wormhole-data (@ wormhole-status)
                                             ...4) ...5)
            ...6)
 })

 <p>In any case, and especially if your @('wormhole') call had a
 @('pseudo-flag') other than @('t'), we recommend that you see @(see
 wormhole).</p>")

(defxdoc note-4-1

; Eliminated state global 'translate-error-depth (unused, as noticed by David
; Rager).

; Fixed the definition of gv to pass the appropriate stobjs-in to
; throw-raw-ev-fncall.  Before this fix, the following caused a guard violation
; for remove-stobjs-in-by-position.  (After this fix, a different error
; occurred because of safe-mode, but that is irrelevant to this discussion.)
;   (assign safe-mode 3)
;   (car 3)
;   (print-gv)

; Made trivial syntactic simplification in #-acl2-loop-only definition of
; with-prover-time-limit.

  :parents (release-notes)
  :short "ACL2 Version  4.1 (September, 2010) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 4.1 into the following
 categories of changes: existing features, new features, heuristic
 improvements, bug fixes, distributed books, Emacs support, and experimental
 versions.  Each change is described in just one category, though of course
 many changes could be placed in more than one category.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>The @(see guard) associated with calls of the macro, @(tsee search), has
 been weakened so that now, given strings are no longer restricted to contain
 only standard characters unless the @(':test') argument is @(tsee
 char-equal).</p>

 <p>Modified the writing of ``hidden @(tsee defpkg)'' forms into @(see
 certificate) files (see @(see hidden-defpkg)), to support moving certificate
 files for distributed books, as is done by ACL2s (see @(see acl2-sedan)) and
 Debian releases of ACL2.  Thanks to Camm Maguire for reporting a problem with
 Debian releases of ACL2 that led to this change.</p>

 <p>Expanded the constant @('*acl2-exports*') by adding @('intersection-equal')
 to the list.  Thanks to Jared Davis for requesting this change.</p>

 <p>The @(':')@(tsee comp) utility now compiles functions that have code
 conditionalized for raw Lisp only (presumably because a trust tag was active
 when they were defined).  Previously, this was not the case when @(':comp')
 was applied to more than a single function symbol.</p>

 <p><b>NEW FEATURES</b></p>

 <p>A new macro, @(tsee top-level), allows evaluation directly in the top level
 loop for forms that normally need to be evaluated inside function bodies, such
 as @(tsee with-local-stobj).  See @(see top-level).  Thanks to Jared Davis for
 requesting such a utility.</p>

 <p>Added @(tsee count), a Common Lisp function, to ACL2.  In support of that
 addition, also added rewrite rule @('eqlablep-nth').</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>[None this time.]</p>

 <p><b>BUG FIXES</b></p>

 <p>We fixed a soundness bug that could occur when a function that returns
 multiple values that is called in its own guard.  Thanks to Sol Swords for
 reporting this bug and sending a small self-contained example, which is
 included in a comment in the function @('chk-acceptable-defuns1') in ACL2
 source file @('defuns.lisp').</p>

 <p>It was possible to cause an error when giving theory hints during
 redefinition of functions.  This has been fixed.  Thanks to Ian Johnson for
 sending an example that nicely illustrated this problem.</p>

 <p>Fixed system function @('io?') for the case that formal parameter
 @('commentp') is @('t') and @('vars') is non-empty.  Thanks to David Rager for
 bringing to our attention the fact that @('io?') was broken for such a
 combination of parameters.</p>

 <p>Not exactly a bug fix, but: @(tsee defun-sk) was breaking when a
 @(':')@(tsee guard) is specified, so we have improved the documentation (see
 @(see defun-sk)) to explain how to provide verified guards for a function
 introduced by @(tsee defun-sk).  Thanks to Jared Davis for bringing this issue
 to our attention.</p>

 <p>Made a fix to the handling of interrupts, which in rare cases might have
 left one in a state where all subsequent proof attempts were labeled as
 ``Aborting due to an interrupt''.</p>

 <p>Fixed @(':')@(tsee pso) and related utilities, so that when proof output is
 redirected to a file, all summary output goes to that file rather than to the
 terminal.</p>

 <p>(GCL on Windows only) Removed an inappropriate check, resulting in an error
 about ``pathname-device,'' that could prevent Windows GCL builds of ACL2.
 Thanks to Camm Maguire for reporting this problem and a helpful
 discussion.</p>

 <p>(Windows only) Modified the computation of canonical pathnames to avoid
 issues of case-insensitivity, in particular for the drive (e.g., @('\"C:\"')
 vs. @('\"c:\"')).  Thanks to Harsh Raju Chamarthi for reporting this issue and
 helping with its debugging.</p>

 <p>(Windows only) The value of @('(@ distributed-books-dir)') no longer will
 be missing the Windows drive prefix, for example, @('\"C:\"').  Thanks to
 Harsh Raju Chamarthi for reporting this issue and helping with its
 debugging.</p>

 <p><b>NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE</b></p>

 <p>See the <a href='http://code.google.com/p/acl2-books/source/list'>log
 entries</a> for a record of books changed or added since the preceding
 release, with log entries.</p>

 <p>Modified @('books/Makefile-generic') by adding a new @('BOOKS_SKIP_COMP')
 variable, which is used in @('Makefile')s in some subdirectories of
 @('books/'), in order to avoid errors when compiling certified books for
 multiple Lisps.</p>

 <p><b>EMACS SUPPORT</b></p>

 <p>Distributed file @('emacs/emacs-acl2.el') has been modified so that the
 forms @('control-t e') and @('control-t control-e') now pick up package
 markers (see @(see sharp-bang-reader)), in the following sense: if the
 top-level form is preceded by a line starting with @('#!'), then that line is
 included in the inserted string.  Thanks to Jared Davis for suggesting this
 enhancement and providing a preliminary implementation.</p>

 <p><b>EXPERIMENTAL VERSIONS</b></p>

 <p>For the @('HONS') version there have been some changes to @(tsee
 memoize):</p>

 <blockquote><p>@(tsee Memoize) accepts a new keyword, @(':recursive'), that is
 a synonym for the existing keyword @(':inline').  Thanks to Sol Swords for
 requesting this addition.  Moreover, it is now enforced that these keywords
 have Boolean values.</p>

 <p>@(tsee Memoize) may now be called on @(':')@(tsee program) mode functions.
 Thanks to Sol Swords for requesting this enhancement.</p>

 <p>A bug has been fixed.  Now, if @(tsee memoize) is called with a
 @(':condition-fn') (with value other than @('nil') or @('t')), then the @(see
 guard) of the memoized function and the @(':condition-fn') must be the same.
 Previously, one could exploit the lack of such a check to get a hard Lisp
 error, for example as follows.</p>

 @({
       (defun f (x) (declare (xargs :guard t)) x)
       (defun cf (x) (declare (xargs :guard (consp x))) (car x))
       (memoize 'f :condition-fn 'cf)
       (f 3)
 })

 <p>Memoization is now illegal for built-in functions that use underlying raw
 Lisp in their implementations.  To see why, consider the form @('(gc$)'),
 which is a macro call expanding to @('(gc$-fn nil)').  Previously, after
 evaluation of @('(memoize 'gc$-fn)'), a call of @('gc$') would no longer call
 the garbage collector, which had been invoked by raw Lisp code.  Now,
 evaluation of @('(memoize 'gc$-fn)') causes an error.</p></blockquote>")

(defxdoc |NOTE-4-1(R)|
  :parents (release-notes)
  :short "ACL2 Version  4.1(r) (September, 2010) Notes"
  :long "<p>Please see @(see note-4-1) for changes in Version 4.1 of ACL2.</p>")

(defxdoc note-4-2

; Fixed a bug in ld-fn0 that was passing NIL as the second argument of a
; pprogn, and in that same area of code inserted a progn to obey the intended
; syntax of mv-let.  It's not clear that any of this actually caused problems,
; however.

; Modified (in function tilde-*-book-check-sums-phrase1) the printing of
; include-book errors due to mismatch of sub-book's certificate with parent
; books' certificate, so that a full-book-name is used instead of a
; familiar-name.

; Added brief documentation for quote, following email from Sandip Ray.

; Eliminated inclp argument of functions in the translate11 nest.

; Made minor changes in include-book-fn1 that could conceivably affect handling
; of uncertified books with stale certificates.  But since this may be rare,
; and it doesn't seem important to invest time to come up with an example
; illustrating such a change in behavior, we merely leave this comment rather
; than adding to the :doc string below.

; Modified the implementation of print-indented-list by having it call new
; function print-indented-list-msg, which in turn is used directly in the new
; "error message for free variables" described in this :doc topic (in
; tilde-@-free-vars-phrase, called by chk-free-vars).

; Fixed bugs in :doc set-backchain-limit.

; A potential soundness hole was plugged in the proof-builder by making
; variable pc-assign untouchable.  But we don't mention this in the release
; notes proper because we have not been able to exploit this potential hole.

; Changed fmt-abbrev1 to print the message about :DOC set-iprint in column 0
; after a newline, because otherwise the new message printed immediately after
; evaluating (retrieve ...) looks odd.

; Introduced new function our-truename, which we use in place of truename.
; This was done in support of the item below mentioning "truename", about
; "certain errors in including books".

; Fixed documentation and error message for the case that only some functions
; in a mutual-recursion are non-executable.

; Improved error message for forms such as (defattach f g :hints ...), in which
; the first argument is a symbol but there are more than two arguments.  A lot
; of defattach code was changed to support the use of :program mode functions
; and a few other small changes were made in the process, e.g., world global
; 'proved-functional-instances-alist isn't (needlessly) set to its existing
; value.

; Changed the names of the arrays stored in enabled-structures that are created
; by hints during the waterfall.  We did this with David Rager, in order to
; support parallel evaluation for the waterfall.

; Added source file boot-strap-pass-2.lisp, processed only during pass 2 of the
; boot-strap, which is useful for defattach.  Deleted obsolete function
; load-acl2-execution-environment, rather than figure out whether it should
; also load this new file (and perhaps other pass-2 files as well).

; Split GNUmakefile target DOC into HTML, EMACS, and TEX targets (where EMACS
; replaces the old TEXINFO target).  Users should not generally need to build
; the :doc themselves, but with this split we make that possible even if they
; are missing the texi2dvi and dvips programs needed for building a .ps file
; (as provided by the TEX target).

; Function elide-locals-rec had an odd case for time$1, which we have replaced
; there by time$ along with a comment that this case seems irrelevant anyhow.

; Improved note-fns-in-form to do a more thorough check, for example diving
; into skip-proofs forms (e.g., open-output-channel had been missing from
; *primitive-logic-fns-with-raw-code*, but we hadn't caught that).

; Here is the example promised in the item below labeled: "Fixed a bug in which
; the wrong attachment could be made....".  A more subtle example is described
; in function install-for-add-trip-hcomp-build.
;
; ;;;;; file sub.lisp ;;;;;
; (in-package "ACL2")
; (defun sub-fn (x) x)
; ;;;;;;;;;;;;;;;;;;;;;;;;;
;
; ;;;;; file foo.lisp (note command for certification world) ;;;;;
; ; Portcullis command:
; ; (progn (defstub f (x) t) (defattach f identity))

; (in-package "ACL2")
; (include-book "sub")
; (defun g (x)
;   (declare (xargs :guard t))
;   (cons x x))
; (defattach f g)
; ;;;;;;;;;;;;;;;;;;;;;;;;;
;
; First certify both books, first submitting the above portcullis command in
; the case of foo.lisp; then delete the compiled file for sub.lisp; then start
; ACL2 and evaluate (include-book "foo"); and finally, evaluate the form (f 3).
; The result was 3 where it should have been (3 . 3).

; Functions print-call-history and maybe-print-call-history are now in :logic
; mode, guard-verified.

  :parents (release-notes)
  :short "ACL2 Version  4.2 (January, 2011) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 4.2 into the following
 categories of changes: existing features, new features, heuristic
 improvements, bug fixes, distributed books, Emacs support, and experimental
 versions.  Each change is described in just one category, though of course
 many changes could be placed in more than one category.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>The @(tsee accumulated-persistence) utility can now do finer-grained
 tracking, providing data for individual hypotheses and the conclusion of a
 rule.  See @(see accumulated-persistence).  To try this out, evaluate the form
 @('(accumulated-persistence :all)'); then see @(see accumulated-persistence)
 for a discussion of display options using @('show-accumulated-persistence').
 Thanks to Dave Greve for suggesting this new capability and collaborating on
 its design and implementation.</p>

 <p>The @(tsee defattach) utility now permits the use of @(':')@(tsee program)
 mode functions, though this requires the use of a trust tag (see @(see
 defttag)).  See @(see defattach) and for discussion of the new capability, see
 @(see defproxy), which explains how part of this change involves allowing
 @(':')@(tsee program) mode functions to be declared @(see non-executable).</p>

 <p>Redefinition (see @(see ld-redefinition-action)) is no longer permitted for
 functions that have attachments (see @(see defattach)).  In such cases, the
 attachment must be removed first, e.g. with @('(defattach foo nil)').</p>

 <p>Made small changes to @(tsee mv-nth) and @(tsee defun-sk) in order to
 permit guard verification of functions introduced with more than one
 quantified variable in a @(tsee defun-sk) form.  The change to @(tsee mv-nth)
 is to weaken the @(see guard) by eliminating the requirement that the second
 argument satisfy @(tsee true-listp), and replacing the call of @(tsee endp) in
 the definition body by a corresponding call of @(tsee atom).  The new
 definition of @(tsee mv-nth) is thus logically equivalent to the old
 definition, but with a weaker guard.  Thanks to Sol Swords for sending the
 following example, for which the final @(tsee verify-guards) form had failed
 but now succeeds.</p>

 @({
  (defstub foo (a b c) nil)
  (defun-sk forall-a-b-foo (c)
     (forall (a b) (foo a b c))
     :witness-dcls ((declare (Xargs :guard t
                                    :verify-guards nil))))
  (verify-guards forall-a-b-foo)
 })

 <p>The implementations of @(tsee prog2$), @(tsee time$), @(tsee
 with-prover-time-limit), @(tsee with-guard-checking), @(tsee mbe) (and @(tsee
 must-be-equal)), and @(tsee ec-call) have changed.  See the discussion below
 of the new utility, @(tsee return-last).  A consequence is that @(tsee trace$)
 is explicitly disallowed for these and related symbols, which formerly could
 cause hard Lisp errors, because they are now macros.  Tracing of return-last
 is also disallowed.  Another consequence is that time$ now prints a more
 abbreviated message by default, but a version of the old behavior can be
 obtained with @(':mintime nil').</p>

 <p>The following utilities no longer print an observation about raw-mode
 transitions: @('set-raw-mode-on'), @(tsee set-raw-mode-on!), @(tsee
 set-raw-mode), and @('set-raw-mode-off').  Thanks to Jared Davis for
 suggestion this change in the case of @(tsee include-book) (which proved
 awkward to restrict to that case).</p>

 <p>The system function @('translate-and-test') now permits its @('LAMBDA')
 form to refer to the variable @('WORLD'), which is bound to the current ACL2
 logical @(see world).</p>

 <p>Modified abort handling to avoid talking about an interrupt when the error
 was caused by a Lisp error rather than an interrupt.</p>

 <p>The value of the constant @('*acl2-exports*'), which is still a list, has
 been extended significantly, though only with the addition of symbols that one
 might reasonably have expected all along to belong to this list.  A new
 distributed book, @('books/misc/check-acl2-exports.lisp'), checks (at
 certification time) that no documented constant, macro, or function symbol in
 the @('\"ACL2\"') package has been accidentally omitted from
 @('*acl2-exports*').  Thanks to Dave Greve for helpful discussions related to
 this change.</p>

 <p>Improved the built-in `@('untranslate')' functions to produce @('let*')
 expressions when appropriate (more to help with tools that call
 @('untranslate') and the like, than to help with proof output).</p>

 <p>The utility @(tsee redo-flat) now works for @(tsee certify-book) failures,
 just as it continues to work for failures of @(tsee encapsulate) and @(tsee
 progn).</p>

 <p>The following only affects users who use trust tags to add to list values
 of either of the @(tsee state) global variables @('program-fns-with-raw-code')
 or @('logic-fns-with-raw-code').  For functions that belong to either of the
 above two lists, @('trace$') will supply a default value of @(':fncall') to
 keyword @(':notinline'), to avoid discarding raw-Lisp code for the
 function.</p>

 <p>The @(see guard) of the macro @(tsee intern) has been strengthened so that
 its second argument may no longer be either the symbol
 @('*main-lisp-package-name*') or the string @('\"COMMON-LISP\"').  That change
 supports another change, namely that the following symbols in the
 @('\"COMMON-LISP\"') package are no longer allowed into ACL2: symbols in that
 package that are not members of the list constant
 @('*common-lisp-symbols-from-main-lisp-package*') yet are imported into the
 @('\"COMMON-LISP\"') package from another package.  See @(see pkg-imports) and
 see @(see symbol-package-name).  To see why we made that change, consider for
 example the following theorem, which ACL2 was able to prove when the host Lisp
 is GCL.</p>

 @({
  (let ((x \"ALLOCATE\") (y 'car))
    (implies (and (stringp x)
                  (symbolp y)
                  (equal (symbol-package-name y)
                         \"COMMON-LISP\"))
             (equal (symbol-package-name (intern-in-package-of-symbol x y))
                    \"SYSTEM\")))
 })

 <p>Now suppose that one includes a book with this theorem (with @(':')@(tsee
 rule-classes) @('nil')), using an ACL2 built on top of a different host Lisp,
 say CCL, that does not import the symbol @('SYSTEM::ALLOCATE') into the
 @('\"COMMON-LISP\"') package.  Then then one can prove @('nil') by giving this
 theorem as a @(':use') hint.</p>

 <p>The axioms introduced by @(tsee defpkg) have changed.  See the discussion
 of @(tsee pkg-imports) under ``NEW FEATURES'' below.</p>

 <p>The error message for free variables (e.g., in definition bodies and
 guards) now supplies additional information when there are governing IF
 conditions.  Thanks to Jared Davis for requesting this enhancement and
 collaborating in its design.</p>

 <p>The command @(':')@(tsee redef-) now turns off redefinition.</p>

 <p>Improved proof output in the case of a @(':')@(tsee clause-processor) hint
 that proves the goal, so that the clause-processor function name is
 printed.</p>

 <p>The @(tsee proof-builder) command `@('then')' now stops at the first
 failure (if any).</p>

 <p>It is no longer permitted to submit definitions in @(':logic') mode for
 merely part of an existing @(tsee mutual-recursion) event.  Such an action
 left the user in an odd state and seemed a potential soundness hole.</p>

 <p>The function @(tsee break$) is now in @(':')@(tsee logic) mode.  Thanks to
 Jared Davis for requesting this enhancement.</p>

 <p>The macro @(tsee verify-termination) now provides clearer output in the
 case that it is redundant.  More important perhaps, as a courtesy it now
 causes an error when applied to a constrained function, since presumably such
 an application was unintended (as the constrained function could never have
 been in @(':')@(tsee program) mode).  Note that if one desires different
 behavior, one can create one's own version of @(tsee verify-termination) (but
 with a different name).</p>

 <p>Improved the @(see guard)s for the following functions, often weakening
 them, to reflect more precisely the requirements for calling @(tsee eq):
 @('alist-difference-eq'), @('intersection-eq'), @('intersection1-eq'), @(tsee
 intersectp-eq), @('not-in-domain-eq'), @('set-difference-assoc-eq'),
 @('set-equalp-eq'), and @(tsee union-eq).  Thanks to Jared Davis for pointing
 out this issue for @(tsee intersectp-eq).</p>

 <p>(CCL only) Made a change that can reduce the size of a compiled file
 produced by @(tsee certify-book) when the host Lisp is CCL, by discarding
 source information (for example, discarding @(tsee local) events).</p>

 <p><b>NEW FEATURES</b></p>

 <p>See the discussion above about new statistics that can be gathered by the
 @(tsee accumulated-persistence) utility.</p>

 <p>A new hint, @(':')@(tsee instructions), allows use of the @(see
 proof-builder) at the level of @(see hints) to the prover.  Thanks to Pete
 Manolios for requesting this feature (in 2001!).  See @(see instructions).</p>

 <p>(For system hackers) There are new versions of system functions
 @('translate1') and @('translate'), namely @('translate1-cmp') and
 @('translate-cmp') respectively, that do not take or return @(tsee state).
 See the Essay on Context-message Pairs for relevant information.  Thanks to
 David Rager for collaborating on this enhancement.</p>

 <p>A new utility, @(tsee return-last), is now the unique ACL2 function that
 can pass back a multiple value result from one of its arguments.  Thus, now
 the following are macros whose calls ultimately expand to calls of @(tsee
 return-last): @(tsee prog2$), @(tsee time$), @(tsee with-prover-time-limit),
 @(tsee with-guard-checking), @(tsee mbe) (and @(tsee must-be-equal)), and
 @(tsee ec-call).  With an active trust tag, an advanced user can now write
 code that has side effects in raw Lisp; see @(see return-last).  Thanks to
 Jared Davis for requesting this feature.</p>

 <p>A new function, @(tsee pkg-imports), specifies the list of symbols imported
 into a given package.  The axioms for @(tsee defpkg) have been strengthened,
 taking advantage of this function.  Now one can prove theorems using ACL2 that
 we believe could not previously be proved using ACL2, for example the
 following.</p>

 @({
  (equal (symbol-package-name (intern-in-package-of-symbol str t))
         (symbol-package-name (intern-in-package-of-symbol str nil)))
 })

 <p>Thanks to Sol Swords for a helpful report, which included the example
 above.  See @(see pkg-imports) and see @(see defpkg).</p>

 <p>Added function @(tsee no-duplicatesp-eq).</p>

 <p>Added a new hint keyword, @(':')@(tsee backchain-limit-rw), to control the
 level of backchaining for @(see rewrite), @(see meta), and @(see linear)
 rules.  This overrides, for the current goal and (as with @(':')@(tsee
 in-theory) hints) descendant goals, the default @(see backchain-limit) (see
 @(see set-backchain-limit)).  Thanks to Jared Davis for requesting this
 feature.</p>

 <p>Support is now provided for creating and certifying books that do not
 depend on trust tags, in the case that the only use of trust tags is during
 @(tsee make-event) expansion.  See @(see set-write-acl2x).  Thanks to Sol
 Swords for reporting a couple of bugs in a preliminary implementation.</p>

 <p>Function @('(file-write-date$ filename state)') has been added, giving the
 write date of the given file.</p>

 <p>See @(see forward-chaining-reports) for how to get new reports on the
 forward chaining activity occurring in your proof attempts.  Thanks to Dave
 Greve for inspiring the addition of this utility.</p>

 <p>It is now possible to use ACL2's printing utilities to return strings, by
 opening output channels to the keyword @(':STRING') rather than to filenames.
 See @(see io).  Thanks to Jared Davis for a helpful conversation that led us
 to add this feature.</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>We have slightly improved the handling of @(':')@(see forward-chaining)
 rules that contain free variables.  Formerly, such rules might fire only once,
 when the first match for a free variable is discovered, and would not fire
 again even if subsequent forward chaining made available another match.  This
 made it difficult to predict whether a rule with free variables would fire or
 not, depending as it did on the order in which newly derived conclusions were
 added.  The new handling is a little slower but more predictable.  Thanks to
 Dave Greve for sending a helpful example that led us to consider making such
 an improvement.</p>

 <p>We have slightly improved the so-called ``@(see type-set)'' heuristics to
 work a bit harder on terms of the form @('(rec term)'), where @('rec') is a
 so-called ``compound-recognizer'' function, that is, a function with a
 corresponding enabled @(':')@(tsee compound-recognizer) rule.  Thanks to Jared
 Davis for sending a helpful example (found, in essence, in the modified
 function @('type-set-rec'), source file @('type-set-b.lisp')).</p>

 <p>We made three heuristic improvements in the way contexts (so-called
 ``type-alists'') are computed from goals (``clauses'').  Although these
 changes did not noticeably affect timing results for the ACL2 regression
 suite, they can be very helpful for goals with many hypotheses.  Thanks to
 Dave Greve for sending a useful example (one where we found a goal with 233
 hypotheses!).</p>

 <p>The algorithm for substituting alists into terms was modified.  This change
 is unlikely to affect many users, but in one example it resulted in a speed-up
 of about 21%.  Thanks to Dave Greve for supplying that example.</p>

 <p>Sped up @(tsee include-book) a bit by memoizing checksums of symbols.
 (This change pertains to ``normal'' ACL2 only, not the @(tsee hons) version
 (see @(see hons-and-memoization), where such memoization already occurred.)
 We found about a 23% speed-up on an example from Dave Greve.</p>

 <p>Made a small change to the algorithm used to prove hypotheses of
 @(':')@(tsee type-prescription) rules (ACL2 source function
 @('type-set-relieve-hyps')).  One change avoids a linear walk through the
 context (the ``type-alist'' structure), while the other could avoid storing
 unnecessary @(tsee force)d assumptions (into the so-called ``tag-tree'').</p>

 <p><b>BUG FIXES</b></p>

 <p>Fixed a long-standing soundness bug caused by the interaction of @(tsee
 force)d hypotheses with destructor @(see elim)ination.  The fix was to avoid
 using forcing when building the context (so-called ``type-alist'') when the
 goal is considered for destructor elimination; those who are interested can
 see a discussion in source function @('eliminate-destructors-clause1'), which
 includes a proof of @('nil') that no longer succeeds.  A similar fix was made
 for generalization, though we have not exploited the previous code to prove
 @('nil') in that case.</p>

 <p>Fixed a bug that allowed book certification to ignore @('skip-proofs')
 around @(tsee encapsulate) @(see events).  Thus, a book could contain an event
 of the form @('(skip-proofs (encapsulate ...))'), and a call of @(tsee
 certify-book) on that book could succeed even without supplying keyword
 @(':skip-proofs-okp t').  This bug was introduced in Version 3.5 (May,
 2009).</p>

 <p>Fixed a bug that could occur when including a book that attempts to
 redefine a function as a macro, or vice-versa.  (For details of the issue, see
 the comment in the definition of variable @('*hcomp-fn-macro-restore-ht*') in
 source file @('other-events.lisp').)</p>

 <p>(Windows only) Fixed handling of the Windows drive so that an executable
 image saved on one machine can be used on another, even with a different
 drive.  Thanks to Harsh Raju Chamarthi for reporting this issue and doing a
 lot of testing and collaboration to help us get this right.</p>

 <p>Made a change to avoid possible low-level errors, such as bus errors, when
 quitting ACL2 by calling @(tsee good-bye) or its synonyms.  This was occurring
 in CCL, and we are grateful to Gary Byers for helping us find the source of
 those errors (which basically was that ACL2 was attempting to quit while
 already in the process of quitting).</p>

 <p>Fixed a bug in @(tsee with-guard-checking), which was being ignored in
 function bodies.</p>

 <p>Fixed a bug in @(tsee top-level), which was not reverting the logical @(see
 world) when an error resulted from evaluation of the given form.  Thanks to
 Jared Davis for bringing this bug to our attention.</p>

 <p>Fixed a long-standing bug (back through Version 2.7) that was discarding
 changes to the connected book directory (see @(see cbd)) when exiting and then
 re-entering the top-level ACL2 loop (with @(tsee lp)).</p>

 <p>In some host Lisps, it has been possible to be in a situation where it is
 impossible to interrupt checkpoint printing during the summary.  We had
 thought this solved when the host Lisp was CCL, but Sol Swords sent us an
 example (for which we are grateful) illustrating that this behavior could
 occur.  This has been fixed.</p>

 <p>Fixed a bug in a proof obligation generated for @(':')@(tsee meta) and
 @(':')@(tsee clause-processor) rules, that the @(see guard) on the
 metafunction or clause-processor function, @('fn'), holds under suitable
 assumptions.  Those assumptions include not only that the first argument of
 @('fn') satisfies @(tsee pseudo-termp), but also that all @(see stobj) inputs
 satisfy the corresponding stobj recognizer predicates.  We had erroneously
 considered stobj outputs of @('fn') instead of stobj inputs.  Thanks to Sol
 Swords for bringing this bug to our attention with a simple example, and
 correctly pointing us to the bug in our code.</p>

 <p>Fixed the following bugs in @(tsee defattach).  We hadn't always been
 applying the full functional substitution when generating guard proof
 obligations.  We had been able to hit an assertion when reattaching to more
 than one function.  Attachment was permitted in the case of an untouchable
 function (see @(see remove-untouchable)).  Finally, the guard proof obligation
 could fail in the case that the two functions have different formal parameter
 lists, as in the following example.</p>

 @({
  (encapsulate
   ((foo (x) x :guard (symbolp x)))
   (local (defun foo (x) x)))
  (defun bar (x2)
    (declare (xargs :guard (symbolp x2)))
    x2)
  (defattach foo bar)
 })

 <p>Fixed a raw Lisp error that could be caused by including a book using
 @(tsee make-event) to define a function symbol in a locally-introduced
 package.  An example appears in a comment in ACL2 source function
 @('write-expansion-file').</p>

 <p>Made a change that can prevent an error near the end of book certification
 when the underlying Host Lisp is Allegro Common Lisp, in the case that
 environment variable @('ACL2_SYSTEM_BOOKS') has been set to the name of a
 directory with a parent that is a soft link.  Thanks to Dave Greve for
 supplying an example to led us to this fix, which involves avoiding Allegro
 CL's implementation of the Common Lisp function, @('truename').</p>

 <p>Fixed a bug that was failing to substitute fully using bindings of free
 variables in @(tsee force)d hypotheses.  A related change is that instead of
 binding such a free variable to a new variable of the form @('???-Y'), the new
 variable is now of the form @('UNBOUND-FREE-Y').</p>

 <p>Fixed a bug that could inhibit the printing of certain theory warnings (and
 probably, in the other direction, cause inappropriate such printing).</p>

 <p>We eliminated excessive @('\"Raw-mode\"') warnings about @(tsee
 add-include-book-dir) that could be generated by the use of raw-mode during
 @(tsee include-book).  Thanks to Dave Greve for bringing this issue to our
 attention.</p>

 <p>Fixed the printing of results from forms within an @(tsee encapsulate), so
 that they are abbreviated according to the @(tsee ld-evisc-tuple).</p>

 <p>It is now possible to evaluate @(see stobj)-related forms after evaluating
 @(':')@(tsee set-guard-checking) @(':none') or @(':')@(tsee
 set-guard-checking) @('nil'), even in cases where such evaluation formerly
 caused a guard violation due to a bug in ACL2.  Here is an example of an error
 that no longer occurs.</p>

 @({
  ACL2 !>(defstobj st fld)

  Summary
  Form:  ( DEFSTOBJ ST ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   ST
  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 >(fld st)

  ACL2 Error in TOP-LEVEL:  The guard for the function call (FLD ST),
  which is (STP ST), is violated by the arguments in the call (FLD ST).
  [... etc. ...]
 })

 <p>You can understand how things now work by imagining that when a function
 introduced by @(tsee defstobj) is called, @(tsee guard)-checking values of
 @(':none') or @('nil') are temporarily converted to @('t').  Thanks to Pete
 Manolios, Ian Johnson, and Harsh Raju Chamarthi for requesting this
 improvement.</p>

 <p>Fixed a bug in which the wrong attachment could be made when the same
 function has an attachment in a book and another in the certification world of
 that book (possibly even built into ACL2), if the load of a compiled file is
 aborted because a sub-book's compiled file is missing.  The bug has been
 present since the time that @(tsee defattach) was added (Version_4.0).  An
 example may be found in a comment in the @(tsee deflabel) for @('note-4-2')
 (ACL2 source file @('ld.lisp')).</p>

 <p>The @(':')@(tsee doc) and related utilities now cause a clean error when
 provided other than a symbol.  Thanks to Jared Davis for pointing out the raw
 Lisp error that had occurred in such cases.</p>

 <p>It had been the case that in raw-mode (see @(see set-raw-mode)), it was
 possible to confuse @(tsee include-book) when including a book in a directory
 different from the current directory.  This has been fixed.  Thanks to Hanbing
 Liu for bringing this problem to our attention with a small example.</p>

 <p><b>NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE</b></p>

 <p>Many changes have been made to the distributed books, thanks to an active
 ACL2 community.  You can contribute books and obtain updates between ACL2
 releases by visiting the <a href='http://acl2-books.googlecode.com/'>ACL2
 Books</a> web page.</p>

 <p>There is new @('Makefile') support for certifying just some of the
 distributed books.  See @(see books-certification-classic), in particular
 discussion of the variable @('ACL2_BOOK_DIRS').  Thanks to Sandip Ray for
 requesting this enhancement.</p>

 <p>The @(see documentation) for @(tsee make-event) now points to a new book,
 @('books/make-event/defrule.lisp'), that shows how @('make-event') can be used
 to do macroexpansion before generating @(see events).  Thanks to Carl Eastlund
 for useful interaction on the acl2-help mailing list that led us to add this
 example.</p>

 <p><b>EMACS SUPPORT</b></p>

 <p>Incorporated a version of changes from Jared Davis to the @('control-t f')
 emacs utility (distributed file @('emacs/emacs-acl2.el')), so that one can
 fill a format string from anywhere within the string.</p>

 <p><b>EXPERIMENTAL VERSIONS</b></p>

 <p>We refrain from listing changes here to experimental versions, other than
 an enhancement to the @(see HONS) version that can reduce sizes of @(see
 certificate) files, by applying @(tsee hons-copy) to introduce structure
 sharing (ACL2 source function @('make-certificate-file1')).</p>")

(defxdoc |NOTE-4-2(R)|
  :parents (release-notes)
  :short "ACL2 Version  4.2(r) (January, 2011) Notes"
  :long "<p>Please see @(see note-4-2) for changes in Version 4.2 of
 ACL2.</p>")

(defxdoc note-4-3

; The following example illustrates the soundness bug related to mbe that is
; mentioned in :doc note-4-3.  To prove nil:

; (certify-book "sub")
; :u
; (certify-book "mid")
; :u
; (certify-book "top")

; The problem is that the macro mac expands differently in the ACL2 loop from
; how it expands in raw Lisp.  The bug fix is to check equality of the values
; of the :logic and :exec forms when in safe-mode.

;;;;;;;;;;;;;;;
; Book sub.lisp
;;;;;;;;;;;;;;;
;   (in-package "ACL2")
;
;   (defmacro mac ()
;     (mbe :logic ''logic
;          :exec ''exec))
;
;   (defconst *a*
;     (mac))

;;;;;;;;;;;;;;;
; Book mid.lisp
;;;;;;;;;;;;;;;
;   (in-package "ACL2")
;
;   (local (include-book "sub"))
;
;   (defmacro mac ()
;     (mbe :logic ''logic
;          :exec ''exec))
;
;   (defconst *a*
;     (mac))
;
;   (defthm got-exec
;     (equal *a* 'exec)
;     :rule-classes nil)

;;;;;;;;;;;;;;;
; Book top.lisp
;;;;;;;;;;;;;;;
;   (in-package "ACL2")
;
;   (defmacro mac ()
;     (mbe :logic ''logic
;          :exec ''exec))
;
;   (defconst *a*
;     (mac))
;
;   (defthm got-logic
;     (equal *a* 'logic)
;     :rule-classes nil)
;
;   (include-book "mid")
;
;   (defthm contradiction
;     nil
;     :hints (("Goal" :use (got-exec got-logic)))
;     :rule-classes nil)

;;;;;;;;;;;;;;; end of example

; Modified some doc-printing functions in support of translation to xdoc.  the
; process, the HTML output has become prettier; see item about HTML, below.

; Added new macro mv-to-state.

; Changed the name mv-let? to bdd-mv-let to avoid potential confusion with
; mv?-let.

; Functions enable-iprint-ar and disable-iprint-ar now return two values
; instead of three.

; Here is the example promised in :doc note-4-3 to illustrate a bug in the
; loop-checking done on behalf of defattach.  The bug was fixed in function
; update-attachment-records1.

;;;;;;;;;;;;;;; start example
;   (progn
;     (encapsulate
;      ((f1 (x) t)
;       (f2 (x) t))
;      (local (defun f1 (x) x))
;      (local (defun f2 (x) x)))
;
;     (encapsulate
;      ((g1 (x) t)
;       (g2 (x) t))
;      (local (defun g1 (x) x))
;      (local (defun g2 (x) x))
;      (defthm g1-f1
;        (equal (g1 (f1 x))
;               (f1 x))))
;
;     (encapsulate
;      ((h1 (x) t)
;       (h2 (x) t))
;      (local (defun h1 (x) x))
;      (local (defun h2 (x) x))))
;
;   (defattach f2 h1)
;
;   ; The following should cause the following loop to be reported, but didn't:
;       G1 is an extended ancestor of H1.
;       H1 is an extended ancestor of F1.
;       F1 is an extended ancestor of G1.
;   (defattach h2 g2)
;;;;;;;;;;;;;;; end of example

; Replaced a couple of calls of 1+ by 1+f in fn-count-evg-rec, after Robert
; Krug brought these to our attention.

; Improved the error message when discovering during load of compiled or
; expansion file that a defconst is not redundant.

; Fixed macro io? so that we are not left in a wormhole when there is an error
; (as happened previously when the commentp argument of io? was t).

; Regarding "Fixed a bug in detection of package redefinition.": The use of
; member-equal instead of assoc-equal in maybe-introduce-empty-pkg-2 allows (at
; least on quick analysis) every package with empty imports to be considered a
; "virgin" package, which may have allowed (again, on quick analysis) illegal
; package redefinition to occur.

; Made efficiency improvement in check-vars-not-free, which is minor but
; perhaps worth a couple percent since we have added equality-variants.

; We no longer make some duplicate cons-tag-trees calls in defaxiom-fn and
; defthm-fn1.

; Removed needless (and confusing) #+ansi-cl in handler-bind call for sbcl in
; with-warnings-suppressed.

; Modified the handling of package definitions in expansion files (macro
; maybe-introduce-empty-pkg-1).

; We took preliminary steps towards removing uses of the big-clock field of
; state.

; Modified deletion of compiled file of acl2-fns.lisp to occur at the Lisp
; level instead of using GNUmakefile.

; Deleted delete-pair and remove-first-pair, which each duplicated the
; functionality of delete-assoc-eq.

; Eliminated cons-into-ttree in favor of cons-tag-trees.

; Moved assert$ to the right place in cmp-to-error-triple (thanks to David
; Rager for correcting an error in our initial change).

; Below we show how to obtain a hard Lisp error in Version_4.2, when, as
; mentioned in the :doc string below, "including books with hidden packages".
; The problem was that write-expansion-file was deciding whether to push
; maybe-introduce-empty-pkg-1 and maybe-introduce-empty-pkg-2 forms based on
; the known-package-alist just before pass 1 of certify-book, rather than just
; after it.  But a second defpkg form can use symbols defined in the first, so
; since it's pretty cheap just to lay down all such forms, that's what we do.

;   sloth:~/temp> cat sub.lisp
;   ; First execute these two commands in the certification world:
;   ; (defpkg "FOO" '(a))
;   ; (defpkg "BAR" '(foo::b))
;
;   ; Then:
;   ; (certify-book "sub" 2)
;
;   (in-package "ACL2")
;
;   (defun g (x) x)
;   sloth:~/temp> cat top.lisp
;   ; Just do this:
;   ; (certify-book "top")
;
;   (in-package "ACL2")
;
;   (local (include-book "sub"))
;
;   (defun h (x) x)
;   sloth:~/temp>
;
;   ACL2 !>(include-book "top")
;
;   ***********************************************
;   ************ ABORTING from raw Lisp ***********
;   Error:  There is no package named "FOO" .
;   ***********************************************

  :parents (release-notes)
  :short "ACL2 Version  4.3 (July, 2011) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 4.2 into the following
 categories of changes: existing features, new features, heuristic
 improvements, bug fixes, changes at the system level and to distributed books,
 Emacs support, and experimental versions.  Each change is described in just
 one category, though of course many changes could be placed in more than one
 category.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>Significant changes have been made for list-processing primitives such as
 @(tsee member) and @(tsee assoc); see @(see equality-variants).  In summary:
 instead of separate functions based on @(tsee eq), @(tsee eql), and @(tsee
 equal), there is essentially just one function, which is based on @(tsee
 equal); the @(tsee eq) and @(tsee eql) variants are logically just the @(tsee
 equal) variant.  For example, @(tsee member-eq) and @(tsee member) are macros
 that generate corresponding calls of @(tsee member-equal) in the logic,
 although in raw Lisp they will execute using tests @(tsee eq) and @(tsee eql),
 respectively.  References to any of these in logical contexts such as @(see
 theories) are now references to the function based on @(tsee equal); for
 example, the hint @(':in-theory (disable member)') is completely equivalent to
 the hint @(':in-theory (disable member-equal)').  Distributed books have been
 modified as necessary to accommodate this change.  While the need for such
 changes was relatively infrequent, changes were for example needed in contexts
 where terms are manipulated directly; for example, @(tsee defevaluator) needs
 to mention @(tsee member-equal) rather than @(tsee member), just as it was
 already the case to mention, say, @(tsee binary-append) rather than @(tsee
 append).  Again, see @(see equality-variants) for more information about
 equality variants.</p>

 <p>A few improvements were made in support of the modified treatment of
 equality variants discussed above.  The changes include the following.</p>

 <blockquote>

 <p>o We now allow the use of macro aliases (see @(see macro-aliases-table) in
 @(':trigger-fns') of rules (see @(see rule-classes)).</p>

 <p>o We now remove so-called ``guard holders'' (including calls of @(tsee
  return-last), hence of @(tsee mbe)) in @(':trigger-terms') of rules.</p>

 <p>o We also remove guard holders in formulas of @(':')@(tsee congruence) and
 @(tsee type-prescription) rules.</p>

 <p>o Macros @('union-eq') and @('intersection-eq') can now take any positive
 number of arguments, and @(tsee union-eq) can take zero arguments.  (Thanks to
 Jared Davis for requesting this enhancement.)  The same can be said for new
 macros @(tsee union$) and @(tsee intersection$), respectively.</p>

 <p>o A few changes were made to built-in theorems from source file
 @('axioms.lisp'), in particular disabling @(':')@(tsee type-prescription) rule
 @('consp-assoc-equal') (formerly two enabled rules, @('consp-assoc-eq') and
 @('consp-assoc')) but adding this theorem as a @(':forward-chaining') rule,
 and similarly for @('true-list-listp-forward-to-true-listp-assoc-equal') (and
 eliminating rule @('true-list-listp-forward-to-true-listp-assoc-eq'); and
 disabling rule @('true-listp-cadr-assoc-eq-for-open-channels-p').  Also,
 theorem @('all-boundp-preserves-assoc') has been renamed to
 @('all-boundp-preserves-assoc-equal') and also strengthened.</p>

 <p>o Some @(see guard)s were slightly improved (logically weaker or the
 same).</p></blockquote>

 <p>Improved @('get-output-stream-string$') to allow for a context and to do
 genuine error printing instead of using @(tsee cw).  See @(see io).</p>

 <p>Added the symbols @(tsee flet) and @(tsee with-local-stobj) to
 @('*acl2-exports*').</p>

 <p>A small change was made to the processing of more than one @(':')@(tsee
 guard) declaration for the same function.  In particular, a guard of @('t') is
 essentially ignored.</p>

 <p>Attachments are now allowed during evaluation of the first argument of
 @(tsee prog2$) even in contexts (such as proofs) during which the use of
 attachments is normally prohibited.  More generally, the second of the three
 arguments of @(tsee return-last) has this property, except in the case of
 @(tsee mbe) (or related macros like @(tsee mbe1)), where the @('exec')
 argument may provide the value.  Thanks to Sol Swords for useful discussions
 leading us to implement this enhancement.</p>

 <p>The restriction has been removed that prohibited the use of @(tsee mbe)
 inside @(tsee encapsulate) @(see events) with a non-empty @(see signature).
 This restriction was introduced in Version 3.4, but has not been necessary
 since Version 4.0, when we first started disallowing @(see guard) verification
 for functions introduced non-@(see local)ly inside such @(tsee encapsulate)
 events.</p>

 <p>We weakened the checks involving common ancestors for evaluator and @(see
 meta) (and @(see clause-processor)) functions (see @(see
 evaluator-restrictions)) so that except in the @(tsee mbe) case, the
 next-to-last argument of @(tsee return-last) is not considered.  Thanks to Sol
 Swords for bringing this issue to our attention.</p>

 <p>The macro @(tsee append) no longer requires at least two arguments.  Thanks
 to Dave Greve for requesting this enhancement.</p>

 <p>(Mostly for system hackers) Now, @(tsee break-on-error) breaks at a more
 appropriate (earlier) time for certain system functions that do not return
 state, such as @('translate11').  Thanks to David Rager for requesting this
 improvement.</p>

 <p>@(tsee Show-accumulated-persistence) may take a new argument, @(':runes'),
 which simply causes an alphabetical list of @(see rune)s to be printed
 out.</p>

 <p>Improved @(tsee trace$) so that @(':entry'), @(':exit'), and @(':cond')
 forms may reference @('state') even if the function being traced does not
 include @('state') as a formal.</p>

 <p>The system function @('acl2x-expansion-alist') now takes a second argument,
 namely @(tsee state).  This change allows for more flexibility in the sorts of
 attachments that can be made to this function (see @(see defattach)).  Thanks
 to Jared Davis and Sol Swords for requesting this enhancement and providing a
 preliminary implementation.</p>

 <p>An obscure @(see proof-builder) change, unlikely to affect users, replaces
 the state global variables @('erp'), @('val'), @('print-macroexpansion-flg'),
 and @('print-prompt-and-instr-flg') by @('pc-erp'), @('pc-val'),
 @('pc-print-macroexpansion-flg'), and @('pc-print-prompt-and-instr-flg'),
 respectively.</p>

 <p>@(see State) globals @('fmt-hard-right-margin') and
 @('fmt-soft-right-margin') are now untouchable (see @(see
 set-fmt-hard-right-margin) and see @(see push-untouchable)).  If you bind
 these @('state') globals with @(tsee state-global-let*), then you will need to
 do so with appropriate setters to restore their values, for example as
 follows.</p>

 @({
    (state-global-let*
     ((fmt-hard-right-margin 500 set-fmt-hard-right-margin)
      (fmt-soft-right-margin 480 set-fmt-soft-right-margin))
     ...)
 })

 <p>The error message has been improved for the case of evaluating an undefined
 function that has an attachment (see @(see defattach)).  Thanks to Jared Davis
 for sending the following example, which illustrates the additional part of
 the message.</p>

 @({
    ACL2 !>(defstub foo (x) t)
    [[... output omitted ...]]
    ACL2 !>(defattach foo identity)
    [[... output omitted ...]]
    ACL2 !>(defconst *x* (foo 3))

    ACL2 Error in ( DEFCONST *X* ...):  ACL2 cannot ev the call of undefined
    function FOO on argument list:

    (3)

    Note that because of logical considerations, attachments (including
    IDENTITY) must not be called in this context.

    [[... additional output omitted ...]]
 })

 <p>The directory string supplied to @(tsee add-include-book-dir) no longer
 must terminate with the `@('/')' character, as had been required in some Lisp
 implementations.  Thanks to Sol Swords for bringing this issue to our
 attention.</p>

 <p>We no longer print induction schemes with @(see gag-mode); use @(':')@(tsee
 pso) if you want to see them.  Thanks to Dave Greve for this suggestion.</p>

 <p>It is now legal to supply a constant for a @(see stobj) array dimension.
 See @(see defstobj).  Thanks to Warren Hunt for requesting this
 enhancement.</p>

 <p>We cleaned up a few issues with @(tsee defpkg).</p>

 <blockquote>

 <p>o It is no longer illegal to submit a @(tsee defpkg) form in raw-mode (see
 @(see set-raw-mode)).  Thanks to Jun Sawada for reporting an example in which
 an @(tsee include-book) form submitted in raw-mode caused an error because of
 a `hidden' @(tsee defpkg) form (see @(see hidden-defpkg)).  There will no
 longer be an error in such cases.</p>

 <p>o It had been the case that @(see local)ly including a book could make it
 possible to use a package defined by that book.  Consider for example the
 following book, @('foo.lisp').</p>

 @({
  (in-package \"ACL2\")
  (local (include-book \"arithmetic/top\" :dir :system))
 })

 <p>After certifying this book, it had been possible to admit the following
 events in a new session.</p>

 @({
  (include-book \"foo\")
  (defconst acl2-asg::*foo* 3)
  (defconst *c* 'acl2-asg::xyz)
 })

 <p>In Version_4.3, neither of these @(tsee defconst) events is admitted.</p>

 <p>o A hard Lisp error is now avoided that had been possible in rare cases
 when including books with hidden packages (see @(see hidden-defpkg)). An
 example may be found in a comment in the @(tsee deflabel) for @('note-4-3')
 (in ACL2 source file @('ld.lisp')).</p></blockquote>

 <p>The undocumented (but sometimes useful) functions @('packn1') and
 @('packn') are now @(see guard)-verified @(':')@(tsee logic) mode functions.
 Thanks to Sandip Ray for requesting this enhancement.</p>

 <p>It had been the case that when including a book, functions defined in the
 book's certification @(see world) (that is, in its @(see portcullis) @(see
 command)s) were typically not given compiled code.  That has been fixed.</p>

 <p>The commands @(':')@(tsee pl) and @(':')@(tsee pl2) have been improved,
 primarily by printing information for more rule classes.  See @(see pl) and
 see @(see pl2).  See also the item below about the new @(see proof-builder)
 command, @('show-type-prescriptions').</p>

 <p><b>NEW FEATURES</b></p>

 <p>New macros @(tsee mv?-let) and @(tsee mv?) extend the functionality of
 @(tsee mv-let) and @(tsee mv) (respectively) to the case of a single
 value.</p>

 <p>Macro @(see with-local-state) is available for system programmers who wish
 bind @(tsee state) locally, essentially using @(see with-local-stobj).  But
 this should only be done with extreme care, and it requires an active trust
 tag; see @(see with-local-state).</p>

 <p>Formatted printing functions now have analogues that print to strings and
 do not take an output channel or @(tsee state) as arguments.  See @(see
 printing-to-strings).</p>

 <p>The system function @('ancestors-check') is now available for verified
 modification by users, i.e., attachment using @('(defattach ancestors-check
 <your_function>)').  Thanks to Robert Krug for providing the necessary proof
 support, which we modified only in small ways.</p>

 <p>New macros, @('observation-cw') and @('warning$-cw'), provide formatted
 printing of @(tsee observation)s and warnings (respectively) without @(tsee
 state).  Thanks to Harsh Raju Chamarthi and David Rager for requests leading
 to these utilities.  @('Observation-cw') is now used in some of the
 distributed books (thanks to Robert Krug for useful interaction for that).</p>

 <p>The @(see proof-builder) command @('type-alist') (see @(see
 proof-builder-commands)) now takes an optional third argument that causes the
 production of forward-chaining reports (see @(see forward-chaining-reports)).
 Thanks to Dave Greve for requesting such an enhancement.</p>

 <p>The reports generated by forward-chaining, @(see forward-chaining-reports),
 have been changed to indicate when a conclusion reached by forward chaining is
 @('REDUNDANT') with respect to the type information already known.  Thanks to
 Dave Greve for suggesting this enhancement.</p>

 <p>The utility @(tsee with-prover-time-limit) is now legal for @(see events)
 (see @(see embedded-event-form)).  For example, the following is now
 legal.</p>

 @({
  (encapsulate
   ()
   (with-prover-time-limit
    2
    (defthm append-assoc
      (equal (append (append x y) z)
             (append x (append y z))))))
 })

 <p>The new utility @(tsee with-prover-step-limit) is analogous to the utility
 @(tsee with-prover-time-limit), but counts ``prover steps'' rather than
 checking for time elapsed.  See @(see with-prover-step-limit).  Also see @(see
 set-prover-step-limit) to provide a default step-limit.  Note that just as
 @(tsee with-prover-time-limit) may now be used to create @(see events), as
 discussed just above, @(tsee with-prover-step-limit) may also be used to
 create @(see events).  Thanks to Carl Eastlund for requesting support for
 step-limits.</p>

 <p>The macro @(tsee progn$) is analogous to @(tsee prog2$), but allows an
 arbitrary number of arguments.  For example:</p>

 @({
  ACL2 !>:trans1 (progn$ (f1 x) (f2 x) (f3 x))
   (PROG2$ (F1 X) (PROG2$ (F2 X) (F3 X)))
  ACL2 !>
 })

 <p>Thanks to David Rager for contributing this macro.</p>

 <p>The macro @(tsee defattach) may now be supplied the argument
 @(':skip-checks :cycles').  In this case, as with argument @(':skip-checks
 t'), a trust tag is required (see @(see defttag)), and no logical claims are
 made.  The effect is to avoid the usual check that the extended ancestor
 relation has no cycles (see @(see defattach)).  Thanks to Dave Greve for
 requesting this feature.</p>

 <p>You can now limit the printing of subgoal names when using @(':')@(tsee
 set-gag-mode)@(' :goals').  See @(see set-print-clause-ids).  Thanks to Karl
 Hoech for a suggestion leading to this enhancement.</p>

 <p>A new @(see proof-builder) command, @('show-type-prescriptions'), or
 @('st') for short, provides information about @(':')@(tsee type-prescription)
 rules that match a given term.  Thanks to Dave Greve for requesting this
 enhancement.  See also the item above about related improvements to commands
 @(':')@(tsee pl) and @(':')@(tsee pl2).</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>ACL2 now avoids some repeated attempts to rewrite hypotheses of rewrite
 rules.  See @(see set-rw-cache-state) for a discussion of this behavior and
 how to avoid it.  The default behavior has been observed to reduce by 11% the
 overall time required to complete a regression.  Here are the directories that
 had the top three time decreases and top three time increases, shown in
 seconds.</p>

 @({
    -368 coi/gacc (1064 down to 696: decrease of 35%)
    -220 workshops/1999/ste (664 down to 444: decrease of 33%)
    -148 unicode (331 down to 183: decrease of 45%)
    ....
      +7 workshops/2002/cowles-flat/support (229 up to 236: increase of 3%)
      +8 workshops/1999/ivy/ivy-v2/ivy-sources (508 up to 516: increase of 2%)
     +12 workshops/2009/hardin/deque-stobj (78 up to 91: increase of 17%)
 })

 <p>The so-called ``ancestors check,'' which is used to limit backchaining, has
 been strengthened so that two calls of @(tsee equal) are considered the same
 even if their arguments appear in the opposite order.  Thanks to Robert Krug
 for providing an implementation and a useful discussion.</p>

 <p>The check for @(see irrelevant-formals) in processing of @(tsee defun)s has
 been made more efficient.  Thanks to Eric Smith for reporting this issue in
 2001 (!) and thanks to Warren Hunt for recently sending an example.  For that
 example, we have seen the time for the @(see irrelevant-formals) check reduced
 from about 10 seconds to about 0.04 seconds.</p>

 <p>(GCL only) The macro @(tsee mv) has been modified so that certain fixnum
 boxing can be avoided.</p>

 <p>(Allegro CL only) We have set to @('nil') four Allegro CL variables that
 otherwise enable storing of certain source information (for details, see the
 discussion of ``cross-referencing'' in ACL2 source file @('acl2-init.lisp')).
 As a result of this change we have about a 6% speedup on the regression suite,
 but a 27% time reduction on an example that includes a lot of books.</p>

 <p>Exhaustive matching for the case of @(see free-variables) has been extended
 to @(see type-prescription) rules, in analogy to the default setting
 @(':match-free :all') already in place for @(see rewrite), @(see linear), and
 @(see forward-chaining) rules.  See @(see free-variables-type-prescription).
 Thanks to Dave Greve for requesting this enhancement.</p>

 <p><b>BUG FIXES</b></p>

 <p>A soundness bug was fixed in some raw-Lisp code implementing the function,
 @(tsee take).  Thanks to Sol Swords for pointing out this bug with
 (essentially) the following proof of @('nil').</p>

 @({
  (defthmd take-1-nil-logic
    (equal (take 1 nil) '(nil))
    :hints((\"Goal\" :in-theory (disable (take)))))
  (thm nil :hints ((\"Goal\" :use take-1-nil-logic)))
 })

 <p>Calls of @(tsee mbe) in ``safe-mode'' situations &mdash; i.e., during
 evaluation of @(tsee defconst), @(tsee value-triple), and @(tsee defpkg)
 forms, and during macroexpansion &mdash; are now guard-checked.  Thus, in
 these situations both the @(':logic') and @(':exec') forms will be evaluated,
 with an error if the results are not equal.  Formerly, only the @(':logic')
 form was evaluated, which was a soundness bug that could be exploited to prove
 @('nil').  For a such a proof and a bit of further explanation, see the
 example at the top of the comments for @('(deflabel note-4-3 ..)') in ACL2
 source file @('ld.lisp').</p>

 <p>It had been possible to prove @('nil') by proving the following theorem
 using ACL2 built on CCL and then proving its negation using ACL2 built on a
 different host Lisp.</p>

 @({
  (defthm host-lisp-is-ccl
    (equal (cdr (assoc 'host-lisp *initial-global-table*))
           :ccl)
    :rule-classes nil)
 })

 <p>This hole has been plugged by moving the setting of @(''host-lisp') out of
 the constant @('*initial-global-table*').</p>

 <p>Fixed @(tsee trace$) for arguments that are @(see stobj) accessors or
 updaters.  It also gives an informative error in this case when the accessor
 or updater is a macro (because the introducing @(tsee defstobj) event
 specified @(':inline t')).</p>

 <p>Avoided a potential error that could occur when no user home directory is
 located.  Our previous solution for Windows simply avoided looking for ACL2
 customization files (see @(see acl2-customization)) and @('acl2-init.lsp')
 files in a user's home directory.  With this change, we handle such files the
 same for Windows as for non-Windows systems: we always look for ACL2
 customization files (see @(see acl2-customization)) and @('acl2-init.lsp')
 files in a user's home directory, but only if such a directory exists.  Thanks
 to Hanbing Liu for reporting this issue.</p>

 <p>(GCL only) Fixed a bug that prevented the use of @(tsee
 get-output-stream-string$) when the host Lisp is GCL.</p>

 <p>Fixed @(tsee with-live-state) to work properly for executable counterparts
 (so-called ``*1*'' functions).</p>

 <p>Fixed a bug in the error message caused by violating the @(see guard) of a
 macro call.</p>

 <p>Fixed a bug in an error message that one could get when calling @(tsee
 defattach) with argument @(':skip-checks t') to attach to a @(':')@(tsee
 program) mode function symbol that was introduced with @(tsee defun).  (This
 is indeed an error, but the message was confusing.)  Thanks to Robert Krug for
 bringing this bug to our attention.</p>

 <p>Fixed a bug in the loop-checking done on behalf of @(tsee defattach), which
 could miss a loop.  For an example, see the comment about loop-checking in the
 comments for @('(deflabel note-4-3 ..)') in ACL2 source file @('ld.lisp').</p>

 <p>Terms of the form @('(hide <term>)') without free variables could be
 simplified, contrary to the purpose of @(tsee hide).  This is no longer the
 case, Thanks to Dave Greve for reporting this issue.</p>

 <p>An infinite loop could occur when an error was encountered in a call of
 @(tsee wormhole-eval), for example with the following form, and this has been
 fixed.</p>

 @({
  (wormhole-eval 'demo
                 '(lambda ()
                    (er hard 'my-top \"Got an error!\"))
                 nil)
 })

 <p>Fixed a bug in detection of package redefinition.  While we have no example
 demonstrating this as a soundness bug, we cannot rule it out.</p>

 <p>Fixed a bug in the message produced by an erroneous call of @(tsee flet).
 Thanks to Jared Davis for reporting this bug and sending a helpful
 example.</p>

 <p>For a failed @(tsee defaxiom) or @(tsee defthm) event, we now avoid
 printing @(see rune)s that are used only in processing proposed rules to be
 stored, but not in the proof itself.  Thanks to Dave Greve for sending us an
 example that led us to make this fix.</p>

 <p>ACL2 did not reliably enforce the restriction against non-@(tsee local)
 @(tsee include-book) @(see events) inside @(tsee encapsulate) events, as
 illustrated by the following examples.</p>

 @({
  ; not permitted (as expected)
  (encapsulate () (include-book \"foo\"))

  ; permitted (as expected)
  (encapsulate () (local (include-book \"foo\")))

  ; formerly permitted (surprisingly); now, not permitted
  (local (encapsulate () (include-book \"foo\")))
 })

 <p>Moreover, the corresponding error message has been fixed.  Thanks to Jared
 Davis and Sandip Ray for relevant discussions.</p>

 <p>When @(tsee include-book) is given a first argument that is not a string, a
 more graceful error now occurs, where previously an ugly raw Lisp error had
 occurred.  Thanks to Eric Smith for bringing this bug to our attention.</p>

 <p>Fixed a bug in an error message that was printed when an unexpected
 expression has occurred where a @(tsee declare) form is expected.</p>

 <p>(Since all functions are compiled when the host Lisp is CCL or SBCL, the
 following bug fix did not occur for those host Lisps.)  After evaluation of
 @('(')@(tsee set-compile-fns)@(' t)'), all defined functions are expected to
 run with compiled code; but this was not the case for functions exported from
 an @(tsee encapsulate) event.  This has been fixed.</p>

 <p>It had been the case that the @(':')@(tsee puff) command was broken for
 @(tsee include-book) form whose book had been certified in a world with an
 @(tsee add-include-book-dir) event.  This has been fixed.</p>

 <p>Evaluation of @(see stobj) updaters (see @(see defstobj)) may no longer use
 attachments (see @(see defattach)).  This is a subtle point that will likely
 not affect many users.  Thanks to Jared Davis for bringing this issue to our
 attention; a slight variant of his example appears in a comment in ACL2 source
 function @('oneify-cltl-code').</p>

 <p>It had been the case that even when a @(see stobj) creator function was
 declared to be untouchable (see @(see push-untouchable)), a @(tsee
 with-local-stobj) form based on that same stobj was permitted.  Now, such
 forms are not admitted.  Thanks to Jared Davis for a query leading to this
 fix.</p>

 <p>Fixed a buggy message upon @(see guard) violations, which was suggesting
 the use of @('(set-guard-checking :none)') in some cases when guard-checking
 was already set to @(':none').</p>

 <p>It had been possible to get a hard Lisp error when computing with @(tsee
 ec-call) in @(see books).  The following is an example of such a book, whose
 certification no longer causes an error.</p>

 @({
  (in-package \"ACL2\")
  (defun f (x) x)
  (defconst *c* (ec-call (f 3)))
  (defun g (x) (cons x x))
 })

 <p>The command @(':')@(tsee pl2), and also the @(see proof-builder) commands
 @('rewrite') and @('show-rewrites') (and hence their respective aliases @('r')
 and @('sr')), now take rule-id arguments that can be @(':')@(tsee definition)
 @(see rune)s.  These commands dealt with definition rules already, e.g.</p>

 @({
  :pl2 (append x y) binary-append
 })

 <p>but they did not allow explicit specification of @(':definition') runes,
 e.g.:</p>

 @({
  :pl2 (append x y) (:definition binary-append)
 })

 <p>The following example illustrates a bug in the processing of (admittedly
 obscure) @(see hints) of the form @(':do-not-induct name'), where @('name') is
 not @('t'), @(':otf-flg-override'), @(':otf'), or @('nil').  In this example,
 ACL2 had essentially ignored the hint and reverted to prove the original goal
 by induction, rather than to skip the goal temporarily as is expected for such
 hints.  Thanks to David Rager for a helpful discussion.</p>

 @({
  (thm (and (equal (append (append x y) z) (append x y z))
            (equal (append (append x2 y2) z2) (append x2 y2 z2)))
       :hints ((\"Subgoal 1\" :do-not-induct some-name)))
 })

 <p>Fixed a slight bug in the definitions of built-in @(tsee theories).  For
 example, in a fresh ACL2 session the value of the following form is @('nil'),
 but formerly included several @(':')@(tsee definition) @(see rune)s.</p>

 @({
  (let ((world (w state)))
    (set-difference-theories (function-theory :here)
                             (function-theory 'ground-zero)))
 })

 <p><b>CHANGES AT THE SYSTEM LEVEL AND TO DISTRIBUTED BOOKS</b></p>

 <p>Many changes have been made to the distributed books, as recorded in svn
 logs under the `Source' and 'Updates' links at the <a
 href='http://acl2-books.googlecode.com/'>ACL2 Books</a> web page.  Here we
 list some of the more significant changes.</p>

 <blockquote>

 <p>o A large library has been graciously contributed by the formal
 verification group at Centaur Technology.  See @('books/centaur/') and, in
 particular, file @('books/centaur/README'), which explains how the library
 depends on the experimental HONS extension (see @(see
 hons-and-memoization)).</p>

 <p>o Among the new books is an illustration of @(tsee defattach),
 @('books/misc/defattach-example.lisp'), as well as a variant of defattach that
 avoids the need for @(see guard) verification,
 @('books/misc/defattach-bang.lisp').</p>

 <p>o Distributed book @('books/misc/trace1.lisp') has been deleted.  It had
 provided slightly more friendly @(see trace) output for new users, but
 distributed book @('books/misc/trace-star.lisp') may be better suited for that
 purpose.</p></blockquote>

 <p>ACL2 can once again be built on LispWorks (i.e., as the host Lisp), at
 least with LispWorks 6.0.  Thanks to David Rager for useful conversations.
 Several changes have been made from previous LispWorks-based ACL2
 executables:<br></br>

 o ACL2 now starts up in its read-eval-print loop.<br></br>

 o You can save an image with @(tsee save-exec).<br></br>

 o Multiprocessing is not enabled.<br></br>

 o The stack size is managed using a LispWorks variable that causes the stack
 to grow as needed.<br></br>

 o When ACL2 is built a script file is written, as is done for other host
 Lisps.  Thus, (assuming that no @('PREFIX') is specified), @('saved_acl2') is
 just a small text file that invokes a binary executable, which for Lispworks
 is @('saved_acl2.lw').</p>

 <p>The HTML documentation no longer has extra newlines in &lt;pre&gt;
 environments.</p>

 <p>Statistics on ACL2 code size may be found in distributed file
 @('doc/acl2-code-size.txt').  This file and other information can be found in
 a new @(see documentation) topic, @(see about-acl2).</p>

 <p>Fixed the build process to pay attention to environment variable
 @('ACL2_SYSTEM_BOOKS') (which may be supplied as a command-line argument to
 `make').  An ACL2 executable can thus now be built even when there is no
 @('books/') subdirectory if a suitable replacement directory is supplied.</p>

 <p>Some warnings from the host Lisp are now suppressed that could formerly
 appear.  For example, the warnings shown below occurs in Version 4.2 using
 Allegro CL, but not in Version 4.3.</p>

 @({
  ACL2 !>(progn (set-ignore-ok t)
                (set-irrelevant-formals-ok t)
                (defun bar (x y)
                  x))
  [[.. output omitted ..]]
   BAR
  ACL2 !>:comp bar
  ; While compiling BAR:
  Warning: Variable Y is never used.
  ; While compiling (LABELS ACL2_*1*_ACL2::BAR ACL2_*1*_ACL2::BAR):
  Warning: Variable Y is never used.
   BAR
  ACL2 !>
 })

 <p><b>EMACS SUPPORT</b></p>

 <p>The distributed Emacs file @('emacs/emacs-acl2.el') now indents calls of
 @('er@par') and @('warning$@par') the same way that calls of @('defun') are
 indented.</p>

 <p><b>EXPERIMENTAL VERSIONS</b></p>

 <p>The parallel version (see @(see parallelism)) now supports parallel
 evaluation of the ``waterfall'' part of the ACL2 prover; see @(see
 set-waterfall-parallelism).  Thanks to David Rager for doing the primary
 design and implementation work.</p>

 <p>A new macro, @(tsee spec-mv-let), supports speculative and parallel
 execution in the parallel version, courtesy of David Rager.</p>

 <p>Among the enhancements for the HONS version (see @(see
 hons-and-memoization)) are the following.</p>

 <blockquote><p>@(tsee Memoize)d functions may now be traced (see @(see
 trace$)).  Thanks to Sol Swords for requesting this enhancement.</p>

 <p>@(tsee Memoize-summary) and @(tsee clear-memoize-statistics) are now
 @(':')@(tsee logic) mode functions that return @('nil').  Thanks to Sol Swords
 for this enhancement.</p>

 <p>@(tsee Memoize) is now explicitly illegal for constrained functions.
 (Already such memoization was ineffective.)</p>

 <p>A new keyword argument, @(':AOKP'), controls whether or not to allow
 memoization to take advantage of attachments; see @(see memoize) and for
 relevant background, see @(see defattach).</p>

 <p>@(tsee Memoize) is now illegal by default for @(':')@(tsee logic) mode
 functions that have not had their guards verified.  See @(see memoize)
 (keyword @(':ideal-okp')) and see @(see acl2-defaults-table) (key
 @(':memoize-ideal-okp')) for and explanation of this restriction and how to
 avoid it.</p>

 <p>@(see History) commands such as @(':')@(tsee pe) and @(':')@(tsee pbt) now
 display ``@('M')'' or ``@('m')'' to indicate memoized functions.  See @(see
 pc).</p></blockquote>")

(defxdoc |NOTE-4-3(R)|
  :parents (release-notes)
  :short "ACL2 Version  4.3(r) (July, 2011) Notes"
  :long "<p>Please see @(see note-4-3) for changes in Version 4.3 of
  ACL2.</p>")

(defxdoc note-5-0

; Total release note items: 125.

; Improved comments about step-limits.

; Here is a slightly simplified version of the example sent to us by Warren
; Hunt for the defstobj bug involving, quoting the :doc below, "excessively
; restrictive type declarations".

;   (defstobj x86-32
;     (mem :type (array (unsigned-byte 8) (4294967296)) ;; 2^32
;          :initially 0
;          :resizable nil)
;     :inline t)

; It has for some time been illegal to do guard verification inside a
; non-trivial encapsulate for an exported function whose body or guard depends
; on signature functions; see function bogus-exported-compliants.  However, we
; made exceptions both for constrained functions and for non-executable
; functions.  The latter exception has been removed; after all, if the guard
; obligations aren't theorems of the post-encapsulate theory, it's a bit odd to
; allow them.

; For more about the increase in speed for ACL2 array reads, see the Essay on
; Array Caching.

; Regarding the fix to getenv$ etc. mentioned below: we also changed
; throw-nonexec-error, get-output-stream-string$-fn, and set-debugger-enable-fn
; just a bit, just to be safe, though we're not aware of a soundness bug for
; those functions.

; We removed a #-acl2-loop-only shortcut in plist-worldp, which remains as a
; comment in that function.

; Modified the check in acl2-check.lisp related to
; *common-lisp-specials-and-constants*, so that it no longer causes an error
; when attempting to build with ECL (which bound the symbol
; COMMON-LISP:FUNCTION), in case this is something we try in the future.

; The soundness bug for with-live-state has been recorded in a comment where
; that macro is defined.

; (Lispworks mods courtesy of Martin Simmons) Changed calls of
; special-form-or-op-p to expand to calls of special-operator-p.  Changed
; 'cl::getenv to 'hcl::getenv and changed 'cl::setenv to 'hcl::setenv.
; Changed lisp::quit to lispworks:quit in acl2.lisp.

; Modified the DOC targets (and HTML, etc. targets under it) so that one can
; specify ACL2=<your_acl2> on the command line with the make command or as an
; environment variable.  If ACL2 is not thus specified, then PREFIX and
; ACL2_SUFFIX will be used, as before.

; The time-reporting bug was in initialize-summary-accumulators, which had
; called main-timer without accumulating times.  The following simple example
; clearly illustrates the bug, as the summary time should match the runtime
; reported by time$.

; (defun fib (n) (if (or (zp n) (eql n 1)) 1 (+ (fib (- n 1)) (fib (- n 2)))))
; (time$ (progn (defun f1 (x) x)
;               (value-triple (length (make-list 10000000)))
;               (defun f2 (x) x)))

; Cleaned up special-form-or-op-p.

; Modified script saved for sbcl to double the control-stack-size, which
; allowed "make DOC" to complete.

; Fixed the function INDUCT so that the second argument of the inform-simplify
; call is less likely to have duplicates.

; Here we say a bit more about the "logical modeling of the ACL2 evaluator"
; mentioned below.  The function ev-fncall-rec is defined in the logic to be
; ev-fncall-rec-logical, but they did not actually match up.  For example, the
; result differed if ev-fncall-rec below was changed to ev-fncall-rec-logical.
;   (defstub foo () t)
;   (defttag t)
;   (remove-untouchable ev-fncall-rec t)
;   (ev-fncall-rec 'foo nil (w state) 100000 nil nil nil nil t)
; We found several such discrepancies and have fixed them.

; After remarks from Gary Byers, improved fgetprop a bit by using defconstant
; to introduce *current-acl2-world-key* and by using symbol-value for
; 'ACL2_GLOBAL_ACL2::CURRENT-ACL2-WORLD.

; Here is an example showing the "security hole" mentioned in these release
; notes, below.

;   ;;;;; File foo.lisp ;;;;;
;   (in-package "ACL2")
;
;   (defun foo (x)
;     x)
;
;   ;;;;; File foo.acl2x ;;;;;
;   ((1 . (defun foo (x) (cons x x))))
;
;   ;;;;; File top.lisp ;;;;;
;   (in-package "ACL2")
;
;   (include-book "foo")
;
;   (defthm foo-cons
;     (equal (foo x)
;            (cons x x)))
;
;   ;;;;; File top2.lisp ;;;;;
;   (in-package "ACL2")
;
;   (include-book "top")
;
;   (defthm ouch
;     nil
;     :hints (("Goal" :in-theory (disable foo-cons)
;              :use foo-cons))
;     :rule-classes nil)
;
;   ;;;;; File cert.lsp ;;;;;
;
;   (certify-book "foo" 0 t :acl2x t)
;   (u)
;   (certify-book "top")
;   (u)
;   (certify-book "foo" 0 t)
;   (u)
;   (certify-book "top2")
;
;   ;;;;; Now evaluate (ld "cert.lsp") ;;;;;

; We improved the function chk-ld-skip-proofsp to cause a soft error instead of
; a hard error.  For this purpose, we moved set-ld-skip-proofsp and replaced
; its use in axioms.lisp with an f-put-global,

; Modified observation-cw for ACL2(p).  Also, in support of ACL2(p) but also of
; general applicability, we modified io? in the commentp=t case to check that
; the form can be translated, at least by default (see new argument
; chk-translatable).

; The previous definition of cons-term1 has been eliminated, and cons-term2 has
; been renamed to cons-term1.  Thanks to Harsh Raju Chamarthi for pointing out
; the dead code that led to this change.

; We tweaked the implementation of defconst to support fast-alists, based on
; discussions with David Rager and Jared Davis.  To see relevant code, search
; for "Remark on Fast-alists" and also see the new call (remprop k
; 'redundant-raw-lisp-discriminator) in the const-restore-ht case of function
; hcomp-restore-defs.

; The new macro ill-formed-certificate-er is called to provide much more
; information than had been provided by use of the constant,
; *ill-formed-certificate-msg*.

; The change "All trust tags are now in the ~il[keyword] package" was made in
; support of provisional certification.  Sol Swords sent an example in which
; the Complete operation caused an error, the reason being that an unknown
; package was being used in the post-alist in the certificate file.

; Here is the example promised in :doc note-5-0 and in a comment about
; :SKIPPED-PROOFSP in certify-book-fn, regarding "Fixed a soundness bug based
; on the use of ~ilc[skip-proofs] ...."  First consider the following two
; books.

;   -- foo.lisp --

;   (in-package "ACL2")
;   (defun f1 (x) x)
;   ; (defthm bad nil :rule-classes nil)

;   -- bar.lisp --

;   (in-package "ACL2")
;   (local (include-book "foo"))
;   (defthm bad nil :rule-classes nil)

;   --

; Notice that foo.lisp ends in a commented-out form.  Now proceed as follows.
; If you prefer, you can eliminate the two calls of set-ld-skip-proofsp by,
; instead, wrapping a skip-proofs around the defthm.

;  (set-ld-skip-proofsp t state)
;  (defthm bad nil :rule-classes nil)
;  (set-ld-skip-proofsp nil state)
;  (certify-book "foo" 1 t :skip-proofs-okp t)
;  Uncomment out the defthm form in foo.lisp.
;  (ubt! 1)
;  (certify-book "foo" t)
;  (ubt! 1)
;  (certify-book "bar")

; You will see no warnings when certifying bar, and its certificate will show
; no trace of skip-proofs.

; Among the changes made to support congruent stobjs are latching of stobjs in
; raw-ev-fncall; the use of FLET in :print-gv output; and a change to
; processing of rewrite rules such that interpret-term-as-rewrite-rule1 now has
; the previous functionality of interpret-term-as-rewrite-rule, except for
; removing lambdas.

; Improved the :use hint warning by adding the goal name and pointing to a new
; :doc topic, using-enabled-rules.  Thanks to David Rager for pointing out how
; the existing warning could be improved.

; To support guard verification (in new books distributed in books/system/):
; Updated several guards and termination conditions (to endp).  Functions
; affected include sublis-var and sublis-var-lst and some ancestors; subst-var
; and subst-var-lst; and subst-expr1 and subst-expr1-lst and subst-expr.
; Thanks to David Rager for his part in this effort, including his addition of
; books that verify guards for these functions.

; Fixed ill-guarded calls of eq and union-eq in non-recursive-fnnames and
; non-recursive-fnnames-lst, respectively.

; Here is an example of the proof-builder "bug that could result in duplicate
; goal names in the case of forced hypotheses".  The log shown was created by
; using Version_4.3 to execute the six events just below.

;   (defstub f (x) t)
;   (defstub g (x) t)
;   (defstub h (x) t)
;   (defstub k (x) t)
;
;   (defaxiom prop
;     (implies (and (f x) (g x))
;              (h x)))
;
;   (defaxiom prop-ts
;     (implies (force (k x)) (f x))
;     :rule-classes :type-prescription)
;
; The log promised above is then as follows.
;
;   ACL2 !>(verify (h x))
;   ->: (r 1)
;   Rewriting with PROP.
;   --NOTE-- Using the following runes in addition to the indicated rule:
;     ((:TYPE-PRESCRIPTION PROP-TS)).
;   NOTE (forcing):  Creating one new goal due to forcing assumptions.
;
;   Creating two new goals:  (MAIN . 1) and (MAIN . 1).
;
;   The proof of the current goal, MAIN, has been completed.  However,
;   the following subgoals remain to be proved:
;     (MAIN . 1) and (MAIN . 1).
;   Now proving (MAIN . 1).
;   ->: goals
;
;   (MAIN . 1)
;   (MAIN . 1)
;   ->:

; Made a small change to newline printing in ubt-ubu-query and ubt-ubu-fn1 in
; support of the change to top-level (to avoid a bogus newline).

; While fixing the cons-term bug, we improved the efficiency of kwote a bit,
; avoiding some unnecessary consing.

; Improved several :doc topics by clarifying the role of type declarations in
; specifying the guard of a function.

; We eliminated some needless property names from renew-name/overwrite, and
; added a comment clarifying why it is only called on function symbols.

; Added new severity option HARD?! for er, so that the guard of theory-fn can
; be t (avoiding the expense of doing the theory-namep check twice).

; We now print notes to use :a! and see :DOC set-evisc-tuple when evaluating
; :brr t.  Thanks to Robert Krug for suggesting this improvement.

; Eliminated warnings at build time for CLISP due to two definitions of the
; same function from both defproxy and encapsulate, by marking those
; encapsulate forms (in boot-strap-pass-2.lisp) as #+acl2-loop-only.

  :parents (release-notes)
  :short "ACL2 Version  5.0 (August, 2012) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 4.3 into the following
 categories of changes: existing features, new features, heuristic
 improvements, bug fixes, changes at the system level and to distributed books,
 Emacs support, and experimental versions.  Each change is described in just
 one category, though of course many changes could be placed in more than one
 category.</p>

 <p>NOTE: ACL2 is now distributed under Version 2 of the GNU General Public
 License.  [Added later: The license has changed since Version_5.0.  See
 LICENSE.]  Formerly, any later version had been acceptable.  Moreover, books
 are no longer distributed from a University of Texas website, but rather, from
 Google Code at the <a
 href='http://code.google.com/p/acl2-books/downloads/'>ACL2 Books Downloads</a>
 page.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>A fatal error now occurs if environment variable @('ACL2_CUSTOMIZATION')
 has a value other than @('NONE') or the empty string, but is not the name of
 an existing file.  Thanks to Harsh Raju Chamarthi for requesting such a
 change.</p>

 <p>Functions @('read-acl2-oracle') (and @('read-acl2-oracle@par')),
 @('read-run-time'), and @('main-timer') are no longer untouchable (see @(see
 remove-untouchable)).</p>

 <p>We now avoid certain duplicate conjuncts in the @(see constraint) stored
 for @(tsee encapsulate) @(see events).  For example, the constraint stored for
 the following event formerly included @('(EQUAL (FOOP (CONS X Y)) (FOOP Y))')
 and @('(BOOLEANP (FOOP X))') twice each, but no more.</p>

 @({
  (encapsulate
   ((foop (x) t))
   (local (defun foop (x) (declare (ignore x)) t))
   (defthm foop-constraints
     (and (booleanp (foop x))
          (equal (foop (cons x y)) (foop y)))
     :rule-classes
     ((:type-prescription :corollary (booleanp (foop x)))
      (:rewrite :corollary (equal (foop (cons x y)) (foop y))))))
 })

 <p>The @(':')@(tsee guard) for a constrained function (see @(see signature))
 may now mention function symbols introduced in the same @(tsee encapsulate)
 event that introduces that function.  Thanks to Nathan Wetzler for a helpful
 discussion leading to this improvement.</p>

 <p>The test for redundancy (see @(see redundant-events)) of @(tsee
 encapsulate) @(see events) has been improved in cases involving redefinition
 (see @(see ld-redefinition-action)).  Thanks to Jared Davis for providing the
 following example, which illustrates the problem.</p>

 @({
    (redef!)

    (encapsulate ()
      (defun g (x)
        (+ 3 x)))

    (g 0) ; 3, as expected

    (encapsulate ()
      (defun g (x)
        (+ 4 x)))

    (g 0) ; 4, as expected

    ; Unfortunately, the following was flagged as redundant because it agreed
    ; with the first encapsulate above.  That has been fixed; now, it is
    ; recognized as not being redundant.
    (encapsulate ()
      (defun g (x)
        (+ 3 x)))
 })

 <p>The test for redundancy of @(tsee defun) and @(tsee defconst) events has
 been improved in the case that redefinition is active.  In that case,
 redundancy now additionally requires that the ``translated'' body is
 unchanged, i.e., even after expanding macro calls and replacing constants
 (defined by @(tsee defconst)) with their values.  Thanks to Sol Swords for
 requesting this enhancement, and to Jared Davis for pointing out a bug in a
 preliminary change.  See @(see redundant-events), in particular the ``Note
 About Unfortunate Redundancies''.  Note that this additional requirement was
 already in force for redundancy of @(tsee defmacro) events.</p>

 <p>The macro @(tsee defmacro-last) and the @(see table) @(tsee
 return-last-table) have been modified so that when they give special treatment
 to a macro @('mac') and its raw Lisp counterpart @('mac-raw'), a call
 @('(return-last 'mac-raw ...)')  can be made illegal when encountered directly
 in the top level loop, as opposed to inside a function body.  See @(see
 return-last).  Thanks to Harsh Raju Chamarthi for showing us an example that
 led us to make this improvement.</p>

 <p>We removed a barrier to admitting function definitions, as we explain using
 the following example.</p>

 @({
  (defun foo (m state)
    (declare (xargs :stobjs state))
    (if (consp m)
        (let ((state (f-put-global 'last-m m state)))
          (foo (cdr m) state))
      state))
 })

 <p>Previously, ACL2 complained that it could not determine the outputs of the
 @(tsee LET) form, as is necessary in order to ensure that @(tsee STATE) is
 returned by it.  ACL2 now works harder to solve this problem as well as the
 analogous problem for @(tsee MV-LET) and, more generally for @(tsee
 mutual-recursion).  (The main idea is to reverse the order of processing the
 @(tsee IF) branches if necessary.)  We thank Sol Swords for contributing a
 version of the above example and requesting this improvement.</p>

 <p>It is no longer the case that @(tsee break-on-error) causes a Lisp break
 when encountering an error during translation of user input into internal
 (translated) form (see @(see term)).  The reason is that an improvement to the
 translation process, specifically the one described in the preceding
 paragraph, allows certain backtracking from ``errors'', which are intended to
 be silent rather than causing breaks into raw Lisp.  Thanks to Jared Davis for
 sending an example leading to this change.</p>

 <p>(CCL and SBCL only) When the host Lisp is CCL or SBCL, then since all
 functions are compiled, a @(tsee certify-book) command will no longer load the
 newly-compiled file (and similarly for @(tsee include-book) with argument
 @(':load-compiled-file :comp')).</p>

 <p>@(tsee Set-write-acl2x) now returns an error triple and can take more
 values, some of which automatically allow including uncertified books when
 @(tsee certify-book) is called with argument :acl2x t.</p>

 <p>The environment variable @('COMPILE_FLG') has been renamed
 @('ACL2_COMPILE_FLG'); see @(see certify-book).</p>

 <p>The macros @(tsee defthmd) and @(tsee defund) no longer return an error
 triple with value @(':SKIPPED') when proofs are being skipped.  Rather, the
 value returned is the same as would be returned on success when proofs are not
 skipped.</p>

 <p>For those who use @(tsee set-write-acl2x): now, when @(tsee certify-book)
 is called without a @(':ttagsx') argument supplied, then the value of
 @(':ttagsx') defaults to the (explicit or default) value of the @(':ttags')
 argument.</p>

 <p>The @(':')@(tsee pl) and @(':')@(tsee pl2) @(see command)s can now accept
 @(see term)s that had previously been rejected.  For example, the command
 @(':pl (member a (append x y))') had caused an error, but now it works as one
 might reasonably expect, treating @(tsee member) as @(tsee member-equal) (see
 @(see equality-variants) for relevant background).  Thanks to Jared Davis for
 reporting this problem by sending the above example.</p>

 <p>We have eliminated some hypotheses in built-in @(see rewrite) rules
 @('characterp-nth') and @('ordered-symbol-alistp-delete-assoc-eq').</p>

 <p>Added the symbols @(tsee f-get-global), @(tsee f-put-global), and @(tsee
 state-global-let*) to @('*acl2-exports*').</p>

 <p>Added to the @(see guard)s of @(tsee push-untouchable) and @(tsee
 remove-untouchable) the requirement that the second argument must be a
 Boolean.  Thanks to Jared Davis for sending an example that led to this
 change.</p>

 <p>The built-in function @('string-for-tilde-@-clause-id-phrase') has been put
 into @(':')@(tsee logic) mode and had its guards verified, as have some
 subsidiary functions.  A few new rules have been added in support of this
 work; search for @('string-for-tilde-@-clause-id-phrase') in ACL2 source file
 @('boot-strap-pass-2.lisp') if interested.  Thanks to David Rager for
 contributing an initial version of this improvement.</p>

 <p>All trust tags are now in the @(see keyword) package.  The @(tsee defttag)
 event may still take a symbol in an arbitrary package, but the trust tag
 created will be in the keyword package (with the same @(tsee symbol-name) as
 the symbol provided).  Similarly, non-@('nil') symbols occurring in the
 @(':ttags') argument of an @(tsee include-book) or @(tsee certify-book)
 command will be converted to corresponding keywords.  See @(see defttag).</p>

 <p>There have been several changes to @(see gag-mode).  It is now is initially
 set to @(':goals'), suppressing most proof commentary other than key
 checkpoints; see @(see set-gag-mode).  (As before, see @(see pso) for how to
 recover the proof output.)  Also, top-level induction schemes are once again
 printed when gag-mode is on, though these as well as printing of guard
 conjectures can be abbreviated (``eviscerated'') with a new @(see
 evisc-tuple); see @(see set-evisc-tuple), in particular the discussion there
 of @(':GAG-MODE').  Finally, the commentary printed within @(see gag-mode)
 that is related to @(see forcing-round)s is now less verbose.  Thanks to Dave
 Greve and David Rager for discussions leading to the change in the printing of
 induction schemes under gag-mode; thanks to Warren Hunt for an email that led
 us to similar handling for printing of guard conjectures; and thanks to Robert
 Krug for a suggestion that led us to restore, in abbreviated form, important
 information about the sources of forcing round goals.</p>

 <p>An error now occurs if @(tsee ld) is called while loading a compiled book.
 See @(see calling-ld-in-bad-contexts).  Thanks to David Rager for reporting a
 low-level assertion failure that led us to make this change.</p>

 <p>The @(see proof-builder) interactive loop is more robust: most errors will
 leave you in that loop, rather than kicking you out of the proof-builder and
 thus back to the main ACL2 read-eval-print loop.  Thanks to David Hardin for
 suggesting this improvement in the case of errors arising from extra right
 parentheses.</p>

 <p>The summary at the end of a proof now prints the following note when
 appropriate:</p>

 @({
  [NOTE: A goal of NIL was generated.  See :DOC nil-goal.]
 })

 <p>See @(see nil-goal).</p>

 <p>Improved @(tsee dmr) to show the function being called in the case of
 explicit evaluation: ``@('(EV-FNCALL function-being-called)')''.</p>

 <p>It is now permitted to bind any number of @(see stobjs) to themselves in
 the bindings of a @(tsee LET) expression.  But if any stobj is bound to other
 than itself in @(tsee LET) bindings, then there still must be only one binding
 in that @('LET') expression.  The analogous relaxation holds for @(tsee
 LAMBDA) expressions.  Thanks to Sol Swords for requesting such a change, which
 was needed for some code generated by macro calls.</p>

 <p>The macro @(tsee top-level) now returns without error; See @(see
 top-level).  Formerly, this macro always returned an error triple @('(mv t
 .. state)'), which meant that normal calls of @(tsee ld) would stop after
 encountering a call of @('top-level').  Thanks to Jared Davis for bringing
 this issue to our attention.</p>

 <p>It is no longer the case that when you specify @(tsee xargs) keyword
 @(':non-executable t') in a @(tsee defun) form rather than using @(tsee
 defun-nx), then the form of the body need match only the shape @('(prog2$
 (throw-nonexec-error ... ...) ...)').  We now require that the body of the
 definition of a function symbol, @('fn'), with formals @('(x1 ... xk)'), be of
 the form @('(prog2$ (throw-nonexec-error 'fn (list x1 ... xk)) ...)').  This
 fixes the following odd behavior, which could be considered a bug.  Consider a
 book that contains the following two events.</p>

 @({
  (defun foo (x)
    (declare (xargs :guard t :non-executable t :mode :logic))
    (prog2$ (throw-nonexec-error 'bar (list x))
            (cons 3 x)))
  (defn h (x)
    (foo x))
 })

 <p>After certifying this book and then including it in a new session, the
 behavior occurred that is displayed below; notice the mention of @('BAR').
 However, if the two forms were submitted directly in the loop, then the error
 message had mentioned @('FOO') instead of @('BAR').  This discrepancy has been
 eliminated, by rejecting the proposed definition of @('foo') because the name
 in the first argument of @('throw-nonexec-error') was @(''bar') where now it
 must be @(''foo').</p>

 @({
  ACL2 !>(h 3)

  ACL2 Error in TOP-LEVEL:  ACL2 cannot ev the call of undefined function
  BAR on argument list:

  (3)

  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

  ACL2 !>
 })

 <p>A tautology checker used in the ACL2 sources (function @('if-tautologyp'))
 has been limited somewhat in the effort it makes to recognize a tautology.
 While we expect it to be rare for the effect of this change to be noticeable,
 we thank Sol Swords for sending us an example that motivated this change: a
 @(see guard) verification that took about 5 seconds in Version_4.3 now takes,
 on the same machine, about 0.07 seconds.</p>

 <p>The behavior of backquote (@('`')) has been changed slightly to be
 compatible with its behavior in raw Lisp.  The change is to allow the use of
 comma-atsign (@(',@')) at the end of a list, as in the following example.</p>

 @({
  (let ((x 3) (y 2) (z 7)) `(,x ,y ,@z))
 })

 <p>Formerly, evaluation of this form had caused a guard violation in the ACL2
 loop unless guard-checking was off (i.e., @(tsee set-guard-checking) was
 invoked with @('nil') or @(':none')), in which case it returned @('(3 2)').
 But we observed evaluation of this form to return @('(3 2 . 7)') in every host
 Lisp on which ACL2 runs (Allegro CL, CCL, CLISP, CMUCL, GCL, LispWorks, and
 SBCL).  Now, ACL2 behaves like these Lisps.</p>

 <p>A call of the @(tsee theory) macro had previously returned @('nil') when
 applied to other than the name of name of a previously executed @(tsee
 deftheory) event.  Now, a hard error occurs.</p>

 <p>The @(see table) @('binop-table') has been replaced by the table @(tsee
 untrans-table).  However, @(tsee add-binop) and @(tsee remove-binop) continue
 to have the same effect as before.  See @(see add-macro-fn), which is a new
 feature discussed below.</p>

 <p>The function @(tsee booleanp) is now defined using @(tsee eq) instead of
 @(tsee equal), which may increase its efficiency.  Thanks to Jared Davis for
 this change.</p>

 <p>For pairs @('(key . val)') in the @(tsee macro-aliases-table), there had
 been a requirement that @('val') is a known function symbol.  Now, it only
 needs to be a symbol.  (This change was made to support the new feature,
 @(tsee defun-inline), described elsewhere in these release notes.)</p>

 <p><b>NEW FEATURES</b></p>

 <p>A new ``tau system'' provides a kind of ``type checker.''  See @(see
 tau-system).  Thanks to Dave Greve for supplying a motivating example (on
 which this system can provide significant speedup), and to Sol Swords for
 sending a very helpful bug report on a preliminary implementation.</p>

 <p>Users may now arrange for additional summary information to be printed at
 the end of @(see events).  [Note added at Version_6.1: Formerly we pointed
 here to @('print-summary-user'), but now, see @(see finalize-event-user); also
 see @(see note-6-1)].  Thanks to Harsh Raju Chamarthi for requesting this
 feature and participating in a design discussion.</p>

 <p>A new, advanced @(see proof-builder) command, @('geneqv'), shows the
 generated equivalence relation at the current subterm.  Thanks to Dave Greve
 for an inquiry leading to this enhancement.</p>

 <p>A new reader macro, @('#u'), permits the use of underscore characters in a
 number.  See @(see sharp-u-reader).  Thanks to Jared Davis for requesting this
 capability.</p>

 <p>New @(see proof-builder) commands @('pl') and @('pr') provide interfaces to
 the ACL2 commands @(':')@(tsee pl) and @(':')@(tsee pr), respectively.  These
 can be useful if you want to see trivially-proved hypotheses, as now clarified
 in the @(see proof-builder) documentation for its @('show-rewrites') command.
 See @(see proof-builder-commands).  Thanks to Pete Manolios for suggesting
 such clarification and capability.</p>

 <p>It is now legal to call @(see non-executable) functions without the usual
 @(see signature) restrictions imposed on executable code.  For example, the
 third event below was not admissible, but now it is.</p>

 @({
  (defstobj foo fld)
  (defun-nx id (x)
    x)
  (defun f (foo)
    (declare (xargs :stobjs foo :verify-guards nil))
    (cons 3 (id foo)))
 })

 <p>Thanks to Jared Davis for requesting this enhancement, in particular for
 calling non-executable functions in the @(':logic') part of an @(tsee mbe)
 call.  Here is Jared's example, which is admissible now but formerly was
 not.</p>

 @({
  (defstobj foo (fld))
  (defun-nx my-identity (x) x)
  (defun my-fld (foo)
    (declare (xargs :stobjs foo))
    (mbe :logic (my-identity foo)
         :exec (let ((val (fld foo)))
                 (update-fld val foo))))
 })

 <p>A new macro, @(tsee non-exec), allows the use of non-executable code, for
 example inside ordinary function definitions.  Thanks to Sol Swords for
 requesting this enhancement.</p>

 <p>A new ``provisional certification'' process is supported that can allow
 @(see books) to be certified before their included sub-books have been
 certified, thus allowing for potentially much greater `make'-level
 parallelism.  See @(see provisional-certification).  Thanks to Jared Davis for
 requesting this feature and for helpful discussions, based in part on
 rudimentary provisional certification schemes that he developed first at
 Rockwell Collins and later for his `Milawa' project.  Also, thanks to Jared
 and to Sol Swords for testing this feature and for providing a fix for a bug
 in a preliminary implementation, and thanks to Sol for providing performance
 feedback and a crucial suggestion that led to an improved implementation.</p>

 <p>Event summaries now show the names of events that were mentioned in @(see
 hints) of type @(':use'), @(':by'), or @(':clause-processor').  See @(see
 set-inhibited-summary-types).  Thanks to Francisco J. Martin Mateos for
 requesting such an enhancement (actually thanks to the community, as his
 request is the most recent but this has come up from time to time before).</p>

 <p>ACL2 now stores a data structure representing the relation ``Event A is
 used in the proof of Event B.''  See @(see dead-events), which explains this
 data structure and mentions one application: to identify dead code and unused
 theorems.  Thanks to Shilpi Goel for requesting such a feature and for helpful
 feedback.</p>

 <p>A new @(see documentation) topic provides a guide to programming with
 state; see @(see programming-with-state).  Thanks to Sarah Weissman for
 suggesting that such a guide might be useful, and to David Rager for helpful
 feedback on a preliminary version.  There also has been some corresponding
 reorganization of the documentation as well as creation of additional
 documentation (e.g., see @(see state-global-let*)).  Now, most built-in
 functions and macros commonly used in programs (as opposed to @(see events)
 like @(tsee defun), for example) are subtopics of a new topic &mdash; see
 @(see acl2-built-ins) &mdash; which is a subtopic of @(see programming), a
 topic that in turn has considerably fewer direct subtopics than before.</p>

 <p>It is now possible to bind extra variables in a @(':USE') hint, thus
 avoiding the error message: ``The formula you wish to instantiate, ...,
 mentions only the variable(s) ...''.  See @(see lemma-instance), in particular
 the discussion of keyword @(':extra-bindings-ok').  Thanks to Sol Swords for
 requesting such an enhancement.</p>

 <p>The function @('read-object-suppress') is like @('read-object') except that
 it avoids errors and discards the value read.  See @(see io).</p>

 <p>A @(see stobj) may now be passed as an argument where another stobj is
 expected if the two are ``congruent''.  See @(see defstobj), in particular,
 its discussion of the new @(':congruent-to') keyword of @('defstobj').  Thanks
 to Sol Swords for requesting this enhancement and for useful discussions
 contributing to its design.</p>

 <p>A new top-level utility has been provided that shows the assembly language
 for a defined function symbol; see @(see disassemble$).  Thanks to Jared Davis
 for requesting such a utility and to Shilpi Goel for pointing out an
 inconvenience with the initial implementation.  Note that it uses the
 distributed book @('books/misc/disassemble.lisp'), which users are welcome to
 modify (see @(see community-books)).</p>

 <p>The macro @('set-accumulated-persistence') is an alias for @(tsee
 accumulated-persistence).  Thanks to Robert Krug for suggesting this
 addition.</p>

 <p>A new @(see documentation) topic lists lesser-known and advanced ACL2
 features, intended for those with prior ACL2 experience who wish to extend
 their knowledge of ACL2 capabilities.  See @(see advanced-features).  Thanks
 to Warren Hunt and Anna Slobodova for requesting such information.</p>

 <p>A new macro, @(tsee deftheory-static), provides a variant of @(tsee
 deftheory) such that the resulting theory is the same at @(tsee include-book)
 time as it was at @(tsee certify-book) time.  Thanks to Robert Krug for
 helpful discussions on this new feature and for updating his
 @('books/arithmetic-5/') distributed books to use this feature.</p>

 <p>A new event, @(tsee defabsstobj), provides a new way to introduce
 single-threaded objects (see @(see stobj) and see @(see defstobj)).  These
 so-called ``abstract @(see stobj)s'' permit user-provided logical definitions
 for primitive operations on stobjs, for example using an alist-based
 representation instead of a list-based representation for array fields.
 Moreover, the proof obligations guarantee that the recognizer is preserved;
 hence the implementation avoids executing the recognizer, which may be an
 arbitrarily complex invariant that otherwise would be an expensive part of
 @(see guard) checks.  Thanks to Warren Hunt for a request leading us to design
 and implement this new feature, and thanks to Rob Sumners for a request
 leading us to implement a related utility, @(tsee defabsstobj-missing-events).
 See @(see defabsstobj).  Also thanks to Sol Swords for sending an example
 exhibiting a bug in the initial implementation, which has been fixed.</p>

 <p>A new command, @(':psof <filename>'), is like @(':pso') but directs proof
 replay output to the specified file.  For large proofs, @(':')@(tsee psof) may
 complete much more quickly than @(':')@(tsee pso).  see @(see psof).  More
 generally, a new utility, @(tsee wof) (an acronym for ``With Output File''),
 directs standard output and proofs output to a file; see @(see wof).</p>

 <p>The new macro @(tsee defnd) defines a function with @(':')@(tsee guard)
 @('t') and @(see disable)s that function, in analogy to how @(tsee defund)
 defines with @(tsee defun) and then @(see disable)s.  Thanks to Shilpi Goel
 for requesting this feature.</p>

 <p>The @(':')@(tsee pl2) command now shows @(':')@(tsee linear) rules; and a
 new @(see proof-builder) command, @('show-linears') (equivalently, @('sls')),
 is an analogue of the @(see proof-builder) @('show-rewrites') (@('sr'))
 command, but for @(see linear) rules.  Thanks to Shilpi Goel for requesting
 this new proof-builder command.  Finally, a corresponding new proof-builder
 command, @('apply-linear') (@('al')), is an analogue of the @(see
 proof-builder) @('rewrite') (@('r')) command, but for @(see linear) rules.</p>

 <p>The macros @(tsee add-macro-fn) and @(tsee remove-macro-fn) replace macros
 @(tsee add-binop) and @(tsee remove-binop), respectively, though the latter
 continue to work.  The new macros allow you to decide whether or not to
 display calls of binary macros as flat calls for right-associated arguments,
 e.g., @('(append x y z)') rather than @('(append x (append y z))').  See @(see
 add-macro-fn).</p>

 <p>It is now possible to request that the host Lisp compiler inline calls of
 specified functions, or to direct that the host Lisp compiler not inline such
 calls.  See @(see defun-inline) and see @(see defun-notinline).  We thank
 Jared Davis for several extensive, relevant conversations, and for finding a
 bug in a preliminary implementation.  We also thank others who have engaged in
 discussions with us about inlining for ACL2; besides Jared Davis, we recall
 such conversations with Rob Sumners, Dave Greve, and Shilpi Goel.</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>Reading of ACL2 @(tsee arrays) (see @(see aref1), see @(see aref2)) has
 been made more efficient (as tested with CCL as the host Lisp) in the case of
 consecutive repeated reads of the same named array.  Thanks to Jared Davis and
 Sol Swords for contributing this improvement.</p>

 <p>Slightly modified the induction schemes stored, so that calls of so-called
 ``guard-holders'' (such as @(tsee mbe) and @(tsee prog2$) &mdash; indeed, any
 call of @(tsee return-last) &mdash; and @(tsee the)) are expanded away.  In
 particular, calls of equality variants such as @(tsee member) are treated as
 their corresponding function calls, e.g., @(tsee member-equal); see @(see
 equality-variants).  Guard-holders are also now expanded away before storing
 @(see constraint)s for @(tsee encapsulate) @(see events), which can sometimes
 result in simpler constraints.</p>

 <p>Improved the performance of @(tsee dmr) (technical note: by modifying raw
 Lisp code for function @('dmr-flush'), replacing @('finish-output') by
 @('force-output')).</p>

 <p>We now avoid certain rewriting loops.  A long comment about this change,
 including an example of a loop that no longer occurs, may be found in source
 function @('expand-permission-result').</p>

 <p>Slightly strengthened @(see type-set) reasoning at the level of literals
 (i.e., top-level hypotheses and conclusions).  See the comment in ACL2 source
 function @('rewrite-atm') about the ``use of dwp = t'' for an example of a
 theorem provable only after this change.</p>

 <p>Strengthened the ability of @(see type-set) reasoning to make deductions
 about terms being integers or non-integer rationals.  The following example
 illustrates the enhancement: before the change, no simplification was
 performed, but after the change, the conclusion simplifies to @('(foo t)').
 Thanks to Robert Krug for conveying the problem to us and outlining a
 solution.</p>

 @({
  (defstub foo (x) t)
  (thm ; should reduce conclusion to (foo t)
   (implies (and (rationalp x)
                 (rationalp y)
                 (integerp (+ x (* 1/3 y))))
            (foo (integerp (+ y (* 3 x))))))
 })

 <p><b>BUG FIXES</b></p>

 <p>Fixed a class of soundness bugs involving each of the following functions:
 @(tsee getenv$), @(tsee get-wormhole-status), @(tsee cpu-core-count), @(tsee
 wormhole-p), @(tsee random$), @('file-write-date$'), and
 @('serialize-read-fn'), and (for the HONS version of ACL2) @(tsee
 clear-memoize-table) and @(tsee clear-memoize-tables) as well as (possible
 soundness bug) @('serialize-write-fn').  For example, we were able to admit
 the following events, but that is no longer the case (neither for @('getenv$')
 as shown, nor analogously for other functions listed above).</p>

 @({
  (defthm not-true
    (stringp (cadr (getenv$ \"PWD\" (build-state))))
    :rule-classes nil)

  (defthm contradiction
    nil
    :hints ((\"Goal\"
             :in-theory (disable (getenv$))
             :use not-true))
    :rule-classes nil)
 })

 <p>Fixed a soundness bug involving @('with-live-state'), which could cause an
 error in the use of @(tsee add-include-book-dir) or @(tsee
 delete-include-book-dir) in a book or its @(see portcullis) commands.  See
 @(see with-live-state), as the documentation for this macro has been updated;
 in particular it is now untouchable (see @(see remove-untouchable)) and is
 intended only for system hackers.  Thanks to Jared Davis for reporting a bug
 in the use of @(tsee add-include-book-dir) after our first attempt at a
 fix.</p>

 <p>Fixed a soundness bug based on the use of @(tsee skip-proofs) together with
 the little-used argument @('k=t') for @(tsee certify-book).  An example proof
 of @('nil') appears in a comment in the ACL2 sources, in @('(deflabel note-5-0
 ...)').</p>

 <p>Fixed a soundness bug that allowed users to define new @(see proof-builder)
 primitive commands.  Before this fix, a book proving @('nil') could be
 certified, as shown in a comment now in the introduction of the @(see table)
 @('pc-command-table') in source file @('proof-builder-a.lisp').</p>

 <p>(Technical change, primarily related to @(tsee make-event):) Plugged a
 security hole that allowed @(see books)' @(see certificate)s to be out-of-date
 with respect to @(tsee make-event) expansions, but not recognized as such.
 The change is to include the so-called expansion-alist in the certificate's
 checksum.  An example appears in a comment in the ACL2 sources, in
 @('(deflabel note-5-0 ...)').</p>

 <p>Fixed a bug in @(see guard) verification due to expanding calls of
 primitives when translating user-level terms to internal form, so called
 ``translated terms'' (see @(see term)).  While we have not observed a
 soundness hole due to this bug, we have not ruled it out.  Before the bug fix,
 the following event was admissible, as guard verification succeeded (but
 clearly should not have).</p>

 @({
  (defun f ()
    (declare (xargs :guard t))
    (car (identity 3)))
 })

 <p>For those who want details about this bug, we analyze how ACL2 generates
 @(see guard) proof obligations for this example.  During that process, it
 evaluates ground subexpressions.  Thus, @('(identity '3)') is first simplified
 to @(''3'); so a term must be built from the application of @('car') to
 @(''3').  Guard-checking is always turned on when generating guard proof
 obligations, so now, ACL2 refuses to simplify @('(car '3)') to @(''nil').
 However, before this bug fix, when ACL2 was building a term by applying
 @('car') to argument @(''3'), it did so directly without checking guards;
 source code function @('cons-term') is `smart' that way.  After the fix, such
 term-building reduction is only performed when the primitive's guard is
 met.</p>

 <p>While calls of many event macros had been prohibited inside executable
 code, others should have been but were not.  For example, the following was
 formerly allowed.</p>

 @({
  (defun foo (state)
    (declare (xargs :mode :program :stobjs state))
    (add-custom-keyword-hint :my-hint (identity nil)))
  (foo state) ; Caused hard raw Lisp error!
 })

 <p>Thus, several event macros (including for example @(tsee
 add-custom-keyword-hint)) may no longer be called inside executable code.</p>

 <p>Fixed an assertion that could occur, for example, after reverting to prove
 the original goal by induction and generating a goal of @('NIL').  Thanks to
 Jared Davis for sending us a helpful example to bring this bug to our
 attention.</p>

 <p>It was possible for @(tsee defstobj) to generate raw Lisp code with
 excessively restrictive type declarations.  This has been fixed.  Thanks to
 Warren Hunt for reporting this bug and sending an example that illustrates it.
 See @(see stobj-example-2) for examples of such raw Lisp code; now, one finds
 @('(and fixnum (integer 0 *))') where formerly the type was restricted to
 @('(integer 0 268435455)').</p>

 <p>Fixed a bug in that was ignoring the use of @(':computed-hint-replacement')
 in certain cases involving a combination of computed hints and custom keyword
 hints.  Thanks to Robert Krug for reporting this bug and sending a very
 helpful example.</p>

 <p>Fixed a bug in the output from @(tsee defattach), which was failing to list
 previous @(see events) in the message about ``bypassing constraints that have
 been proved when processing the event(s)''.</p>

 <p>(GCL only) Fixed a bug in @(tsee set-debugger-enable) (which was only a bug
 in GCL, not an issue for other host Lisps).</p>

 <p>Fixed ACL2 trace output to indent properly for levels above 99 (up to
 9999).  Thanks to Warren Hunt for bringing this bug to our attention.</p>

 <p>Fixed a bug in the reporting of times in event summaries &mdash; probably
 one that has been very long-standing!  The times reported had often been too
 small in the case of compound @(see events), notably @(tsee include-book).
 Thanks to everyone who reported this problem (we have a record of emails from
 Eric Smith and Jared Davis on this issue).</p>

 <p>Fixed a bug in @(':expand') @(see hints), where the use of @(':lambdas')
 could prevent other parts of such a hint.  For example, the following
 invocation of @(tsee thm) failed before this fix was made.</p>

 @({
  (defund foo (x) (cons x x))
  (thm (equal (car (foo x)) x)
  :hints ((\"Goal\" :expand (:lambdas (foo x)))))
 })

 <p>Certain ``program-only'' function calls will now cause hard Lisp errors.
 (The rather obscure reason for this fix is to support logical modeling of the
 ACL2 evaluator.  A relevant technical discussion may be found in source
 function @('oneify-cltl-code'), at the binding of variable
 @('fail_program-only-safe').)</p>

 <p>There was an unnecessary restriction that @(tsee FLET)-bound functions must
 return all @(see stobj)s among their inputs.  For example, the following
 definition was rejected because @('state') was not among the outputs of
 @('h').  This restriction has been removed.</p>

 @({
  (defun foo (state)
    (declare (xargs :stobjs state))
    (flet ((h (state) (f-boundp-global 'x state)))
      (h state)))
 })

 <p>We fixed a bug, introduced in the preceding release (Version 4.3), in the
 check for irrelevant formals (see @(see irrelevant-formals)).  That check had
 been too lenient in its handling of lambda (@(see LET)) expressions, for
 example allowing the following definition to be admitted in spite of its first
 formal parameter obviously being irrelevant.</p>

 @({
  (defun foo (x clk)
    (if (zp clk)
        :diverge
      (let ((clk (1- clk)))
        (foo x clk))))
 })

 <p>Fixed a bug in the @('mini-proveall') target in @('GNUmakefile').  The fix
 includes a slight change to the @(':mini-proveall') @(see command) (an extra
 event at the end).  Thanks to Camm Maguire for reporting this bug.</p>

 <p>Fixed a bug that occurred when @(tsee certify-book) was called after using
 @(tsee set-fmt-soft-right-margin) or @(tsee set-fmt-hard-right-margin) to set
 a small right margin.</p>

 <p>Fixed @(tsee set-inhibit-warnings) so that it takes effect for a subsequent
 @(tsee include-book) event.  Thanks to Jared Davis and David Rager for queries
 that led to this fix.</p>

 <p>Hard Lisp errors are now avoided for certain @(':')@(tsee rewrite) rules:
 those whose @(see equivalence) relation is other than @('equal') when the rule
 is originally processed, but is no longer a known equivalence relation when
 the rule is to be stored.  Thanks to Jared Davis for sending a useful example,
 a minor variant of which is included in a comment in source function
 @('interpret-term-as-rewrite-rule') (file @('defthm.lisp')).</p>

 <p>Fixed a bug in the ACL2 evaluator (source function @('raw-ev-fncall')),
 which was unlikely to be exhibited in practice.</p>

 <p>Fixed a hard Lisp error that could occur for ill-formed @(':')@(tsee meta)
 @(see rule-classes), e.g., @('(:meta :trigger-fns '(foo))').</p>

 <p>It is now an error to include a @(see stobj) name in the @(':renaming')
 alist (see @(see defstobj)).</p>

 <p>Some bogus warnings about non-recursive function symbols have been
 eliminated for rules of class @(':')@(tsee type-prescription).</p>

 <p>(Allegro CL host Lisp only) Fixed an obsolete setting of compiler variable
 @('comp:declared-fixnums-remain-fixnums-switch'), which may have been
 responsible for intermittent (and infrequent) checksum errors encountered
 while including books during certification of the regression suite.</p>

 <p>Fixed a @(see proof-builder) bug that could result in duplicate goal names
 in the case of forced hypotheses.  An example showing this bug, before the
 fix, appears in a comment in the ACL2 sources, in @('(deflabel note-5-0
 ...)').</p>

 <p>We fixed a bug in a prover routine involved in @(see type-set) computations
 involving linear arithmetic.  This bug has been around since at least as far
 back as Version_3.3 (released November, 2007).  We are not aware of any
 resulting unsoundness, though it did have the potential to weaken the prover.
 For example, the following is proved now, but was not proved before the bug
 was fixed.</p>

 @({
  (thm
   (implies (and (rationalp x)
                 (rationalp y)
                 (integerp (+ (* 1/3 y) x)))
            (integerp (+ y (* 3 x))))
   :hints ((\"Goal\" :in-theory (disable commutativity-of-+))))
 })

 <p>Although all bets are off when using redefinition (see @(see
 ld-redefinition-action)), we wish to minimize negative effects of its use,
 especially raw Lisp errors.  The examples below had caused raw Lisp errors,
 but no longer.</p>

 @({
  (defstobj st fld :inline t)
  (redef!)
  (defstobj st new0 fld)
  (u)
  (fld st) ; previously an error, which is now fixed

  ; Fresh ACL2 session:
  (redef!)
  (defun foo (x) x)
  (defmacro foo (x) `(quote ,x))
  (u)

  ; Fresh ACL2 session:
  (redef!)
  (defmacro foo (x) (cons 'list x))
  (defun foo (x) x)
 })

 <p>Fixed a bug that could cause hard Lisp errors in an @(tsee encapsulate)
 event.  Thanks to Sol Swords for sending an example that exhibited this bug.
 Here is a simpler such example; the bug was in how it was checked whether the
 @(see guard) for a guard-verified function (here, @('g')) depends on some
 function introduced in the @(see signature) of the @(tsee encapsulate) (here,
 the function @('f')).</p>

 @({
  (encapsulate
   ((f (x) t))
   (local (defun f (x) (declare (xargs :guard t)) x))
   (defun g (x)
     (declare (xargs :guard (if (integerp x) (f x) t)))
     x))
 })

 <p>Fixed a bug in @('mfc-relieve-hyp') that we believe could prohibit its use
 on the last hypothesis.  Thanks to Sol Swords for reporting this bug and
 providing a fix.</p>

 <p>The syntax @('#!') (see @(see sharp-bang-reader)) was broken after a
 skipped readtime conditional.  For example, the following input line caused an
 error.</p>

 @({
  #+skip #!acl2(quote 3)
 })

 <p>This bug has been fixed.</p>

 <p>Fixed a bug in the @(see break-rewrite) utility, which was evidenced by
 error messages that could occur when dealing with free variables.  An example
 of such an error message is the following; we thank Robert Krug for sending us
 an example that produced this error and enabled us to produce a fix.</p>

 @({
  HARD ACL2 ERROR in TILDE-@-FAILURE-REASON-PHRASE1:  Unrecognized failure
  reason, ((MEM-ARRAY . X86) (ADDR QUOTE 9)).
 })

 <p>We fixed an obscure bug that we believe could interfere with @(tsee
 defproxy) because of an incorrect @('(declaim (notinline <function>))')
 form.</p>

 <p><b>CHANGES AT THE SYSTEM LEVEL AND TO DISTRIBUTED BOOKS</b></p>

 <p>Improvements have been made related to the reading of characters.  In
 particular, checks are now done for ASCII encoding and for the expected @(tsee
 char-code) values for @('Space'), @('Tab'), @('Newline'), @('Page'), and
 @('Rubout').  Also, an error no longer occurs with certain uses of
 non-standard characters.  For example, it had caused an error to certify a
 book after a single @(see portcullis) @(see command) of @('(make-event
 `(defconst *my-null* ,(code-char 0)))'); but this is no longer an issue.
 Thanks to Jared Davis for helpful correspondence that led us to make these
 improvements.</p>

 <p>The character encoding for reading from files has been fixed at iso-8859-1.
 See @(see character-encoding).  Thanks to Jared Davis for bringing this
 portability issue to our attention (as this change arose in order to deal with
 a change in the default character encoding for the host Lisp, CCL), and
 pointing us in the right direction for dealing with it.  In many cases, the
 character encoding for reading from the terminal is also iso-8859-1; but this
 is not guaranteed.  In particular, when the host Lisp is SBCL this may not be
 the case.</p>

 <p>Although the HTML documentation is distributed with ACL2, it had not been
 possible for users to build that documentation without omitting graphics, for
 example on the ACL2 home page.  That has been fixed, as files
 @('graphics/*.gif') are now distributed.</p>

 <p>Compiler warnings are suppressed more completely than they had been before.
 For example, the following had produced a compiler warning when the host Lisp
 is CCL, but no longer does so.</p>

 @({
  (defun f () (car 3))
  (trace$ f)
 })

 <p>Removed support for ``tainted'' @(see certificate)s.  One reason is that
 there are rarely incremental releases.  A stronger reason is that for the
 compatibility of a new release is with the previous non-incremental release,
 it's not particularly relevant whether or not the new release is
 incremental.</p>

 <p>The `make' variable @('BOOKS') can now be defined above the line that
 includes Makefile-generic.  (For relevant background, see @(see
 books-certification-classic).)</p>

 <p>(SBCL only) ACL2 images built on SBCL now have an option,
 @('--dynamic-space-size 2000'), that can avoid space problems that could
 previously have caused the session to die.</p>

 <p>The default value for variable @('LISP') in file @('GNUmakefile') is now
 @('ccl').  Thus, if you use `make' in the standard way to build an ACL2
 executable, the default host Lisp is @('ccl') rather than @('gcl').</p>

 <p><b>EMACS SUPPORT</b></p>

 <p><b>EXPERIMENTAL VERSIONS</b></p>

 <p>For the version supporting the reals, ACL2(r) (see @(see real)), the
 supporting function @('floor1') has been defined in raw Lisp.  This avoids an
 error such as in the following case.</p>

 @({
  (defun f () (declare (xargs :guard t)) (floor1 8/3))
  (f) ; had caused raw Lisp error, before the fix
 })

 <p>Among the enhancements for the parallel version, ACL2(p) (see @(see
 parallelism)), are the following.  We thank David Rager for his work in
 developing ACL2(p) and these improvements in particular.</p>

 <blockquote>

 <p>The macro @('set-parallel-evaluation') has been renamed @(tsee
 set-parallel-execution).</p>

 <p>Calls of the macro @(tsee set-waterfall-printing) are no longer @(see
 events), so may not be placed at the top level of @(see books).  However, it
 is easy to create events that have these effects; see @(see
 set-waterfall-printing).  Note that now, @(':')@(tsee ubt) and similar
 commands do not change the settings for either waterfall-parallelism or
 waterfall-printing.</p>

 <p>The implementation of @(tsee deflock) has been improved.  Now, the macro it
 defines can provide a lock when invoked inside a @(see guard)-verified or
 @(':')@(tsee program) mode function.  Previously, this was only the case if
 the function definition was loaded from raw Lisp, typically via a compiled
 file.</p>

 <p>The underlying implementation for waterfall parallelism (see @(see
 set-waterfall-parallelism)) has been improved.  As a result, even the largest
 proofs in the regression suite can be run efficiently in @(':resource-based')
 waterfall parallelism mode.  Among these improvements is one that can prevent
 machines from rebooting because operating system limits have been exceeded;
 thanks to Robert Krug for bringing this issue to our attention.</p>

 <p>There is also a new flag for configuring the way waterfall parallelism
 behaves once underlying system resource limits are reached.  This flag is most
 relevant to @(':full') waterfall parallelism.  see @(see
 set-total-parallelism-work-limit) for more information.</p>

 <p>The @(tsee dmr) utility has the same behavior in ACL2(p) as it has in ACL2
 unless waterfall-parallelism has been set to a non-@('nil') value (see @(see
 set-waterfall-parallelism)), in which case statistics about parallel execution
 are printed instead of the usual information.</p>

 <p>The user can now build the regression suite using waterfall @(see
 parallelism).  See the distributed file @('acl2-customization-files/README')
 for details, and see @(see unsupported-waterfall-parallelism-features) for a
 disclaimer related to building the regression suite using waterfall
 parallelism.</p>

 <p>When building ACL2 with both the hons and parallelism extensions (what is
 called ``ACL2(p)'' or, equivalently, ``ACL2(hp)''), the functions that are
 automatically memoized by the hons extension are now automatically unmemoized
 and memoized when the user toggles waterfall parallelism on and off,
 respectively.</p>

 <p>Calling @(tsee set-waterfall-parallelism) with a flag of @('t') now results
 in the same settings as if it were called with a flag of @(':resource-based'),
 which is now the recommended mode for waterfall parallelism.  Thanks to Shilpi
 Goel for requesting this feature.</p>

 <p>The prover now aborts in a timely way in response to interrupts issued
 during a proof with waterfall parallelism enabled.  (This had often not been
 the case.)  Thanks to Shilpi Goel for requesting this
 improvement.</p></blockquote>

 <p>Among the enhancements for the HONS extension (see @(see
 hons-and-memoization)) are the following.</p>

 <blockquote>

 <p>The compact-print code has been replaced by new serialization routines
 contributed by Jared Davis.  This may improve performance when including books
 that contain @(tsee make-event)s that expand to very large constants.  You can
 also now save objects to disk without going into raw lisp; see @(see
 serialize) for details.</p>

 <p>Printing of certain messages has been sped up (by using Lisp function
 @('force-output') in place of @('finish-output')).  Thanks to Jared Davis for
 contributing this improvement.</p>

 <p>@(see Stobj) array writes are perhaps twice as fast.</p>

 <p>It is now permitted to @(see memoize) functions that take user-defined
 @(see stobj)s as inputs, provided that no @(see stobj)s are returned.  Even if
 stobjs are returned, memoization is permitted provided the condition is
 @('nil'), as when profiling (see @(see profile)).  Thanks to Sol Swords for an
 observation that led to this improvement and for useful conversations,
 including follow-up leading us to improve our initial implementation.</p>

 <p>Fixes have been made for memoizing with a non-@('nil') value of
 @(':ideal-okp').  Errors had occurred when memoizing with a @(':condition')
 other than @('t') for a @(':')@(tsee logic) mode function that had not been
 @(see guard)-verified, even with a non-@('nil') value of @(':ideal-okp'); and
 after successfully memoizing such a function (without such @(':condition')),
 it had not been possible to @(tsee unmemoize) it.  Thanks to Sol Swords for
 reporting issues with the @(':ideal-okp') argument of @(tsee memoize).</p>

 <p>If a book defined a function that was subsequently @(see memoize)d in that
 book, the function would no longer behaves as memoized upon completion of book
 certification (unless that @(tsee certify-book) command was undone and
 replaced by evaluation of a corresponding @(tsee include-book) command).  This
 has been fixed.  Thanks to David Rager for pointing out the problem by sending
 an example.</p>

 <p>We now support ACL2(h) built not only on 64-bit CCL but also on all
 supported host Ansi Common Lisps (i.e., all supported host Lisps except GCL).
 Thanks to Jared Davis for doing much of the work to make this improvement.
 Note that performance will likely be best for 64-bit CCL; for some Lisps,
 performance may be much worse, probably depending in part on the underlying
 implementation of hash tables.</p></blockquote>")

(defxdoc note-6-0

; Total number of release note items: 53.

; Added analogues simple-translate-and-eval-error-double and
; simple-translate-and-eval-cmp of simple-translate-and-eval, which instead of
; (mv erp val state) return (mv erp val) and a context-message pair,
; respectively.  Note that error output is never inhibited for these functions
; as implemented.

; Two new functions, which are rarely if ever called by users, have been made
; untouchable: stobj-evisceration-alist and trace-evisceration-alist.  Before
; this change, (trace-evisceration-alist state) and (stobj-evisceration-alist
; nil state) could return non-ACL2 objects, and the former even caused a hard
; Lisp error when a user stobj had previously been introduced.

; Fixed an error message that was complaining about redefinition of a function
; previously defined at the top level, or at the top level of a book, when the
; function was actually built into ACL2.  For example:
;
; ; old:
; ACL2 !>(defun rewrite (x) x)
; ....
; Note: REWRITE was previously defined at the top level.
;
; ; new:
; ACL2 !>(defun rewrite (x) x)
; ....
; Note: REWRITE has already been defined as a system name; that is, it
; is built into ACL2.

; Fixed bugs in case-match calls: final branch cased on t instead of &.  The
; functions were translate-rule-class-alist and bdd-clause1; the former could
; be exploited to get a misleading error message, but that's all, while we
; didn't investigate the consequences of the bdd-clause1 bug.

; The defrec utility now defines a recognizer with guard t.  An optional
; argument specifies the name of the recognizer, which by default for (defrec
; foo ...) is the symbol WEAK-FOO-P, in the same package as foo.

; Among the lower-level changes made in support of meta-extract hypotheses are
; the following:

;   If x is an atom then (sublis-var1-lst alist x) is x; formerly it was nil.
;   This change was originally made to support meta-extract hypotheses, but
;   probably is no longer necessary.  Still, it seems like a good change, since
;   it "almost" allows us to prove that (sublis-var nil x) = x -- "almost"
;   because this is only true when x is in quote-normal form.

;   Some mfc-xx functions now have implicit constraints because of
;   meta-extract-contextual-fact, so *unattachable-primitives* has been
;   extended accordingly.

;   The Essay on Correctness of Meta Reasoning has been substantially
;   extended.

; The definition of constraint-info has changed very slightly in order to make
; it easier to make :common-lisp-compliant (as required in order to make
; meta-extract-formula :common-lisp-compliant).  The main change is that some
; zero-ary function constraints might not be in quote-normal form, though that
; actually seems impossible since the changes away from cons-term would only be
; relevant for executable zero-ary primitives, of which there are none!

; We eliminated the nonlinearp condition in add-polys1.  For details, see the
; comment there about this change.

; The file doc/texinfo.tex has been removed, the result being that if one
; builds one's own Postscript version of the documentation, then the look will
; quite possibly be somewhat different than it was previously.

; Here is an example from Sol Swords, as promised in the item below about a
; soundness bug in defabsstobj based on guards.

;   (defstobj my-stobj-impl (my-fld :type (integer 0 *) :initially 0))
;
;   (trace$ len)
;
;   (defun bad-accessor-logic (my-stobj-logic)
;      (declare (xargs :guard (equal (len my-stobj-logic) 0)))
;      (mbe :logic 0
;           :exec (len my-stobj-logic)))
;
;   (defun bad-accessor-exec (my-stobj-impl)
;      (declare (xargs :stobjs my-stobj-impl)
;               (ignorable my-stobj-impl))
;      1)
;
;   (defun create-my-stobj-logic ()
;      (declare (xargs :guard t))
;      (list 0))
;
;   (defun my-stobj-logicp (x)
;      (declare (xargs :guard t))
;      (AND (TRUE-LISTP X)
;           (= (LENGTH X) 1)
;           (MY-FLDP (NTH 0 X))))
;
;   (defun-nx my-stobj-corr (my-stobj-i my-stobj-l)
;      (and (my-stobj-implp my-stobj-i)
;           (equal my-stobj-i my-stobj-l)))
;
;   (DEFTHM CREATE-MY-STOBJ-ABS{CORRESPONDENCE}
;            (MY-STOBJ-CORR (CREATE-MY-STOBJ-IMPL)
;                           (CREATE-MY-STOBJ-LOGIC))
;            ;; added by Matt K.:
;            :hints (("Goal" :in-theory (disable (my-stobj-corr)))))
;
;   (DEFTHM CREATE-MY-STOBJ-ABS{PRESERVED}
;            (MY-STOBJ-LOGICP (CREATE-MY-STOBJ-LOGIC)))
;
;   (DEFTHM BAD-ACCESSOR{CORRESPONDENCE}
;            (IMPLIES (AND (MY-STOBJ-CORR MY-STOBJ-IMPL MY-STOBJ-ABS)
;                          (EQUAL (LEN MY-STOBJ-ABS) 0))
;                     (EQUAL (BAD-ACCESSOR-EXEC MY-STOBJ-IMPL)
;                            (BAD-ACCESSOR-LOGIC MY-STOBJ-ABS))))
;
;   (defabsstobj my-stobj-abs
;      :concrete my-stobj-impl
;      :recognizer (my-stobj-absp :logic my-stobj-logicp :exec my-stobj-implp)
;      :creator (create-my-stobj-abs :logic create-my-stobj-logic :exec
;                                    create-my-stobj-impl)
;      :corr-fn my-stobj-corr
;      :exports ((bad-accessor :logic bad-accessor-logic :exec bad-accessor-exec)))
;
;   ; Test added by Matt K.:
;   (bad-accessor my-stobj-abs) ; note trace of len here: (LEN |<my-stobj-abs>|)
;
;   (defun length-of-my-stobj-abs ()
;      (declare (xargs :guard t))
;      (with-local-stobj my-stobj-abs
;        (mv-let (len my-stobj-abs)
;          (let ((len (ec-call (bad-accessor my-stobj-abs))))
;            (mv len my-stobj-abs))
;          len)
;        create-my-stobj-abs))
;
;   (defthm length-of-my-stobj-abs-by-def
;      (equal (length-of-my-stobj-abs) 0)
;      :hints(("Goal" :in-theory (disable (length-of-my-stobj-abs))))
;      :rule-classes nil)
;
;   (defthm length-of-my-stobj-abs-by-exec
;      (equal (length-of-my-stobj-abs) 1))

; Replaced "data base" and "data-base" by "database".

; The following change supports certification of books/centaur/ books in ACL2,
; not just ACL2(h).  In order to eliminate errors upon reference to
; *never-profile-ht* in raw Lisp code such as is found in
; books/centaur/vl/util/print-htmlencode.lisp, *never-profile-ht* is now
; defined in ACL2.

; Changed equal to eq in the body of the definition of pos-listp.

; Fixed a typo (":type-prescription", in chk-acceptable-type-prescription-rule)
; that could have affected warnings printed when :type-prescription rules are
; submitted.

; Modified the definition of mbe to use ignorable.  Some Lisps might warn, but
; they probably warned before.  With this change, CCL svn rev 15527 doesn't
; warn.

; Modified the layout of the history-entry record so that it's not dependent on
; #+acl2-par, and hence its generated macros are the same for ACL2 and
; ACL2(p).  As a consequence, made a few related changes.

  :parents (release-notes)
  :short "ACL2 Version  6.0 (December, 2012) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 5.0 into the following
 categories of changes: existing features, new features, heuristic
 improvements, bug fixes, changes at the system level, Emacs support, and
 experimental versions.  Each change is described in just one category, though
 of course many changes could be placed in more than one category.</p>

 <p>NOTE.  But we start with one major change that is outside the usual
 categories:</p>

 <p><b>LICENSE change</b></p>

 <p>The ACL2 license has been changed from GPL Version 2 to a 3-clause BSD
 license, found in the @('LICENSE') file distributed with ACL2.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>Function @(tsee fmt-to-string) and similar functions (see @(see
 printing-to-strings)) now use the default right margin settings; formerly the
 right margin had been set at 10,000.  If you want the former behavior, you can
 use the @(':fmt-control-alist'), as illustrated below.</p>

 @({
  (fmt-to-string \"~x0\"
                 (list (cons #\\0 (make-list 30)))
                 :fmt-control-alist
                 `((fmt-soft-right-margin . 10000)
                   (fmt-hard-right-margin . 10000)))
 })

 <p>The use of attachments (see @(see defattach)) has been made more efficient,
 avoiding some low-level checks (Common Lisp `@('boundp')' checks).  Thanks to
 Shilpi Goel for constructing an example that we used to help direct us to
 remove inefficiency.  The following results for that example &mdash; a
 Fibonacci program run on a machine interpreter in raw-mode (see @(see
 set-raw-mode)) &mdash; give a sense of the potential speedup, though we note
 that a full ACL2(h) regression showed no significant speedup.</p>

 @({
  ; Time before the change:
  ; 0.89 seconds realtime, 0.90 seconds runtime

  ; Time after the change:
  ; 0.75 seconds realtime, 0.75 seconds runtime

  ; Time when cheating to avoid the cost of attachments, by redefining a
  ; function to BE its attachment (so, this gives a lower bound on possible
  ; execution time):
  ; 0.72 seconds realtime, 0.72 seconds runtime
 })

 <p>Functions @('read-acl2-oracle') and @('read-acl2-oracle@par') are no longer
 untouchable (see @(see remove-untouchable)).  We reported this change for
 Version_5.0 but it was not made; thanks to Jared Davis for bringing this to
 our attention.  Function @('get-timer') also is no longer untouchable.</p>

 <p>The function @(tsee butlast) now behaves more reasonably on arguments
 violating its @(see guard).  For example, @('(butlast '(1 2 3) -1)') is now
 provably equal to @('(1 2 3)') instead of to @('(1 2 3 nil)').  Thanks to
 Jared Davis for suggesting a change to the definition of @('butlast').</p>

 <p>The utilities @('mfc-ts') and @('mfc-ap') (see @(see
 extended-metafunctions)) formerly never used forcing (see @(see force)).  Now,
 by default, forcing is allowed during execution of these functions if and only
 if it is permitted in the rewriting environment where they are called.
 Moreover, these and the @('mfc-xx') utilities &mdash; @('mfc-rw'),
 @('mfc-rw+'), and @('mfc-relieve-hyp') &mdash; are now macros that take
 (optional) keyword arguments @(':forcep') and @(':ttreep').  The @(':forcep')
 argument is @(':same') by default, providing the forcing behavior inherited
 from the environment (as described above); but it can be the symbol @('t') or
 @('nil'), indicating that forcing is to be enabled or disabled, respectively.
 The @(':ttree') argument is @('nil') by default, but when it is @('t'), then a
 second value is returned, which is a tag-tree.  See @(see
 extended-metafunctions).</p>

 <p>Many improvements have been made to the tau-system (see @(see tau-system)),
 including support for arithmetic intervals bounded by constants.  Thus, for
 example, @('(and (<= 0 x) (<= x 15))') is a tau predicate.  The @(see
 documentation) has also been improved (see @(see
 introduction-to-the-tau-system)). Also see @(see time-tracker-tau) for
 discussion of how the new @(tsee time-tracker) utility can help discover ways
 to detect slowdown related to the tau-system.</p>

 <p>The @(tsee defthm) @(see events) printed by @(tsee defabsstobj), namely
 those that remain to be proved, are now given with @(':rule-classes nil')
 since there is probably no intention to use them as rules.  Thanks to Robert
 Krug for suggesting that we consider this change.</p>

 <p>The formal parameters for a macro definition (see @(see defmacro)) may now
 include @(tsee state) and user-defined @(tsee stobj)s.  (However, macro
 formals may not be declared as stobjs; see @(see xargs).)  Thanks to Jose Luis
 Ruiz-Reina for raising this issue and to Rob Sumners for helpful conversations
 &mdash; both of these nearly 10 years ago!</p>

 <p>The utilities @(tsee defun-inline), @(tsee defun-notinline), @(tsee
 defund-inline), and @(tsee defund-notinline) have been simplified, by taking
 advantage of the lifting of restrictions on formal parameters of macro
 definitions mentioned above (involving symbols that happen to be @(see stobj)
 names).  Now, when any of the above four utilities is called with a given set
 of formal parameters, those formals will be used not only for the generated
 @(tsee defun) event but also for the generated @(tsee defmacro) event.
 (Previously, they had been renamed for the @(tsee defmacro) event in order to
 respect the stobj name restriction that no longer exists.)  Thanks to Jared
 Davis for pointing out the value of making this change.</p>

 <p>The @(see events) @(tsee add-invisible-fns) and @(tsee
 remove-invisible-fns) now convert arguments as appropriate using the @(tsee
 macro-aliases-table).  For example, the event @('(add-invisible-fns append
 car)') is now legal (though probably not a good idea), because
 @('add-invisible-fns') is now sensitive to the fact that @(tsee append) maps
 to @(tsee binary-append) in the @(tsee macro-aliases-table).</p>

 <p>When @(':')@('pe') is applied to a built-in function that does not have a
 defining event, such as @(tsee symbolp), @(':pe') now gives more useful output
 that points to the documentation instead of printing a call of
 @('ENTER-BOOT-STRAP-MODE').  Thanks to Anthony Knape for bringing this issue
 to our attention.</p>

 <p>The macros @(tsee memoize) and @(tsee unmemoize) now cause a warning rather
 than an error in ACL2 (and work as before in ACL2(h)).</p>

 <p>Terms are now parsed into @(':')@(tsee type-prescription) rules in a manner
 that removes @(tsee let) bindings both at the top level and in the conclusion
 (but still not in the hypotheses of the rule).  See @(see type-prescription).
 Thanks to Jared Davis for requesting such an enhancement.</p>

 <p>Printing of numbers is now appropriately sensitive to the print radix; see
 @(see set-print-radix).  Thanks to Shilpi Goel for requesting this
 enhancement.</p>

 <p>The system function @('explode-atom') no longer includes the radix
 indicator.  The new function @('explode-atom+') may be used for that
 purpose.</p>

 <p><b>NEW FEATURES</b></p>

 <p>Among the new features for system hackers are analogues of system function
 @('simple-translate-and-eval') that do not return @(tsee state).  (Thanks to
 David Rager for requesting this feature and helpful conversations on its
 implementation.)  This and other low-level changes are typically documented in
 comments in the corresponding release note event, which in this case is
 @('(deflabel note-6-0 ...)').</p>

 <p>More built-in functions are now @(see guard)-verified (and in @(':')@(tsee
 logic) mode).  Furthermore, a mechanism exists for marking yet more built-in
 functions as guard-verified based on @(see books) contributed by users; see
 Part II of <a
 href='http://www.cs.utexas.edu/users/moore/acl2/open-architecture/'>http://www.cs.utexas.edu/users/moore/acl2/open-architecture/</a>.
 The current state of that enterprise may be viewed by evaluating the constant
 @('*system-verify-guards-alist*'), which associates a community book name with
 a list of functions.  When ACL2 is built in the normal way, each of those
 functions is marked as guard-verified when ACL2 is started up; but a special
 developer build can be used to check that the indicated book, together with
 its sub-books, proves that those functions are guard-verified.</p>

 <p>Metatheorems (see @(see meta)) may now have additional hypotheses, called
 ``meta-extract hypotheses'', that allow metafunctions to depend on the
 validity of certain terms extracted from the context or the logical @(see
 world).  See @(see meta-extract).  Thanks to Sol Swords for providing an
 initial implementation, together with very helpful discussions as well as a
 community book, @('books/clause-processors/meta-extract-user.lisp'), that
 extends the power of meta-extract hypotheses.</p>

 <p>New utilities @('oracle-funcall'), @('oracle-apply'), and
 @('oracle-apply-raw') call a function argument on specified arguments.  Thanks
 to Jared Davis for requesting this utility.</p>

 <p>A new utility makes it convenient to track time spent inside specified
 function calls or, more generally, during specified evaluation.  See @(see
 time-tracker).</p>

 <p>New runic designators make it easy to refer to macro names when building
 theories.  Thus, for example, the object @('(:i append)') may be used in
 theory expressions to designate the @(see rune) @('(:induction
 binary-append)').  See @(see theories).  Thanks to Jared Davis for a useful
 discussion leading to this enhancement.</p>

 <p>@(tsee Defabsstobj) @(see events) now take an optional @(':congruent-to')
 keyword argument, much like @(tsee defstobj).  Thanks to Sol Swords for
 requesting this feature and for suggesting a very nice optimization that
 avoids the need to prove additional lemmas.</p>

 <p>@(tsee Flet) may now include @('inline') and @('notinline') declarations.
 Thanks to Jared Davis for requesting this feature.</p>

 <p>The utility @('gc-verbose') controls printing of messages by the garbage
 collector, for certain host Lisps.  See @(see gc-verbose).  Thanks to Shilpi
 Goel for requesting this utility.</p>

 <p>Added definitions of functions @(tsee nat-listp) and @(tsee
 acl2-number-listp).  Thanks to Harsh Raju Chamarthi for requesting these
 additions.  Many community books had varying definitions of these functions;
 these additions guarantee that all books must agree on how these two functions
 are defined.  (Some community books have been changed in order that they
 remain certifiable, given these additions.)  Note that a few built-in
 @(':')@(tsee forward-chaining) rules were modified in order to accommodate
 these additions, and the definition of @(tsee integer-listp) was modified to
 call @(tsee eq) instead of @(tsee equal), like the other such definitions.</p>

 <p>See @(see get-command-sequence) for a new utility that returns a list of
 @(see command)s between two given command descriptors.</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>We obtained a substantial speedup &mdash; 13% observed for the regression
 suite, and 8% observed for the ACL2(h) regression suite &mdash; by tweaking
 the @(see break-rewrite) implementation to eliminate virtually all of its
 overhead when it is not in use (the default, which holds until @(':')@(tsee
 brr)@(' t') is evaluated).  Thanks to David Rager for a conversation involving
 ACL2(p) performance statistics that suggested looking at changing @(see
 break-rewrite) to boost performance.</p>

 <p>The heuristics for automatically expanding recursive function calls have
 been changed during proofs by induction.  Now, during induction, more terms
 that suggested the induction scheme are automatically expanded.  Thanks to
 David Rager for providing an example and having discussions with us that
 spurred us to develop this heuristic improvement.</p>

 <p><b>BUG FIXES</b></p>

 <p>Fixed a soundness bug in @(tsee defabsstobj) based on @(tsee guard)s that
 violated single-threadedness restrictions.  Thanks to Sol Swords for bringing
 this bug to our attention and supplying a proof of @('nil'), which we include
 as a comment in source file @('ld.lisp'), in @('(deflabel note-6-0 ...)').  We
 also thank Sol for helpful discussions about @(see guard)s of functions
 introduced by @('defabsstobj'), which has led us to enhance the @(see
 documentation); see @(see defabsstobj).</p>

 <p>Fixed a soundness bug in @(tsee defabsstobj) based on interrupted updates
 of abstract stobjs.  As part of the fix a new keyword, @(':PROTECT'), has been
 introduced for @('defabsstobj') exports, along with a new top-level
 @('defabsstobj') keyword, @(':PROTECT-DEFAULT'); see @(see defabsstobj).  We
 do some analysis that we expect will avoid the use of @(':PROTECT') in many
 cases, which is fortunate since the use of @(':PROTECT t') may cause a slight
 slowdown in (abstract) stobj updates.  Thanks to Sol Swords for bringing this
 bug to our attention and supplying a proof of @('nil'), which we include as a
 comment in source file @('other-events.lisp'), in the definition of function
 @('set-absstobj-debug').</p>

 <p>Fixed a raw Lisp error that occurred when tracing a <i>stobj</i> resize
 function, thanks to an error report from Warren Hunt, Marijn Heule, and Nathan
 Wetzler.</p>

 <p>Fixed a raw Lisp error that occurred for certain ill-formed signatures, as
 in the following example.</p>

 @({
  ACL2 !>(encapsulate
             (((f (*) => * :guard t)))
             (local (defun f (x) (consp x))))

  ***********************************************
  ************ ABORTING from raw Lisp ***********
  Error:  value (F (*) => * :GUARD T) is not of the expected type SYMBOL.
  ***********************************************
 })

 <p>The notion of ``error triple'' (see @(see error-triple)) had been
 implemented ambiguously, with the result that for a @(see stobj), @('st'), the
 result of evaluating the following two forms was the same: @('(mv nil st
 state)') and @('(mv t st state)').  Of course, these are just examples; in
 general, a result of @('(mv erp val state)') was sometimes treated as an error
 triple even when @('val') is a @(see stobj).  Now, @('(mv erp val state)') is
 an error triple only when @('erp') and @('val') are ordinary (non-@(see
 stobj)) values.  Thanks to Warren Hunt and Marijn Heule for bringing this
 problem to our attention.</p>

 <p>The ``with-error-trace'' utility, @(tsee wet), now works in the non-error
 case when given a form that returns multiple values.  (Note however that
 @(tsee STATE) will be printed as @('REPLACED-STATE'); and similarly, a
 user-defined @(see stobj), say @('ST'), will be printed as
 @('REPLACED-ST').)</p>

 <p>Some possible error messages for @(tsee defabsstobj) have been fixed that
 had been ill-formed.  Thanks to Sol Swords for bringing this bug to our
 attention.</p>

 <p>Fixed a bug that sometimes caused the times displayed in the summary for
 @(tsee certify-book) to be smaller than the actual times.</p>

 <p>Fixed a bug in the @(see guard)s to system functions @('fmt-char') and
 @('fmt-var'), which are no longer @(':')@(tsee logic)-mode, guard-verified
 functions.</p>

 <p>(GCL only) Fixed a bug present in Gnu Common Lisp for @('#u') (see @(see
 sharp-u-reader)).</p>

 <p><b>CHANGES AT THE SYSTEM LEVEL</b></p>

 <p>The @(see state) global variable @(''distributed-books-dir') has been
 renamed @(''system-books-dir').  On a related note, the @(see documentation)
 now refers to ``community books'' rather than ``distributed books'', and there
 is a corresponding new documentation topic; see @(see community-books).</p>

 <p>Fixed a bug in the implementation of @(tsee wet) (which is actually in the
 community book @('books/misc/wet.lisp')).</p>

 <p>A directory, @('interface/'), is no longer part of the ACL2 distribution.
 Rather, it is a subdirectory of the ACL2 community books.  Thus, if you fetch
 those books in the usual way (see the installation instructions on the ACL2
 home page), you will find a directory @('books/interface/').  Subdirectory
 @('emacs/') of that @('interface') directory provides Emacs support for @(see
 proof-tree)s as well an @('acl2-mode').  This change has been reflected in
 ACL2 file @('emacs/emacs-acl2.el'), so users will probably not be impacted if
 they load that file into Emacs.</p>

 <p>The community books file @('books/Makefile-generic') now causes, by
 default, a backtrace to be printed when there is a raw Lisp error.</p>

 <p>Some changes have been made to how regressions are run, i.e., to how the
 community books are certified.  (1) The standard regression now includes
 community books directory @('books/centaur').  To skip these (for example, a
 Windows system has encountered difficulty with them even after installing
 Perl), include @('ACL2_CENTAUR=skip') with your `make' command.  (2) A new
 `make' (or environment) variable, @('ACL2_JOBS'), specifies the number of
 parallel jobs to run, serving as a replacement for the @('-j') argument of
 `make' that works for all community books, including those under directory
 @('centaur'); see @(see books-certification-classic).  (3) It is no longer
 necessary to do an ACL2(h) regression in order to build a copy of the
 documentation generated by Jared Davis's xdoc utility at
 @('books/xdoc-impl/manual/preview.html'); a vanilla ACL2 regression will build
 this manual.  (4) It is no longer necessary to set the @('ACL2') environment
 variable for ACL2(h) regressions if you want to use the executable
 @('saved_acl2h') in the ACL2 sources directory.</p>

 <p>The ACL2 home page now has a search utility for documentation and books.
 Thanks to Shilpi Goel and David Rager for feedback on a preliminary version of
 this utility.</p>

 <p>(only for SBCL with 64-bit ACL2(h)) The value of SBCL command line option
 @('--dynamic-space-size') for ACL2(h) on 64-bit platforms has been increased
 from 2000 to 16000 (as explained in a comment in the ACL2 source definition of
 @('*sbcl-dynamic-space-size*')).</p>

 <p><b>EMACS SUPPORT</b></p>

 <p><b>EXPERIMENTAL/ALTERNATE VERSIONS</b></p>

 <p>Among the enhancements for ACL2(r) (see @(see real)) are the following.</p>

 <blockquote>

 <p>Thanks to Ruben Gamboa for his helpful role in making the following
 improvements made with Ruben Gamboa in support for non-standard analysis in
 ACL2(r).</p>

 <p>Constrained functions can now be introduce as non-classical.  See @(see
 signature).</p>

 <p>@(tsee Defun-sk) now takes a new keyword argument, @(':CLASSICALP'), that
 determines whether or not the named function is classical.  See @(see
 defun-sk).</p>

 <p>Incorporated a bug fix from Ruben Gamboa for @(tsee ceiling).  The default
 (for `bad' arguments) had been 1, but now we follow normal ACL2 practice by
 returning 0 in that case.</p></blockquote>

 <p>Among the enhancements for the HONS extension (see @(see
 hons-and-memoization)) are the following.</p>

 <blockquote>

 <p>Macros @(tsee with-fast-alist), @(tsee with-stolen-alist), and @(tsee
 fast-alist-free-on-exit) are now defined in ACL2(h), rather than being defined
 in the community book @('\"books/centaur/misc/hons-extra.lisp\"').  Thanks to
 Jared Davis and Sol Swords for donating this code, and thanks to Jared for
 helpful discussions leading to this change.</p></blockquote>

 <p>Among the enhancements for ACL2(p) (see @(see parallelism)) are the
 following.  We thank David Rager for his work in developing ACL2(p) and for
 his helpful role in these improvements.</p>

 <blockquote>

 <p>A bug has been fixed that could leave one in a @(see wormhole), awaiting
 input, after an error, such as an error in an @(':in-theory') hint during a
 proof.  Thanks to Shilpi Goel for bringing this bug to our attention.</p>

 <p>A key checkpoint for a given goal is now printed only once.  Previously, if
 a key checkpoint led to more than one goal pushed for proof by induction, the
 key checkpoint would be printed once for each such goal during the proof, and
 also once for each such goal in the summary at the end.</p></blockquote>")

(defxdoc note-6-1

; Total number of release note items: 26.

; As usual, we made a number of improvements to the documentation, based in
; part on useful feedback from users.

; "Theory" warnings about disabling primitives (such as mv-nth) have been made
; much more compact, pointing to a new :doc topic, theories-and-primitives.
; Thanks to David Rager and Jared Davis for helpful discussions leading to this
; change.

; Avoided a bogus call of all-vars in
; defstobj-component-recognizer-axiomatic-defs, and removed a false comment in
; translate-declaration-to-guard that had "justified" this.

; Removed argument value of :raw-lisp for defstobj-template.

; Regarding Expansion/Defstobj Bug (technical remarks followed by example): The
; problem was that the raw Lisp code for defstobj, which is called when loading
; an expansion file, in turn called function defstobj-raw-defs in a world that
; did not include the definition of the `satisfies' predicate, which in turn
; called defstobj-component-recognizer-axiomatic-defs on that world, which in
; turn called translate-declaration-to-guard on that world, which translated
; the `satisfies' type-spec (below) to nil.  Here is the promised example (file
; bug.lisp).

;   ; acl2
;   ; (assign save-expansion-file t)
;   ; (certify-book "bug")
;   ; (quit)
;   ; rm bug.lx64fsl
;   ; acl2
;   ; (include-book "bug")
;   ; (defthm bug
;   ;   nil
;   ;   :hints (("Goal" :use obvious))
;   ;   :rule-classes nil)
;
;   (in-package "ACL2")
;
;   (defun my-natp (x)
;     (declare (xargs :guard t))
;     (natp x))
;
;   (defstobj st1 (fld1 :type (satisfies my-natp) :initially 0))
;
;   (defthm obvious
;     (fld1p 3)
;     :rule-classes nil)
;
;   ; [End of file bug.lisp.]

; Regarding memoize/congruent stobj bug: The following example illustrates the
; bug.  Technical remark: The problem was that the true congruent stobj
; representative was not stored where expected.

;   ; acl2h
;   ; (certify-book "foo")
;   ; (quit)
;   ; acl2h
;   ; (include-book "foo")
;   ; (memoize 'fld3)
;   ; (defthm bug
;   ;   nil
;   ;   :hints (("Goal" :use foo-is-17))
;   ;   :rule-classes nil)
;
;   (in-package "ACL2")
;
;   (defstobj st1 fld1)
;   (defstobj st2 fld2 :congruent-to st1)
;   (defstobj st3 fld3 :congruent-to st2)
;
;   (defun foo ()
;     (with-local-stobj
;      st3
;      (mv-let (result st3)
;              (prog2$ (fld3 st3)
;                      (let ((st3 (update-fld3 17 st3)))
;                        (mv (fld3 st3) st3)))
;              result)))
;
;   (defthm foo-is-17
;     (equal (foo) 17)
;     :rule-classes nil)

; Here is a proof of nil for "a soundness bug involving system function
; canonical-pathname...."  This is a trivial modification (being very slightly
; simpler) of the example sent by Jared Davis and Sol Swords.

;   (in-package "ACL2")
;
;   (defchoose state-for-canonical-pathname (st) ()
;      (not (canonical-pathname nil nil st)))
;
;   (defevaluator ncp-ev ncp-ev-lst ((state-for-canonical-pathname)
;                                     (canonical-pathname a b c)
;                                     (if a b c)
;                                     (equal a b)))
;
;   (defun run-canonical-pathname-cp (clause hints state)
;      (declare (xargs :guard (pseudo-term-listp clause)
;                      :stobjs state)
;               (ignore hints))
;      (mv nil
;          (if (equal clause '((equal (canonical-pathname
;                                      'nil 'nil
;                                      (state-for-canonical-pathname))
;                                     'nil)))
;              (if (canonical-pathname nil nil state)
;                  (list clause)
;                nil)
;            (list clause))
;          state))
;
;   (defthm run-canonical-pathname-cp-correct
;      (implies (and (pseudo-term-listp clause)
;                    (alistp a)
;                    (ncp-ev (conjoin-clauses
;                             (clauses-result
;                              (run-canonical-pathname-cp clause hint state)))
;                            a))
;               (ncp-ev (disjoin clause) a))
;      :hints (("goal" :use ((:instance state-for-canonical-pathname
;                                       (st state)))))
;      :rule-classes :clause-processor)
;
;   (defthm canonical-pathname-is-nil
;      (equal (canonical-pathname
;              'nil 'nil
;              (state-for-canonical-pathname))
;             'nil)
;      :hints (("goal" :clause-processor
;               (run-canonical-pathname-cp clause nil state))))
;
;   (defun foo (x dir-p st)
;      ;; Matches the constraints of canonical-pathname but never returns NIL.
;      (declare (ignore x dir-p st))
;      "hello")
;
;   (defthm foo-never-returns-nil
;      (foo x dir-p st))
;
;   (defchoose state-for-foo (st) ()
;      (not (foo nil nil st)))
;
;   (defthm foo-sometimes-returns-nil
;      (not (foo nil nil (state-for-foo)))
;      :hints (("goal" :use ((:functional-instance
;                             canonical-pathname-is-nil
;                             (canonical-pathname foo)
;                             (state-for-canonical-pathname
;                              state-for-foo))))))
;
;   (defthm contradiction
;      nil
;      :rule-classes nil
;      :hints (("Goal" :use ((:instance foo-sometimes-returns-nil)))))

; Elaborating here on "the functions ~ilc[sys-call] and ~ilc[sys-call-status]
; are now ~il[guard]-verified ~c[:]~ilc[logic]-mode functions": Sys-call-status
; now modifies the oracle, not the file-clock.  It was misguided anyhow to
; expect that modifying the file-clock would provide a coherent story, since
; one might call sys-call to modify the file-system but never call
; sys-call-status to update the file-clock.  Since a trust-tag is necessary in
; order to call sys-call, there is no soundness problem here.  Indeed, :doc
; sys-call is already quite clear on such matters.

; As part of the process of fixing two soundness bugs -- one related to
; canonical-pathname and the other about defaxiom and defattach -- we made a
; number of changes, in particular improving the Essay on Correctness of Meta
; Reasoning and the Essay on Defattach.  In particular, the Essay on Defattach
; now comprehends the use of defaxiom.  Also note that now, as part of fixing
; that first bug, canonical-pathname and mfc-xx functions have been given
; unknown-constraints (by introducing them with dependent clause processors),
; and are no longer in *unattachable-primitives* (as their unattachability is
; enforced by their having unknown-constraints).

; We improved (and slowed down) the algorithm for computing the tau of a term.
; For example it dives into NOT now. The biggest change is that it in
; Version_6.0, preprocess-clause tried tau only before the first simplification
; (when hist=nil) and after the clause was stable under simplification.  The
; new one tries tau more aggressively: before the first three simplifications.
; We found proofs where the more aggressive use of tau -- try after a little
; rewriting got rid of functions the users means to expand -- helped.
;
; Some tests showed that the more aggressive use of tau slows down the
; regression a little compared to the less aggressive use of tau.  But because
; as more tau-based scripts are developed, we expect the more aggressive use of
; tau will pay for itself.
;
; Perhaps more important is the comparison between these two alternatives and
; Version_6.0.  They don't have identical regression suites (of course).  But
; they have 3,075 books in common as of Feb. 2013.  The new .out comparison
; utility can compare total reported book certification time for books in
; common.  Based on that, the less aggressive use of tau was measured at about
; 1% faster than Version_6.0 and the more aggressive use of tau was measured as
; about the same speed as Version_6.0.

; Source function simple-array-type formerly accepted '* as a valid array-etype
; for deducing a type of `(simple-vector *).  But since '* is not a valid
; type-spec, we should never hit this case, so we now cause a hard error in
; order to detect a mistake in that thinking.  Note that we tried evaluating
; (make-array '(5) :element-type *) in several (raw) Lisps, and often got an
; error (though it took two evaluations in CCL to get the error).

  :parents (release-notes)
  :short "ACL2 Version  6.1 (February, 2013) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 6.0 into the following
 categories of changes: existing features, new features, heuristic
 improvements, bug fixes, changes at the system level, Emacs support, and
 experimental versions.  Each change is described in just one category, though
 of course many changes could be placed in more than one category.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>More system functions are in @(':')@(tsee logic) mode, @(see
 guard)-verified.  Evaluate</p>

 @({
  (strip-cars (cdr (assoc-equal \"system/top\" *system-verify-guards-alist*)))
 })

 <p>for the list of functions checked to be guard-verifiable in the community
 books.  Thanks to those who have contributed to this effort, as shown in file
 headers in directory @('system/') of the community books.</p>

 <p>The macro @(tsee defund) now avoids an error when @(':mode :program') has
 been specified in an @(tsee xargs) form of a @(tsee declare) form, for
 example: @('(defund f (x) (declare (xargs :mode :program)) x)').  It does this
 by avoiding the generation of @(tsee in-theory) @(see events) in such cases.
 Thanks to David Rager and Jared Davis for requesting such a change, and for
 ensuing helpful discussions.</p>

 <p>Added a field @(':UNIFY-SUBST') to metafunction contexts (see @(see
 EXTENDED-METAFUNCTIONS)), accessed with function @('mfc-unify-subst').  Thanks
 to Sol Swords for requesting this enhancement.</p>

 <p>The functions @(tsee sys-call) and @(tsee sys-call-status) are now @(see
 guard)-verified @(':')@(tsee logic)-mode functions.</p>

 <p>It had been the case that if any supporter of a dependent clause processor
 (see @(see define-trusted-clause-processor)) is among the ancestors of a given
 formula, then it was illegal to apply functional instantiation (see @(see
 lemma-instance)) to that formula.  Now, this is illegal only if some such
 supporter is in the domain of the functional substitution.</p>

 <p>The tau system (see @(see tau-system), or if you are unfamiliar with the
 tau system, see @(see introduction-to-the-tau-system)) now allows the user to
 define and verify functions that compute bounds on arithmetic expressions.
 See @(see bounders).</p>

 <p>The utility @('print-summary-user') has been replaced by @(tsee
 finalize-event-user), which is described below.  If you previously attached a
 function to @('print-summary-user'), say @('my-print-summary-user'), then you
 can get the effect you had previously as follows.</p>

 @({
  (defun my-finalize-event-user (state)
    (declare (xargs :mode :logic :stobjs state))
    (prog2$ (my-print-summary-user state)
            state))
  (defattach finalize-event-user my-finalize-event-user)
 })

 <p>It had been the case that when you @(tsee LD) a file, the connected book
 directory (see @(see cbd)) was set to the canonical pathname of that file's
 directory for the duration of the @('LD') call.  This could cause problems,
 however, if the file is actually a soft link: an @(tsee include-book) form in
 the book with a relative pathname for the book would be resolved with respect
 to the absolute pathname for that link, which is probably not what was
 intended.  So soft links are no longer followed when computing the above
 connected book directory.  The following example, which is how we discovered
 this problem, may clarify.  We attempted to execute the form @('(ld
 \"top.lisp\")') using ACL2(r) (see @(see real)) in community books directory
 @('nonstd/arithmetic/'), where all of the @('.lisp') files are soft links to
 files in @('arithmetic/').  Thus, the form @('(include-book \"equalities\")')
 attempted to include @('arithmetic/equalities') instead of
 @('nonstd/arithmetic/equalities'), which caused an error.</p>

 <p>We no longer document the use of value @(':START') for @(tsee
 with-prover-step-limit).  This value has always been used by the ACL2
 implementation and may have semantics that change with new ACL2 versions.  If
 you have reason to use this value, please contact the ACL2 implementors.</p>

 <p><b>NEW FEATURES</b></p>

 <p>By default, the prover now gives information about case splits.  See @(see
 splitter).  Thanks to many ACL2 users, most recently David Rager, for
 requesting such a capability.  Also thanks to David Rager and Jared Davis for
 helpful discussions, and thanks to Robert Krug for feedback on the initial
 implementation and documentation that led us to make improvements.</p>

 <p>New utilities @(tsee initialize-event-user) and @(tsee finalize-event-user)
 allow the user to run @(see state)-modifying code at the start and end of
 @(see events).  Thanks to Harsh Raju Chamarthi for requesting these
 capabilities.  Note that @(tsee finalize-event-user) replaces
 @('print-summary-user').</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>Several heuristic improvements have been made to the tau system, even if
 you do not explicitly use the new capability for computing bounds on
 arithmetic expressions, mentioned above.  See @(see tau-system), or if you are
 unfamiliar with the tau system, see @(see introduction-to-the-tau-system).</p>

 <p><b>BUG FIXES</b></p>

 <p>A soundness bug has been fixed that exploited the use of expansion files
 (see @(see book-compiled-file)) together with @(tsee defstobj).  For an
 example illustrating this bug, see the comment about ``Expansion/Defstobj
 Bug'' in the form @('(deflabel note-6-1 ...)') in ACL2 source file
 @('ld.lisp').</p>

 <p>We fixed a soundness bug involving system function @(tsee
 canonical-pathname) and (most likely) other functions in the former value of
 constant @('*unattachable-primitives*').  Thanks to Jared Davis and Sol Swords
 for bringing this bug to our attention by way of an example.  We include a
 very slight variant of that example in a comment within the form @('(deflabel
 note-6-1 ...)') in ACL2 source file @('ld.lisp').</p>

 <p>There was a soundness bug that allowed attachments to prove @('nil') in a
 consistent logical @(see world) involving @(tsee defaxiom) @(see events).
 This has been fixed, by requiring that no function symbol ancestral in a
 @(tsee defaxiom) formula is allowed to get an attachment.  See @(see
 defattach), in particular discussion of ``a restriction based on a notion of a
 function symbol syntactically supporting an event'', which concludes with a
 proof of @('nil') that is no longer possible.</p>

 <p>(ACL2(h) only) We fixed a soundness bug in the interaction of memoization
 with congruent stobjs, in cases where the @(':congruent-to') field of @(tsee
 defstobj) was not the canonical representative in the congruence class.  For
 an example illustrating this bug, see the comment about ``memoize/congruent
 stobj bug'' in the form @('(deflabel note-6-1 ...)')  in ACL2 source file
 @('ld.lisp').</p>

 <p>Functions defined by @(tsee defstobj) had failed to be compiled when
 certifying books, except in host Lisps that compile on-the-fly (CCL, SBCL).
 This has been fixed for all host Lisps.  A related change, probably less
 significant, was made for @(tsee defabsstobj).  Thanks to Sol Swords for
 reporting bugs that turned out to be mistakes in a preliminary implementation
 of this change.</p>

 <p>Fixed an assertion error involving linear arithmetic.  Thanks to Sol Swords
 for sending an example illustrating the bug (now appearing as a comment in
 ACL2 source function @('linearize1')).</p>

 <p>Fixed a bug that was breaking the ACL2s build mechanism (see @(see
 acl2-sedan)) by causing certain needless evaluation of ``hidden @(tsee
 defpkg)'' forms in @(see certificate) files when executing a call of @(tsee
 include-book).  The bug could also affect rare error messages arising from
 ill-formed @(see certificate) files.  Thanks to Harsh Raju Chamarthi for
 bringing this bug to our attention by sending us an example script of the sort
 that was breaking during an ACL2s build.</p>

 <p>Fixed handling of pathnames by some low-level code (system function
 @('our-truename')) that could cause errors, for example for host-Lisp GCL on
 some platforms when environment variable @('HOME') points to a non-existent
 directory.  Thanks to Camm Maguire for bringing this issue to our attention
 and helping with the debugging.</p>

 <p>Fixed a coding bug in generation of stobj resizing functions for a stobj
 named @('OLD').  The following example illustrates the bug.</p>

 @({
  (defstobj old
    (fld :type (array (unsigned-byte 31) (8))
          :initially 0 :resizable t))
  (resize-fld 10 old)
  ; The following returned 8 but should have returned 10:
  (fld-length old)
 })

 <p>Fixed a bug in @(tsee defabsstobj-missing-events) (which macroexpanded
 incorrectly).  Thanks to Sol Swords for bringing this bug to our
 attention.</p>

 <p>Fixed two bugs in the handling of step-limits.  Thanks to Hanbing Liu for
 bringing the main such bug to our attention, which was that ACL2 could report
 a step-limit violation during @(tsee certify-book) (in fact, during any
 compound event such as a call of @(tsee encapsulate) or @(tsee progn)), even
 without direct user involvement in managing step-limits (see @(see
 set-prover-step-limit) and see @(see with-prover-step-limit)).  The other bug
 was that a bad argument to @(tsee set-prover-step-limit) could result in a raw
 Lisp error, for example: @('(progn (set-prover-step-limit '(a b)))').</p>

 <p><b>CHANGES AT THE SYSTEM LEVEL</b></p>

 <p>The @('books/') directory no longer needs to exist in order to build an
 ACL2 executable.  Thanks to Robert Krug for pointing out that the installation
 instructions had suggested that this was already the case.</p>

 <p>Many changes have been made to the @(see community-books).  For example,
 some community books now include @('std/lists/rev.lisp'), which contains the
 rule @('revappend-removal'), which may cause some proofs involving @(tsee
 revappend) to fail where they formerly succeeded, or vice-versa.  When a proof
 fails that formerly succeeded, it may be useful for you to look over the @(see
 rune)s printed in the event summary.</p>

 <p><b>EMACS SUPPORT</b></p>

 <p><b>EXPERIMENTAL/ALTERNATE VERSIONS</b></p>

 <p>For ACL2(p), @(tsee wormhole-eval) is now locked by default; thanks to
 David Rager for suggesting this change.  But there is a way to avoid the lock;
 see @(see wormhole-eval).  In particular, the lock is avoided in the
 implementations of @(see accumulated-persistence) and @(see
 forward-chaining-reports), which are not supported in ACL2(p) (see @(see
 unsupported-waterfall-parallelism-features)).</p>")

(defxdoc note-6-2

; Total number of release note items: 41.

; Here is the example from Sol Swords for the item below about acl2-magic-mfc
; and acl2-magic-canonical-pathname.  The problem was that these "placeholder"
; functions are really clause processors, and hence should return a list of
; clauses, not (as erroneously done before) a single clause.
;
;  (defun foo (x)
;     (declare (ignore x))
;     nil)
;
;  (defthm foo-of-t
;     (foo t)
;     :hints (("goal" :clause-processor acl2-magic-mfc)))
;
;  (thm nil :hints (("goal" :use foo-of-t)))

; Defined function set-new-dispatch-macro-character, which we use instead of
; set-dispatch-macro-character to extend the reader with #\@, #\!, #\u, and in
; ACL2(h), also #\Y and #\Z.  This way, we check that the character hasn't
; already being appropriated for the reader by the host Lisp.  Now, for
; example, CLISP causes an error when trying to build ACL2(h), because #\Y is
; already defined as a dispatch macro character.

; Here is Robert Krug's example, trivially modified, for the heuristic
; improvement pertaining to the ancestors check.

;   (defstub rm-low-32 (addr x86) t)
;
;   (defaxiom n32p-rm-low-32-axiom
;     (implies (and (integerp addr)
;                   (<= 0 addr)
;                   (force (< (+ 3 addr) 1000)))
;              (and (integerp (rm-low-32 addr x86))
;                   (<= 0 (rm-low-32 addr x86)))))
;
;   (defstub foo-p (x) t)
;
;   (defaxiom axiom-2
;     (implies (<= 0 (rm-low-32 addr x86))
;              (foo-p (rm-low-32 addr x86))))
;
;   ; The following fails, which is to be expected.  But we expect to see a forcing
;   ; round.  This is indeed the case now, but it was not in Version_6.1 (and
;   ; probably many versions preceding that one).
;   (thm (implies (and (integerp addr)
;                      (<= 0 addr))
;                 (foo-p (rm-low-32 addr x86))))

; Improved error messages and documentation pertaining to certain ill-formed
; uses of syntaxp, in response to feedback from Robert Krug.

; Regarding the change for THE, note that the-error has been replaced by
; the-check, a 3-place function that results in a macroexpansion of THE forms
; that differs from what we got previously.

; In the process of modifying the ancestors-check heuristic to use var-counts,
; as mentioned below and explained further in the definition of macro
; var-or-fn-count-<, we changed var-fn-count to be a macro defined in terms of
; (partly) tail-recursive "flag" function var-fn-count-1, in analogy to what we
; already did for fn-count and fn-count-1.  Var-fn-count-1 is in :logic mode;
; the old var-fn-count nest was not.

; It had been possible to violate the first invariant on type-alists: no quotep
; is bound in a type-alist, but we fixed that.  See the long comment in
; subst-type-alist1.

; Added macro our-ignore-errors in raw Lisp, to ignore errors except for CLtL1
; (i.e., non-ANSI GCL).  Used it to define safe-open, which is open wrapped
; with our-ignore-errors.  Used safe-open to implement the change mentioned
; below for open-input-channel open-output-channel: "no longer cause an error
; when failing to open a channel".

; The Essay on Correctness of Meta Reasoning has been greatly improved, in
; particular with respect to its handling of meta-extract hypotheses.

; Here is an example that formerly broke into raw lisp, but no longer after the
; fix for "A hard Lisp error was possible for certain illegal functional
; substitutions", mentioned in the :doc below.
;
;   (encapsulate
;    ((f (x) t))
;    (local (defun f (x) (cons x x)))
;    (defthm f-prop
;      (consp (f x))))
;
;   (defthm main
;     (let ((y x))
;       (listp (f y))))
;
;   (defun g (x y)
;     (cons x y))
;
;   (defthm g-prop
;     (listp (g x y))
;     :hints (("Goal"
;              :use
;              (:functional-instance main
;                                    (f (lambda (v) (g v y)))))))

; In the course of modifying ACL2 to run on top of ANSI GCL, we did
; miscellaneous clean-up of various comments and documentation topics, and in a
; few cases, code.  In particular, ANSI GCL exposed a flaw in
; intern-in-package-of-symbol, which we slightly reworked as a result.

; In support of mfc-xx fixes documented below, mfc-relieve-hyp-raw now
; returns two values, as expected by call from mfc-relieve-hyp macro.

; We made the following changes during the process of adding support for
; building ACL2(h) on ANSI GCL.  While we have run a significant portion of the
; ACL2(h) regression suite on ACL2(h) built on a version of ANSI GCL, which was
; gracefully built for us by Camm Maguire, it stalled out with
; books/models/y86/y86-basic/common/x86-state.lisp.  Here is a summary of those
; changes, some of which might benefit other Lisps, although currently we only
; do automatic proclaiming for defuns for ANSI GCL.
;
; - We improved output-type-for-declare-form-rec and
;   output-type-for-declare-form for gcl, but as a result, no longer
;   attempt to do such declaims for *1* functions (see
;   install-defs-for-add-trip).
;
; - We now avoid function declaims for an abstract stobj export, which
;   is defined as a macro.
;
; - We now avoid using defun-one-output for functions like mfc-ts-raw
;   that return two values (the second of which is a ttree).
;
; - We rationalized saving the system in GCL (function
;   save-acl2-in-akcl), in particular to use the function
;   acl2-default-restart.
;
; - With-print-controls no longer messes with *print-pprint-dispatch*.
;
; - We did miscellaneous cleanup, including changing #+DRAFT-ANSI-CL-2
;   to #+cltl2.
;
; - The definition of global *float-internal-units-per-second* was
;   clearly intended to be the definition of global
;   *float-internal-time-units-per-second*.  This has been fixed.
;
; - For ANSI GCL, we added a workaround for undefinedness of
;   compiler-macro-function.
;
; - For ANSI GCL, we fixed memoize-fn to quote the symbol-function
;   passed to funcall.  Perhaps that could be done in other Lisps too,
;   but it seemed unwise to risk it.
;
; - We guarded an occurrence of (start-sol-gc) with #+Clozure, since
;   start-sol-gc is undefined otherwise.
;
; - We moved a type declaration on formals in the definition of
;   ser-decode-nat-large to be just after the formals (which avoids a
;   complaint by ANSI GCL, but is probably a good thing to do
;   regardless).

; Fixed bug in rare error message in check-certificate-file-exists, for the
; case: "argument k is t for certify-book".

; Arranged that character encoding for files in LispWorks is always as expected
; (latin-1 with linefeed for :EOL-STYLE).

; Strengthened the identification of built-ins with raw Lisp definitions (see
; constant *primitive-logic-fns-with-raw-code*, as well as source function
; fns-different-wrt-acl2-loop-only and related functions).

; Added documentation about guards in :doc princ$ and :doc io.

; Removed trailing whitespace from the ACL2 sources.  Thanks to Warren Hunt for
; suggesting this change.

; We improved :doc redundant-events, especially to clarify that progn and
; make-event forms are never redundant.  Thanks to Harsh Raju Chamarthi for an
; email exchange that led us to make this improvement.

; For GCL only, further increased the binding stack (except, still, on
; Windows); see the setting of si::*multiply-stacks* in init.lisp.

; Modified *home-page* for searching books, to point to tag
; #Searching_and_browsing_the_books.

; For SBCL only, increased --control-stack-size from 4 to 8.

  :parents (release-notes)
  :short "ACL2 Version  6.2 (June, 2013) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 6.1 into the following
 categories of changes: existing features, new features, heuristic
 improvements, bug fixes, changes at the system level, Emacs support, and
 experimental versions.  Each change is described in just one category, though
 of course many changes could be placed in more than one category.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>The macro @(tsee top-level) has been changed, so that evaluation of a form
 @('(top-level x)') results in an error when evaluation of @('x') results in an
 error.  Thanks to Jared Davis for observing that when evaluating a file using
 @(tsee ld), an interrupt of a call of a @(tsee top-level) call in that file
 would not prevent evaluation of later forms in the file.</p>

 <p>The macro @(tsee THE) no longer causes an error when @(see guard)-checking
 is @(':NONE').  For example, it had been the case that evaluation of @('(the
 integer t)') always caused an error; but now, there is no error after
 executing command @(':')@(tsee set-guard-checking)@(' :NONE').  Thanks to
 Jared Davis for asking for a way to avoid such errors.</p>

 <p>The error printed when attempting to ``reincarnate'' a package &mdash; that
 is, to define a package that is not part of the ACL2 logical @(see world) but
 exists in raw Lisp because it was once part of the world &mdash; is now much
 more instructive.  In particular, it shows pathnames for the previous and
 proposed @(tsee defpkg) events, and it shows the symbols that are imported by
 one but not the other.  Thanks to Jared Davis for requesting this
 improvement.</p>

 <p>Functions @(tsee open-input-channel) and @(tsee open-output-channel) no
 longer cause an error when failing to open a channel because of a permissions
 problem, but instead return @('(mv nil state)').  Thanks to Jared Davis for
 requesting this change.  (Note: this change does not apply if the host Lisp is
 non-ANSI, i.e., if the host Lisp is non-ANSI GCL.)</p>

 <p>The advanced @(see meta-extract) mechanisms, provided for using facts from
 the @(see world) or metafunction context, have been enhanced in the following
 ways, in collaboration with Sol Swords.  See @(see meta-extract) for more
 details.</p>

 <blockquote>

 <p>It is now permissible to use calls of @('meta-extract-global-fact') in
 hypotheses of @(tsee clause-processor) rules, much as they are used in
 hypotheses of @(tsee meta) rules.  See @(see meta-extract).  Thanks to Sol
 Swords for requesting this feature.</p>

 <p>The utility @('meta-extract-global-fact') is now a macro, which expands to
 a corresponding call of the new function, @('meta-extract-global-fact+').
 This new function takes an alternate, extra @(see state) as an argument; it is
 not to be executed, and it operates on the alternate state, whose logical
 @(see world) is intended to be the same as that of the ``live'' (usual)
 state.</p>

 <p>A new sort of value for the @('obj') argument is supported for
 @('meta-extract-global-fact') (and @('meta-extract-global-fact+')), which
 results in a term equating a function application to its result.  See @(see
 meta-extract), in particular the discussion of @(':fncall').</p></blockquote>

 <p>It is now possible for @('trace$') to avoid printing prefixes of the form
 @('\"n> \"') and @('\"<n \"'), while also (optionally) avoiding indentation.
 See @(see trace$), in particular the discussion of @(':fmt!').  Thanks to
 Shilpi Goel for requesting this feature.</p>

 <p>It was possible for the @(see guard-debug) feature to generate duplicate
 calls of @('extra-info') in hypotheses generated for guard verification.  We
 have eliminated duplicates of this sort.</p>

 <p>When @(tsee in-theory) returns without error, it returns a value
 @('(:NUMBER-OF-ENABLED-RUNES k)'), where @('k') is the length of the new
 current theory.  (Formerly, @('k') was returned.)  This value is thus printed
 when an @('in-theory') event is submitted at the top level.  Thanks to Gisela
 Rossi for feedback that led us to make this change.</p>

 <p>A new keyword parameter for @(tsee ld) is @(':ld-missing-input-ok').  Its
 default value is @('nil'), which causes an error, as before, upon failure to
 open a specified file.  Other legal values are @('t') and @(':WARN'); see
 @(see ld-missing-input-ok) and see @(see ld).</p>

 <p>Extended @('*acl2-exports*'), in particular adding @('UNSIGNED-BYTE-P') and
 @('SIGNED-BYTE-P') (thanks to a suggestion by Jared Davis)</p>

 <p>Even if the function @('f') is defined to take one or more @(see stobj)
 arguments, the form @('(ec-call (f ...))') is now legal if all arguments of
 the call of @('f') are non-stobj objects, in any context where only ordinary
 object return values are expected.</p>

 <p>When the second argument of @(tsee certify-book) is a symbol, that symbol
 formerly needed to be @('?') or @('t'), in the @('\"ACL2\"') package.  Now,
 the @(see symbol-package-name) of the second argument is ignored: any symbol
 whose @(see symbol-name) is @('\"?\"') or @('\"T\"') is treated the same in
 that argument position as the symbol @('?') or @('t') in the @('\"ACL2\"')
 package, respectively.  Thanks to Warren Hunt and Nathan Wetzler for
 suggesting consideration of a more relaxed criterion for that second
 argument.</p>

 <p>(For system hackers, not standard ACL2 users:) Utilities @(tsee
 initialize-event-user) and @(tsee finalize-event-user) now each take a list of
 three arguments, @('(ctx body state)').  Thanks to Harsh Raju Chamarthi for
 requesting this change.</p>

 <p><b>NEW FEATURES</b></p>

 <p>It is now permissible to specify a @(see stobj) field that is itself either
 a stobj or an array of stobjs.  A new primitive, @(tsee stobj-let), is
 provided in order to access or update such fields; see @(see stobj-let).
 Thanks to Warren Hunt and Sol Swords for requesting the ability to specify
 nested stobjs.</p>

 <p>New accessor function @('(mfc-world mfc)') returns the world component of a
 metafunction context.  See @(see extended-metafunctions).</p>

 <p>A new @(tsee xargs) keyword, @(':SPLIT-TYPES'), can be used to ``split''
 the @(see type) declarations from the @(see guard) in the following sense.  By
 default, or when @(':SPLIT-TYPES') has value @('nil'), one gets the existing
 behavior: the terms corresponding to type declarations are conjoined into the
 guard.  However, if @(':SPLIT-TYPES t') is specified, then that is not the
 case; instead, guard verification will require that these terms are proved
 under the hypothesis that the guard holds.  In this way, one can add type
 declarations to assist the host Lisp compiler without cluttering the
 function's guard.  See @(see xargs).  Thanks to Jared Davis for requesting
 this feature.</p>

 <p>Advanced users may want to see @(see
 quick-and-dirty-subsumption-replacement-step) for a way to turn off a prover
 heuristic.  Thanks to those who have mentioned to us potential issues with
 this heuristic, most recently Dave Greve.</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>We made changes to the ``ancestors check'' heuristic (source function
 @('ancestors-check-builtin')), as follows.</p>

 <blockquote>

 <p>The heuristic could prevent a @(see rewrite) rule's hypothesis from being
 rewritten to true, even when that hypothesis is of the form @('(force
 <term>)').  Now, forcing will take place as expected; see @(see force).
 Thanks to Robert Krug for bringing this issue to our attention and sending an
 example, which we include as a comment in the ACL2 source code (see
 @('(deflabel note-6-2 ...)')).</p>

 <p>The heuristic is now delayed until after we check whether the hypothesis is
 already known, using @(see type-set) reasoning alone (in particular, not using
 rewriting), to be true or to be false.  We believe that this is now the
 ``right'' order for those two operations.  We saw a slight speed up in the
 regression tests (about a percent) with this change, but that might be in the
 noise.</p>

 <p>A technical change makes the heuristic slightly less aggressive in
 preventing backchaining.  Roughly speaking, ordering checks based on function
 symbol counts could suffice to permit backchaining, where now variable counts
 also suffice.  Thanks to Robert Krug for showing us an example where
 backchaining led to a term with no free variables that was nevertheless
 subject to the ancestors check, preventing it from being rewritten.</p>

 <p>(For those who use @(tsee defattach) to attach to @('ancestors-check')) We
 have used @('defrec') to introduce an `@('ancestor')' data structure.  A new
 function, @('strip-ancestor-literals'), should be used to obtain the literals
 from a list of ancestors, although @('strip-cars') will still work at this
 time.</p></blockquote>

 <p>When we rewrite the current literal of the current clause we assume the
 falsity of the other literals and of the conclusions produced by forward
 chaining.  We have changed the order in which those assumptions are made,
 which affects the type-alist used during rewriting.  This has three effects:
 the new type-alist, which is sometimes stronger than the old one, may allow
 additional rules to fire, the choice of free vars may be different, and the
 order of the literals in forced subgoals may be different.  Should ``legacy''
 proofs fail under the new type-alist, we recommend looking for rules that are
 fired in the new proof that were not fired (on that same subgoal) in the old
 one.  Thanks to Dave Greve for sending us an example that led us to make this
 change.</p>

 <p><b>BUG FIXES</b></p>

 <p>We fixed a soundness bug that could be exploited by calling system
 functions @('acl2-magic-mfc') or @('acl2-magic-canonical-pathname').  Thanks
 to Sol Swords for bringing this bug to our attention.</p>

 <p>We fixed a soundness bug in the handling of @(see stobj)s, in which strings
 were recognized as stobjs in raw Lisp.  Thanks to Jared Davis for sending us a
 proof of @('nil') that exploited this bug.  We now have a much simpler example
 of this bug, as follows.</p>

 @({
  (defstobj st fld)
  (defthm bad (stp \"abc\") :rule-classes nil)
  (defthm contradiction
    nil
    :hints ((\"Goal\" :in-theory (disable (stp)) :use bad))
    :rule-classes nil)
 })

 <p>We fixed bugs in extended metafunctions (see @(see
 extended-metafunctions)).  The macro @('mfc-ap') no longer takes a
 @(':TTREEP') keyword argument, because this argument could allow returning a
 tag tree that does not properly account for forcing.  The remaining
 @('mfc-xx') macros &mdash; @('mfc-relieve-hyp'), @('mfc-rw+'), @('mfc-rw'),
 and @('mfc-ts') &mdash; still take a @(':TTREEP') keyword argument, but the
 corresponding functions when @(':TTREEP') is @('t') &mdash;
 @('mfc-relieve-hyp-ttree'), @('mfc-rw+-ttree'), @('mfc-rw-ttree'), and
 @('mfc-ts-ttree') &mdash; were introduced with incorrect output signatures.  A
 complication is that @('mfc-relieve-hyp-ttree') was improperly defined in raw
 Lisp in a way that actually matched the incorrect signature!  All of these
 bugs have been fixed.  Perhaps any of them could have made it possible to
 prove @('nil'), though we have not tried to do so.</p>

 <p>(Windows only) On Windows, it had been possible for ACL2 not to consider
 two pathnames to name the same file when the only difference is the case of
 the drive, e.g., `@('C:')' vs. `@('c:')'.  This has been fixed.  Thanks to Sol
 Swords for reporting this issue.</p>

 <p>Fixed a bug in the storing of rules for the tau system; see @(see
 tau-system).  (The error message mentions
 PARTITION-SIGNATURE-HYPS-INTO-TAU-ALIST-AND-OTHERS.)  Thanks to Sol Swords for
 reporting this bug and sending a simple example to illustrate it.</p>

 <p>It had been possible to admit the missing @(tsee defthm) events printed by
 @(tsee defabsstobj), and yet get an error when subsequently submitting the
 same @('defabsstobj') event, stating: ``Note discrepancy with existing
 formula''.  The problem could occur when an expression of the form @('(or X
 Y)') occurred in one of those missing events, because ACL2 created it from the
 term @('(if X 't Y)') but then translated @('(or X Y)') to @('(if X X Y)'),
 resulting in a mismatch.  This has been fixed.  Thanks to Jared Davis for
 reporting this bug using a simple example.</p>

 <p>A hard Lisp error was possible for certain illegal functional substitutions
 (see @(see lemma-instance)).  Thanks to Sol Swords for reporting this bug.</p>

 <p>We fixed a bug in the case that an exported function of a @(tsee
 defabsstobj) event had a @(see guard) of @('t').  Thanks to Jared Davis for
 sending a simple example when reporting this bug.</p>

 <p>We now avoid an infinite loop that could occur when attempting to close the
 standard character output channel (see @(see standard-co)).  Instead, an error
 message explains how to accomplish what was probably intended.  Thanks to
 Shilpi Goel for bringing this issue to our attention.</p>

 <p>(Windows only) Fixed a bug that was causing a hard error on Windows when
 ACL2 encountered filenames starting with the tilde character (@('~')), for
 example, @('(ld \"~/acl2-customization.lsp\")').  Thanks to Sol Swords for
 bringing this bug to our attention.  Also thanks to Harsh Raju Chamarthi for a
 useful conversation that led to a better fix than our first one.</p>

 <p><b>CHANGES AT THE SYSTEM LEVEL</b></p>

 <p>ACL2 may now be built on recent versions of a new host Lisp, ANSI Gnu
 Common Lisp (GCL).  Traditional (non-ANSI) GCL was the original host Lisp
 underlying ACL2, and we are grateful for GCL support that we received from the
 late Bill Schelter and, more recently and particularly for ANSI GCL, from Camm
 Maguire.</p>

 <p>The `make' process suggested for book certification has changed
 substantially, thanks in large part to contributions from Jared Davis and Sol
 Swords.  We have seen the new process provide better performance on machines
 with many cores, and we expect maintenance advantages such as eliminating the
 need for Makefiles in individual book directories.  The ``classic'' process,
 which was based on community books file @('books/Makefile-generic'), is still
 supported (see @(see books-certification-classic)) but may disappear in a
 future release of ACL2.  See @(see books-certification).  Most changes should
 be invisible to the user, other than improved `make'-level parallelism, with
 the exception of the following.</p>

 <blockquote><p>o Variable @('ACL2_JOBS') is no longer supported, nor is it
 necessary; simply use `make' option `-j' instead.</p>

 <p>o Regressions now use `make' option @('-k') by default, which causes the
 regression to keep going after errors, rather than @('-i'), which ignores
 errors.  If you encounter problems because of this change, use
 @('ACL2_IGNORE=-i') with your `make' command.</p>

 <p>o The `regression' target works for the experimental extension, ACL2(h)
 (see @(see hons-and-memoization)); target `regression-hons' no longer
 exists.</p></blockquote>

 <p>Please let us know if you run into problems with the new infrastructure, as
 we consider the legacy infrastructure to be deprecated and we will probably
 eliminate much of it in the future.  In particular, circular dependencies were
 formerly prohibited at the directory level, but that is no longer the case,
 and we expect such cycles to occur in the future.</p>

 <p>Although ACL2 users don't typically modify raw Lisp variables, we have
 arranged to reset Lisp variable @('*default-pathname-defaults*') if necessary
 at startup so that it will not interfere with ACL2, in particular by messing
 up the initial connected book directory (see @(see cbd)).  Thanks to Jared
 Davis, Sol Swords, and Raymond Toy for helping us to identify this issue.</p>

 <p><b>EMACS SUPPORT</b></p>

 <p><b>EXPERIMENTAL/ALTERNATE VERSIONS</b></p>

 <p>In ACL2(h), @(tsee print-object$) no longer uses the serialize printer
 except in system applications as before (e.g., write out @('.cert') files).
 Thanks to Dave Greve for bringing this issue to our attention.</p>

 <p>Jared Davis contributed changes related to the @(tsee memoize) utility of
 ACL2(h), including some low-level changes as well as the following.</p>

 <p>o @(tsee Never-memoize) specifies that a given function should never be
 memoized.</p>

 <p>o Removed @('memoize-let'), which may never have ever been used.</p>

 <p>o Removed the @(':inline') keyword option to memoize, which was just an
   alias for the @(':recursive') option.</p>

 <p>For ACL2(p), some anomalous behavior may no longer occur because prover
 calls (more specifically, trips through the ACL2 ``waterfall'') will return
 only after all sub-computations (threads) have finished.  Thanks to David
 Rager for contributing this improvement.</p>

 <p>ACL2(pr), which includes @(see parallelism) (as for ACL2(p)) and
 non-standard analysis support for the @(see real)s (as for ACL2(r)), now
 builds and can certify the community @('nonstd/') books.  Thanks to David
 Rager for his contribution to this capability.</p>")

(defxdoc note-6-3

; Total number of release note items: 36.

; (CMUCL only) Allocated larger stack for CMUCL on 64-bit x86 installations.

; Evaluation of a redundant encapsulate event, in the case that the event is
; not equal to the corresponding earlier encapsulate event, now causes an
; additional message to be printed that directs the user to a new :doc topic --
; redundant-events -- which explains the situation (and includes some :doc that
; was formerly in :doc encapsulate).  Because of this, stop-redundant-event has
; been modified.  Thanks to Carl Eastlund for suggesting improvements along
; these lines.

; Modified functions stobjs-out and get-stobjs-out-for-declare-form according
; to a suggestion from Jared Davis, to cause an error when attempting to
; determine the stobjs-out for IF just as we already do for RETURN-LAST.

; Regarding the "bug in the case of a field of a (concrete) stobj that is an
; abstract stobj": this was a bug in the #-acl2-loop-only case of
; get-stobj-creator.

; Here is a little example showing the change to :by hints involving
; quote-normal form.  The proof of the THM failed until this change was made.
;
;   (defthm my-thm
;     (equal (car '(3 . 4)) 3)
;     :rule-classes nil)
;
;   (thm (equal (car (cons 3 4)) 3)
;        :hints (("Goal" :by my-thm)))

; (GCL only) Just below is a book, certifiable in ACL2 Version_6.2,
; illustrating the "obscure soundness bug due to an error in the GCL
; implementation of set-debugger-enable".  The problem was that the definition
; of set-debugger-enable-fn ended with #-acl2-loop-only code of the form (when
; (live-state-p state) ... state), which erroneously returns nil for a non-live
; state.
;
;   (in-package "ACL2")
;
;   (defthm false-formula
;     (equal (set-debugger-enable-fn nil (build-state))
;            nil)
;     :rule-classes nil)
;
;   (defthm true-formula
;     (implies (state-p1 s)
;              (state-p1 (set-debugger-enable-fn nil s)))
;     :hints (("Goal" :in-theory (enable state-p1)))
;     :rule-classes nil)
;
;   (defthm contradiction
;     nil
;     :hints (("Goal"
;              :use (false-formula
;                    (:instance true-formula
;                               (s (build-state))))))
;     :rule-classes nil)

; Improved our-truename (definition and calls) so that in case of an error, we
; get additional information.

; Added new :doc topic, ignored-attachment, pointing to it in the message
; printed by function ignored-attachment-msg.

; Changed all-equal to have a test of atom instead of endp, so that it
; could be guard-verifiable as requested by Eric Smith.

; Updated :doc make-event to clarify that it is legal to call make-event during
; make-event expansion, even outside an event context.

; Modified function maybe-add-command-landmark to avoid giving special
; treatment to with-prover-time-limit, since with-prover-time-limit is
; a full-fledged event constructor and hence this is not necessary.

; Removed definition of obsolete function, called acl2, from the
; sources.

; Slightly changed wording pertaining to the "combined" (xdoc) manual on the
; ACL2 home page.

; Fixed TAGS! target in GNUmakefile to do what it has been claiming to
; do: rebuild TAGS even when TAGS is up-to-date with respect to the
; source files.

; Added new state global, acl2-sources-dir, in support of the new ACL2 startup
; banner in the case of an svn version.

; The guard for function ENDP has potentially been made trivially more
; efficient by using EQ to test against nil instead of EQUAL.

; In support of :by hint processing (see the :doc string below),
; remove-guard-holders now returns a term in quote normal form, even when the
; input term contains no guard holders.

; The startup banner can now be suppressed, though only by unsanctioned hacking
; in raw Lisp, as requested by Jared Davis.  See *print-startup-banner*, which
; has a comment explaining more about how this may not be appropriate and what
; needs to be done to suppress startup information.

; Removed support for "make fast", "make very-fast", and "make fast-meter",
; which as far as we know are no longer in use.  Thus, deleted
; quick-compile-acl2.  Also deleted no-object-file-or-out-of-date-object-file,
; since it was there only to support quick-compile-acl2.

; Improved the error message for #.expr when expr hasn't been defined by
; defconst.

; Modified printing of the banner for GCL, especially for versions 2.6.9 and
; later, due to a change in how GCL prints such banners.  (Printing of the
; banner still works fine with older versions of GCL.)

; For SBCL only, increased --control-stack-size from 8 to 16.

; For CMUCL only, declaimed len to be notinline, to avoid what appears to be a
; CMUCL compiler bug that shows up when attempting to certify the community
; book books/models/jvm/m1/defsys.lisp.

; Incorporated fix from Sol Swords for ACL2(h): "memoize time
; tracking: fix some subtle RDTSC-related problems that could cause
; safe-incf errors on machines that often switch your thread across
; cores".

; Just below is a book containing a proof of nil, which exploits the soundness
; bug reported by Jen Davis and Dave Greve, permitting a stobj to be bound by a
; let or mv-let form without being among the outputs of that form.  The bug was
; in translate11-let (and also, similarly, in translate11-mv-let); it was a
; coding bug that failed to distinguish between the original value of a formal,
; tbody, and an updated version of that formal.

;   (in-package "ACL2")
;
;   (defstobj st halt)
;
;   (defun foo (st)
;     (declare (xargs :stobjs st))
;     (let ((st (update-halt 0 st)))
;       (halt st)))
;
;   (defun bar ()
;     (declare (xargs :guard t))
;     (with-local-stobj
;      st
;      (mv-let (result st)
;              (let ((x (foo st)))
;                (declare (ignore x))
;                (mv (halt st) st))
;              result)))
;
;   (defthm thm1
;     (equal (bar) 0)
;     :rule-classes nil)
;
;   (defthm thm2
;     (equal (bar) nil)
;     :hints (("Goal" :in-theory (disable (bar))))
;     :rule-classes nil)
;
;   (defthm contradiction
;     nil
;     :hints (("Goal" :use (thm1 thm2)))
;     :rule-classes nil)

  :parents (release-notes)
  :short "ACL2 Version  6.3 (October, 2013) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes since Version 6.2 into the following
 categories of changes: existing features, new features, heuristic
 improvements, bug fixes, changes at the system level, Emacs support, and
 experimental versions.  Each change is described in just one category, though
 of course many changes could be placed in more than one category.</p>

 <p><b>CHANGES TO EXISTING FEATURES</b></p>

 <p>The evaluation of a term from a @(tsee bind-free) hypothesis had been
 expected to produce an alist binding free variables to terms.  While that is
 still legal, it is also legal for that evaluation to produce a list of such
 alists: then each is considered, until one of them permits all remaining
 hypotheses to be relieved.  See @(see bind-free).  Thanks to Sol Swords for
 requesting this enhancement.</p>

 <p>ACL2 continues to provide a way to specify keyword command abbreviations
 for the top-level loop; see @(see ld-keyword-aliases).  However, @(tsee
 ld-keyword-aliases) is now a @(see table) rather than a @(see state) global;
 it is thus no longer a so-called @(see LD) special.  The functionality of
 @('set-ld-keyword-aliases') has essentially been preserved, except that it is
 now an event (see @(see events)), hence it may appear in a book; it is @(see
 local) to a book (or @(tsee encapsulate) event); and the @(tsee state)
 argument is optional, and deprecated.  A non-local version
 (@('set-ld-keyword-aliases!'))  has been added, along with corresponding
 utilities @('add-keyword-alias') and @('add-keyword-alias!') for adding a
 single keyword alias.  See @(see ld-keyword-aliases).  Thanks to Jared Davis
 for correspondence that led us to make this change.</p>

 <p>The @(see proof-builder) command @('(exit t)') now exits without a query
 (but still prints an event to show the @(':INSTRUCTIONS')).  Thanks to Warren
 Hunt for feedback leading us to make this change.</p>

 <p>We made the following minor changes to the behavior of @('dmr'); see @(see
 dmr).  First, if @('dmr') monitoring is enabled, then @('(dmr-start)') will
 have no effect other than to print a corresponding observation, and if
 monitoring is disabled, then @('(dmr-stop)') will have no effect other than to
 print a corresponding observation.  Second, it had been the case that when
 @('(dmr-start)') is invoked, the debugger was always automatically enabled
 with value @('t') (see @(see set-debugger-enable)), and the debugger remained
 enabled when @('(dmr-stop)') was invoked.  Now, the debugger is only enabled
 by @('(dmr-start)') if it is not already enabled and does not have setting
 @(':never').  Moreover, if such automatic enabling takes place, then the old
 setting for the debugger is restored by @('(dmr-stop)') unless @(tsee
 set-debugger-enable) has first been called after that automatic enabling.
 Finally, if the value of @(see state) global variable @(''debugger-enable') is
 @(':bt'), then the new value will be @(':break-bt'), not @('t').</p>

 <p>When a call of @(tsee progn) is executed in the ACL2 loop, its constituent
 @(see events) and their results are printed, just as was already done for
 calls of @(tsee encapsulate).  Thanks to Jared Davis for a conversation
 causing us to consider this change.</p>

 <p>(CCL only) When @(tsee set-debugger-enable) is invoked with an argument
 that prints a backtrace and CCL is the host Lisp, the backtrace will be
 limited to 10,000 stack frames.  (We have seen more than 65,000 stack frames
 before this change.)  This limit is the value of raw Lisp variable
 @('*ccl-print-call-history-count*'), which may be assigned another positive
 integer value to serve as the maximum number of stack frames to be
 printed.</p>

 <p>Improvements have been made pertaining to the disabling (inhibiting) of
 individual types of warning.  Now, inhibited warnings are implemented in a
 straightforward way using a separate @(see table) for this purpose, the
 @('inhibit-warnings-table'), rather than using the @(tsee
 acl2-defaults-table).  See @(see set-inhibit-warnings), and see @(see
 set-inhibit-warnings!) for a variant that is not @(tsee local) to an @(tsee
 encapsulate) or a book in which it occurs.  Thanks to Sol Swords for sending
 examples showing how @(tsee set-inhibit-warnings) did not always behave as one
 might reasonably expect when books are involved.</p>

 <p>It had been the case that @(tsee lp) took a single argument, @(''raw').
 This argument was not documented and also caused an error, so it has been
 eliminated.</p>

 <p>The functionality of @(tsee make-event) has been significantly expanded.
 First: if the expansion is of the form @('(:OR e1 e2 ...)'), then event forms
 @('e1'), @('e2'), and so on are evaluated, in order, until the evaluation of
 some @('ek') completes without error.  In that case, the expansion is treated
 simply as @('ek').  With this capability, alternative expansions can be
 attempted and the successful one does not need to be evaluated again.  See the
 new version of community book @('books/make-event/proof-by-arith.lisp') for an
 example.  Second, an expansion may be of the form @('(:DO-PROOFS e)'), in
 which case the event @('e') is evaluated with proofs <b>not</b> skipped; see
 @(see ld-skip-proofsp).  Third, new keyword @(':EXPANSION?') can be used to
 avoid storing expansions in certificate files.  See @(see make-event).</p>

 <p>When a @(tsee defun) event prints a failure message in the summary, that
 message now indicates when the failure is due to a failed proof of guard
 verification or a failed proof of the measure theorem.  Thanks to Shilpi Goel
 for requesting this enhancement.</p>

 <p><b>NEW FEATURES</b></p>

 <p>ACL2 can now be instructed to time activities using real time (wall clock
 time) instead of run time (typically, cpu time).  See @(see
 get-internal-time).  Thanks to Jared Davis for asking to be able to obtain
 real-time reports in event summaries.</p>

 <p>A new utility, @(tsee sys-call+), is similar to existing utility @(tsee
 sys-call) in that it executes a command.  Unlike @('sys-call'), however,
 @('sys-call+') returns values that include output from the command (in
 addition to the exit status), rather than simply printing the command.  See
 @(see sys-call+).</p>

 <p>The new macro @(tsee verify-guards+) extends the functionality of @(tsee
 verify-guards) by permitting macro-aliases (see @(see macro-aliases-table)).
 See @(see verify-guards+).  Thanks to Jared Davis for requesting this feature
 and suggesting the use of @(tsee make-event) in its implementation.  We have
 also modified @(tsee verify-guards) to print a friendlier error message when
 its argument is a macro-alias.</p>

 <p>See @(see last-prover-steps) for a new utility that returns the number of
 prover steps most recently taken.</p>

 <p><b>HEURISTIC IMPROVEMENTS</b></p>

 <p>The processing of @(':use') and @(':by') @(see hints) has been changed in
 the following two rather subtle ways, thanks to suggestions from Sol
 Swords.</p>

 <blockquote>

 <p>o For @(':by') hints, the simplest check was an equality check, rather than
 a more general subsumption check.  That equality check was made after removing
 so-called ``guard holders'' (@(tsee must-be-equal), @(tsee prog2$), @(tsee
 ec-call), @(tsee the)) from both the previous theorem and the purported
 theorem.  Now, guard-holder removal has been strengthened, so that the results
 are also put into so-called quote-normal form, for example replacing @('(cons
 '3 '4)') by @(''(3 . 4)').</p>

 <p>o For a @(see lemma-instance) provided to a @(':use') or @(':by') hint that
 is a @(':functional-instance'), if a @(':do-not') hint (see @(see hints)) has
 specified that @('preprocess-clause') is not to be used, then preprocessing
 will not be used on the constraints.</p></blockquote>

 <p>We eliminated certain warnings about being ``weak'' for every @(':')@(tsee
 type-prescription) rule whose conclusion designates that the function call can
 be equal to one of its arguments, e.g., @('(or (integerp (foo y)) (equal (foo
 y) y))').  In many cases (such as the one above), such warnings about ``weak''
 simply aren't correct.</p>

 <p><b>BUG FIXES</b></p>

 <p>Fixed a soundness bug that was permitting a @(see stobj) to be bound by a
 @(tsee let) or @(tsee mv-let) form, without being among the outputs of that
 form.  Thanks to Jen Davis and Dave Greve for reporting this bug.  Their
 report included an example which forms the basis for a proof of @('nil'),
 included as a comment in the form @('(deflabel note-6-3 ...)') in ACL2 source
 file @('ld.lisp').</p>

 <p>(GCL only) Fixed an obscure soundness bug due to an error in the GCL
 implementation of @(tsee set-debugger-enable).  For details, see the relevant
 comment in the ACL2 source code under @('(deflabel note-6-3 ...)').</p>

 <p>Fixed a bug in the case of a field of a (concrete) stobj that is an
 abstract stobj (see @(see nested-stobjs)).  Thanks to David Rager for bringing
 this bug to our attention.</p>

 <p>Splitter output for type @('if-intro') (see @(see splitter)) could formerly
 occur even when at most one subgoal is generated.  This has been fixed.</p>

 <p>Fixed a bug in @(tsee wof), hence in @(tsee psof) (which uses @('wof')),
 that was causing the printing of a bogus error message.</p>

 <p>A small logical bug has been fixed in the logical definition of @(tsee
 sys-call-status).  Formerly it always returned @('(mv nil state)') whenever
 the oracle of the state is non-empty (see @(see state)).</p>

 <p>Fixed a bug that was causing an error upon evaluation of the form
 @('(set-prover-step-limit nil)').  Thanks to David Russinoff for reporting
 this error.</p>

 <p>The @(':measure') (if supplied) is now ignored when checking redundancy
 with respect to a non-recursive definition that is not defined within a @(tsee
 mutual-recursion).  (See @(see redundant-events) and see @(see xargs).)  It
 had been possible to get a low-level ACL2 error in this situation.  Thanks to
 Jared Davis for reporting this bug with a helpful example.</p>

 <p>Eliminated a potential error when using @(tsee comp) to compile an
 uncompiled function defined under @(tsee progn!), which we observed in
 LispWorks.</p>

 <p><b>CHANGES AT THE SYSTEM LEVEL</b></p>

 <p>The ACL2 sources are now publicly available between ACL2 releases, using
 svn; see the new ``@('acl2-devel')'' project hosted by Google code at <a
 href='http://acl2-devel.googlecode.com'>http://acl2-devel.googlecode.com</a>.
 Although such a copy of ACL2 is likely to work well with the latest svn
 (trunk) revision of the ACL2 community books (see @(see community-books)),
 please take seriously the warning message printed at startup: ``The authors of
 ACL2 consider svn distributions to be experimental; they may be incomplete,
 fragile, and unable to pass our own regression.''  That message also provides
 instructions for bug reports.  If you decide to use svn versions of either the
 community books or ACL2, then you should use both, as they tend to be kept in
 sync.  We fully expect ACL2 releases to continue from time to time, as usual.
 Thanks to Jared Davis for his efforts in setting up the new acl2-devel project
 and svn repository, and to him and David Rager for convincing us to distribute
 ACL2 sources via svn between releases.</p>

 <p>Thanks to a suggestion from Jared Davis, over 30 built-in functions are now
 declared to be inline in order to boost performance.  (The list may be found
 by searching ACL2 source file @('axioms.lisp') for ``@('(declaim
 (inline')''.)</p>

 <p>Better support has been provided for command line arguments, especially
 those supplied directly by the user when calling ACL2.  For one, problems with
 quoting have been solved using @('\"$@\"') in place of @('$*').  Also, the
 function @(tsee save-exec) now allows specification of arguments, both for the
 host Lisp as well as ``inert'' arguments that can be passed along to calls of
 programs (as with @(tsee sys-call)).  A keyword argument,
 @(':return-from-lp'), specifies a form to evaluate before quitting the
 read-eval-print loop at startup.  See @(see save-exec).  Also see the source
 function @('user-args-string') and its comments, source file
 @('acl2-init.lisp'), for more information.  Thanks to Jared Davis for
 suggesting the use of @('\"$@\"'), as well as modifications to @(tsee
 save-exec) and helpful conversations about that.</p>

 <p>A rather extensive overhaul has taken place for the function proclaiming
 mechanism.  As before, this is only used when the host Lisp is GCL.  However,
 building an executable is now faster for some Lisps, including GCL, by
 avoiding repeated recompilation and perhaps repeated initialization.</p>

 <p>(CCL only) We increased stack sizes when the host Lisp is CCL.  The default
 for recent CCL versions is equivalent to specifying `@('-Z 2M')' on the
 command line, but saved ACL2 scripts (including experimental versions ACL2(h),
 ACL2(p), ACL2(r), and combinations of them) to `@('-Z 64M')', representing a
 32-fold increase.  Thanks to Jared Davis for pointing us to community books
 file @('books/centaur/ccl-config.lsp') and to Sol Swords for helpful
 discussions.</p>

 <p>(SBCL only) Fixed @('save-exec') for host Lisp SBCL to provide the same
 export of variable @('SBCL_HOME') that was provided in the original
 @('saved_acl2') script.</p>

 <p>(GCL only) We made changes, following suggestions from Camm Maguire (whom
 we thank for these suggestions), to support ACL2 builds on recent versions of
 GCL (2.6.8 and 2.6.10; we recommend against using GCL 2.6.9, since issues
 there were fixed in 2.6.10).  Specifically, we no longer set the hole size,
 and we allocate contiguous pages sufficient to run an ACL2 regression without
 failing due to memory limitations.</p>

 <p><b>EMACS SUPPORT</b></p>

 <p>Modified file @('emacs/emacs-acl2.el') to eliminate some warnings that were
 appearing in a recent Emacs version, replacing @('(end-of-buffer)') by
 @('(goto-char (point-max))') and @('next-line') by @('forward-line').  Thanks
 to Warren Hunt for bringing the warnings to our attention.</p>

 <p><b>EXPERIMENTAL/ALTERNATE VERSIONS</b></p>

 <p>(Allegro CL only) ACL2(h) now avoids blow-ups in hash table sizes that
 could be caused by @(see fast-alist-fork).  Thanks to Jared Davis for
 helping to debug this problem, and to David Rager for contributing the
 community book @('books/parsers/earley/earley-parser.lisp'), which highlighted
 this problem.</p>

 <p>(SBCL only) Fixed a bug that was causing a Lisp break after turning on
 @(see waterfall-parallelism).  Thanks to David Rager for confirming that our
 proposed fix is correct.</p>")

(defxdoc note-6-4

; Total number of release note items: 27.

; Here is an example proof of nil exploiting the soundness bug in the handling
; of hypotheses of conditional definition rules invoked during rewriting by
; applying expand hints.

;   (defun e (x y)
;     (iff (booleanp x) (booleanp y)))
;   (defun f (x)
;     (booleanp x))
;   (defun g (x)
;     (if (equal x nil) t x))
;   (defun h (x)
;     (equal x nil))
;   (defthm g-open
;     (implies (h x)
;              (equal (g x) t))
;     :rule-classes :definition)
;   (defequiv e)
;   (defcong e iff (f x) 1)
;   (in-theory (disable f g))
;   (defthm h-rewrite
;     (e (h x) t))
;   (defthm bad
;     (f (g x))
;     :hints (("Goal" :expand ((g x))))
;     :rule-classes nil)
;   (defthm contradiction
;     nil
;     :hints (("Goal" :use ((:instance bad (x 17)))))
;     :rule-classes nil)

; Fixed a bug in save-gprof.lsp, reported by Camm Maguire (who might be the
; first person to use this in many years).

; Incorporated fix to time$ from Jared Davis and Sol Swords, to speed up time$
; in (especially) the case that printing is not done.

; Here is an example sent by Sol Swords to illustrate the soundness bug
; pertaining to violating stobj recognizers.

;   (defstobj st (fld :type (satisfies integerp) :initially 0))
;
;   (defun integerp-of-fld (st)
;      (declare (xargs :stobjs st))
;      (mbe :logic t
;           :exec (integerp (fld st))))
;
;   (defun screw-up-st (st)
;      (declare (xargs :mode :program :stobjs st))
;      (update-fld nil st))
;
;   (make-event
;     (let ((st (screw-up-st st)))
;       (mv nil '(value-triple :screwed-up-st) state st)))
;
;   (defun-sk exists-non-integer-fld ()
;      (exists st
;              (not (integerp-of-fld st))))
;
;   (defthm no-non-integer-flds
;      (not (exists-non-integer-fld)))
;
;   (defun non-integer-fld-clauseproc (clause hints st)
;      (declare (xargs :stobjs st)
;               (ignore hints))
;      (if (and (equal clause '((exists-non-integer-fld)))
;               (not (integerp-of-fld st)))
;          (mv nil nil) ;; proved
;        (mv nil (list clause))))
;
;   (defevaluator my-ev my-ev-lst ((exists-non-integer-fld) (if a b c)))
;
;   (defthm non-integer-fld-clauseproc-ok
;      (implies (and (pseudo-term-listp clause)
;                    (alistp a)
;                    (my-ev (conjoin-clauses
;                            (clauses-result
;                             (non-integer-fld-clauseproc clause hints st)))
;                           a))
;               (my-ev (disjoin clause) a))
;      :rule-classes :clause-processor)
;
;   (defthm does-exist-non-integer-fld
;      (exists-non-integer-fld)
;      :hints (("goal" :clause-processor
;               (non-integer-fld-clauseproc clause nil st))))
;
;   (defthm bug
;      nil
;      :hints (("goal" :use (does-exist-non-integer-fld
;                            no-non-integer-flds)
;               :in-theory nil))
;      :rule-classes nil)

; Improved an error message produced in cases that could be due to a missing
; stobj declaration or formal parameter.  Below is a test suite, where the
; first four forms come from Jared Davis, who suggested making such an
; improvement.  Thanks to Jared Davis for reporting a bug in our initial
; implementation of this improvement.

;   (set-state-ok t)
;   (defun f (x state)
;     (mv x state))
;
;   ; Normal error:
;   (defun test1 (state)
;     (mv-let (a state)
;             (f n state)
;             (mv a state)))
;
;   ; New error (missing state):
;   (defun test2 (n)
;     (mv-let (a state)
;             (f n state)
;             (mv a state)))
;
;   (defstobj st1 fld1)
;   (defstobj st2 fld2)
;
;   (defun f2 (x state st1 st2)
;     (declare (xargs :stobjs (st1 st2)))
;     (mv x st1 st2 state))
;
;   ; New error (missing state)
;   (defun test2 (n st1 st2)
;     (declare (xargs :stobjs (st1 st2)))
;     (mv-let (a st1 st2 state)
;             (f2 n state st1 st2)
;             (mv a st1 st2 state)))
;
;   ; New error (missing user-defined stobjs)
;   (defun test3 (n st1 st2 state)
;     (mv-let (a st1 st2 state)
;             (f2 n state st1 st2)
;             (mv a st1 st2 state)))
;
;   ; New error (missing both state and user-defined stobjs)
;   (defun test4 (n st1 st2)
;     (mv-let (a st1 st2 state)
;             (f2 n state st1 st2)
;             (mv a st1 st2 state)))
;
;   (defun f3 (x state st1)
;     (declare (xargs :stobjs (st1)))
;     (mv x st1 state))
;
;   ; New error (missing both state and one user-defined stobj)
;   (defun test5 (n st1)
;     (mv-let (a st1 state)
;             (f3 n state st1)
;             (mv a st1 state)))
;
;   ; Traditional error (no mention of "may occur"):
;   (defun test6 (n st1 st2 state)
;     (declare (xargs :stobjs (st1 st2)))
;     (mv-let (a st1 x state)
;             (f2 n state st1 st2)
;             (mv a st1 x state)))

; Slightly improved error message for illegal rewrite rules, following feedback
; from David Rager.

; Removed EXPANSION from *valid-output-names* (it was not used).

; Added minor optimization to avoid calling nu-rewriter-mode and
; recursive-fn-on-fnstackp when not in nu-rewriter-mode.

; Synched up the guards of oracle-apply and ev-fncall-w, and removed
; untouchables check from ev-fncall-w (since that check is now in the guard).
; This could of course allow the user to do terrible things with ev-fncall-w
; when calling it from a :program mode function, but that's not really new.  At
; least untouchables won't be allowed for ev-fncall-w at the top level or when
; using safe-mode or guard-checking :all.

  :parents (release-notes)
  :short "ACL2 Version  6.4 (January, 2014) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes to ACL2 since Version 6.3 into the
 following categories of changes: existing features, new features, heuristic
 improvements, bug fixes, changes at the system level, Emacs support, and
 experimental versions.  Each change is described in just one category, though
 of course many changes could be placed in more than one category.</p>

 <p>See also @(see note-6-4-books) for a summary of changes made to the ACL2
 Community Books since ACL2 6.3, including the build system.</p>

 <h3>Changes to Existing Features</h3>

 <p>@(see Gag-mode) no longer saves prover output when @('PROVE') output is
 inhibited (see @(see set-inhibit-output-lst)).  This may improve performance
 slightly when certifying community books using their @('Makefile') or @(see
 BUILD::cert.pl); in particular, GCL 2.6.8 running on a Mac can now certify the
 book @('books/tau/bounders/elementary-bounders.lisp') without running out of
 space, even without explicitly turning off @(see gag-mode) (which had been
 done shortly before the Version 6.3 release).</p>

 <p>When @(see include-book) fails to find a readable @(see certificate)
 (@('.cert')) file, the error message now distinguishes between the case that
 this file is missing and the case that read permission is missing.</p>

 <p>(GCL only) Time reporting has been improved when the host Lisp is Gnu
 Common Lisp.  A key change was made in the computation of runtime (for
 example, to report in event summaries), so that it includes the ``child
 runtime''.  See @(see get-internal-time).  Also, the utility @(tsee time$) now
 gives improved information by including child runtime information, which can
 be significant; for example, it probably includes compile time, while the
 ``seconds runtime'' statistic (still) does not.  Recent versions of GCL might
 also provide system runtime and child system runtime.  See @(see time$).
 Thanks to Camm Maguire for suggesting these improvements to @('time$') and
 providing an initial implementation for them.</p>

 <p>Fixed a bug in an ACL2 system function, @('our-truename'), which returns
 the ``true name'' for a file name, when supplied with an optional second
 argument.  Thanks to Camm Maguire for bringing this bug to our attention.</p>

 <p>The wording in theory warnings has been improved, to avoid giving the
 impression that you are newly disabling a built-in rule in the case that it
 merely remains disabled.</p>

 <p>As requested by Sol Swords, erroneous evaluations of system function
 @('magic-ev-fncall') that had produced a message, @('msg'), will now also
 return that message.  The following example, sent by Sol, illustrates the fix:
 before, evaluation of @('(magic-ev-fncall 'cons '(a) state nil nil)') printed
 a message (to the comment window) and then returned @('(mv t nil)'), but now
 it returns @('mv t <msg>'), where @('<msg>') denotes the message (printed with
 the @(tsee fmt) @('~@') directive).</p>

 <p>Fixed @(':')@(tsee pbt) to avoid printing the bodies of @(tsee defconst)
 forms.  Thanks to Jared Davis for pointing out the large output when the body
 is a large character string.</p>

 <p>A new output type, @('history'), now controls the printing of
 history-related information; see @(tsee set-inhibit-output-lst).  The unused
 output type, @('expansion'), is no longer supported, i.e., is no longer a
 member of the list @('*valid-output-names*').  Because of this change,
 printing of information when undoing, as by @(':')@(tsee u), will now take
 place even when @('event') output is inhibited (if @('history') output is not
 inhibited); we thank Sol Swords for requesting that change.</p>

 <p>The @(':')@(tsee loop-stopper) field of a rule of class @(':')@(tsee rewrite),
 should still be a list of lists @('(var1 var2 fn1 fn2 ... fnk)'), where
 @('var1') and @('var2') are variables and the @('fni') are symbols.  But
 formerly each @('fni') was required to be a function symbol; now, it can be a
 macro alias for a function symbol (see @(tsee add-macro-alias)).  For example,
 the following is a valid @(':')@(tsee loop-stopper) field: @('((x y +))').</p>

 <p>The restrictions on utilities @('oracle-apply') and @('oracle-funcall')
 have been updated in order to avoid potentially confusing or inappropriate
 results, by imposing the following new requirements on their first argument,
 which must still be a function symbol.  That symbol must not be
 @('if') (formerly the illegal symbol was @(tsee return-last)); it must not be
 a key of the alist, @('*ttag-fns-and-macros*'); it must not be
 untouchable (see @(tsee remove-untouchable)); and it must not be a @(tsee
 stobj) creator (see @(tsee defstobj)).</p>

 <p>The @(see table) guard on @(tsee dive-into-macros-table) has been
 strengthened in order to avoid calling untouchable functions (see @(tsee
 remove-untouchable)).</p>

 <h3>New Features</h3>

 <p>We have added a tool for writing out useful information about a book's
 event names when certifying the book.  See @(see bookdata).  Thanks to Dave
 Greve for requesting this tool and participating in its specification.</p>

 <p>There are new analogues of @(tsee add-include-book-dir) and @(tsee
 delete-include-book-dir): @(tsee add-include-book-dir!) and @(tsee
 delete-include-book-dir!), respectively.  The new utilities are similar to
 their existing counterparts, except that their effects are not @(see local) to
 enclosing @(see books) or @(tsee encapsulate) events.  Thanks to Shilpi Goel
 for requesting this enhancement.</p>

 <p>The class of @(see congruence) rules has been broadened considerably, so
 that one can restrict to patterns.  For example, a congruence rule can now
 state that an equivalence is maintained for the term @('(mv-nth 1 (f (cons u
 v) y 'a))') when rewriting @('y').  See @(see patterned-congruence).  Thanks
 to Sol Swords for requesting this feature.</p>

 <h3>Heuristic Improvements</h3>

 <p>(None to report this time.)</p>

 <h3>Bug Fixes</h3>

 <p>Fixed a soundness bug in the handling of hypotheses of conditional
 @(':')@(tsee definition) rules invoked during rewriting by applying
 @(':')@(tsee expand) @(see hints).  See (defxdoc note-6-4 ...) in community
 book @('system/doc/acl2-doc.lisp') for a proof of @('nil') in ACL2 Version_6.3
 that exploits this bug.</p>

 <p>It had been possible to update a @(see stobj) (either an ordinary stobj or
 an abstract stobjs) so that it no longer satisfies its recognizer predicate.
 This soundness bug has been fixed.  Thanks to Jared Davis and Sol Swords for
 pointing out this bug, making useful observations about the issue, and sending
 proofs of @('nil'), one of which may be found in a Lisp comment in the
 defxdoc form for @('note-6-4').</p>

 <p>Fixed a long-standing soundness bug (found at least as far back as Version
 1.9!) in the checking done for @(see congruence) rules.  There had failed to
 be a check that the new variable on the right-hand side of the conclusion is
 indeed new.  The following example is shown in detail as a comment in function
 @('interpret-term-as-congruence-rule'), ACL2 source file @('defthm.lisp'),
 where it is used to prove @('nil') in Version  6.3.</p>

 @({
 (implies (e y1 y2)
          (equal (h y2 y1)
                 (h y2 y2)))
 })

 <p>Fixed a bug in the ACL2 character reader that was causing an end-of-file
 error when reading from a string ending in <tt>\"#\\c\"</tt>, for @('c') a
 character or non-terminating sequence of characters.  Thanks to Jared Davis
 for sending the following example, whose evaluation in raw Lisp had caused an
 error.</p>

 @({
 (let* ((*readtable* *acl2-readtable*)
        (stream (make-string-input-stream \"#\\\\a\"))
        (x1 (read stream nil :EOF))
        (x2 (read stream nil :EOF)))
   (list x1 x2))
 })

 <p>(GCL only) Improved the automatic proclaiming mechanism used for GCL
 builds, in particular to avoid computing a return type when a term is detected
 that could come from a call of @(tsee non-exec), and to do a more complete job
 for calls of @(tsee return-last).</p>

 <p>(CCL only) A CCL bug was treating filenames of the form @('\"~/user/...\"')
 as @('\"~/...\"').  Thanks to Gary Byers for sending us a CCL-specific form
 that is now included in the ACL2 sources, which avoids this problem.</p>

 <p>Attempts to submit @(tsee congruence) rules had unfortunate consequences in
 the case that the function ``symbol'' is @(tsee if) or @(tsee quote): for
 @('if'), rules were appropriately ignored because of the special handling that
 ACL2 already gives to calls of @(tsee if) for congruence-based reasoning,
 while for @('quote'), it was possible to get a hard Lisp error.  Now, attempts
 to submit such rules will result in a clear ACL2 error.</p>

 <p>It had been possible to get a confusing raw Lisp error when submitting a
 @(tsee defstobj) event whose first argument is not a symbol, as in:
 @('(defstobj (fld :type integer :initially 0))').  That user error is now
 reported gracefully by ACL2.</p>

 <p>When an @(tsee include-book) form is executed for a non-existent book, we
 no longer get a bogus warning about a missing compiled file.  (Of course the
 compiled file is missing when the book itself is missing!  So there's no need
 to report this fact.)  Thanks to Caleb Eggensperger for bringing this issue to
 our attention.</p>

 <h3>Changes at the System Level</h3>

 <p>The ACL2 system @(see documentation) has been reworked for the @(see XDOC)
 framework developed by Jared Davis.  While the ACL2 User's Manual can still be
 built, it is now possible for the ACL2 community to contribute to the ACL2
 system documentation, in community book
 <tt>books/system/doc/acl2-doc.lisp</tt>; see comments near the top of that
 book.  Now that both the ACL2 system documentation and much of the community
 books documentation are written in @(see XDOC) format, we hope the ACL2
 community will add links from the ACL2 system documentation topics to book
 documentation topics.  Note that @(':')@(see doc) still works at the terminal,
 but it is based on the new system, and other terminal-based access to the
 documentation has been eliminated (for example @(':more')).  Thanks to Jared
 for all his work contributing to this enhancement.</p>

 <p>Fixed community books @('books/Makefile-generic') and also
 @('books/Makefile'), which now has filename @('books/GNUmakefile'), to work
 with Cygwin (Windows).  Thanks to Harsh Raju Chamarthi for his substantial
 help.</p>

 <p>The guard for system function @('ev-fncall-w') now includes an arity
 check.</p>

 <h3>EMACS Support</h3>

 <p>There is now an Emacs utility for browsing the hypertext documentation for
 ACL2 and the community books.  This browser, ACL2-Doc, essentially serves as a
 replacement for Emacs Info, which can no longer be used to browse the
 documentation.  ACL2-Doc can be used not just for the ACL2 User's Manual but
 also for the ACL2+Books Manual.  It is loaded automatically into Emacs if you
 load the file <tt>emacs/emacs-acl2.el</tt>.  See @(see acl2-doc) and @(see
 documentation).</p>

 <h3>Experimental/Alternate Versions</h3>

 <p>(None to report this time.)</p>")

(defxdoc note-6-5

; Total number of release note items: 49.

; Improved error message when :trans1 is given other than a true-list.
; Formerly, :trans1 (foo 3 . 4) would seem to suggest that foo is not a macro
; even when it is.

; Improved error message for bad calls of with-local-stobj, especially when the
; indicated creator function (whether or not provided explicitly) is wrong.
; Thanks to Jared Davis for bringing this issue to our attention.

; Added new :doc topic, type-alist, and added links to it.  Thanks to David
; Rager for discussions leading to this addition.

; Here is the example from Jared Davis and Sol Swords that prompted us to make
; functions untouchable that can call set-w in ways that we do not control
; adequately.
;
;   $ cat sub.acl2
;   (in-package "ACL2")
;   (include-book "std/util/bstar" :dir :system)
;   (set-state-ok t)
;
;   (defun run-as-toplevel-command-and-try-to-cheat (real-form other-form ctx state)
;      (declare (xargs :mode :program))
;      (b* ((orig-world (w state))
;           (orig-defun-mode (default-defun-mode orig-world))
;           ((er ans) (trans-eval real-form ctx state t)))
;        (cw "ans: ~x0~%" ans)
;        (maybe-add-command-landmark
;         orig-world orig-defun-mode other-form ans state)))
;
;   (run-as-toplevel-command-and-try-to-cheat
;     '(defun baz (x) x) '(defun baz (x) (+ 1 x)) "ho" state)
;
;   (defthm baz-of-three
;      (equal (baz 3) 3)
;      :rule-classes nil)
;
;   $ cat sub.lisp
;   (in-package "ACL2")
;
;   $ cat top.lisp
;   (in-package "ACL2")
;   (include-book "sub")
;
;   (defthm baz-of-three-alt
;      (equal (baz 3) 4)
;      :hints(("Goal" :in-theory '(baz))))
;
;   (defthm shoot
;      nil
;      :rule-classes nil
;      :hints(("Goal"
;              :use ((:instance baz-of-three-alt)
;                    (:instance baz-of-three)))))

; We fixed a small bug in extended-ancestors, to guarantee that argument to
; canonical-ancestors is canonical.  We have not attempted to analyze how
; serious this bug may be.

; Here is a proof of nil following the example from Sol Swords related to the
; "resizable array of stobjs" bug documented in the string below.

;   (defstobj a$
;     (a$.f :type (integer 0 *) :initially 0))
;
;   (defstobj b$
;     (b$.as :type (array a$ (0)) :resizable t))
;
;   (defun resize-new-b-and-get-af ()
;     (with-local-stobj b$
;       (mv-let (result b$)
;         (let ((b$ (resize-b$.as 10 b$)))
;           (stobj-let ((a$ (b$.asi 0 b$)))
;                      (res)
;                      (a$.f a$)
;                      (mv res b$)))
;         result)))
;
;   (thm (equal (resize-new-b-and-get-af) 0))
;
;   (thm (equal (resize-new-b-and-get-af) nil)
;        :hints (("Goal" :in-theory (disable (resize-new-b-and-get-af)))))

; Here is a slight variant of an example from Sol Swords that illustrates the
; "wrongly disallowing calls of exported functions" bug discussed below.  The
; only change is to make it self-contained, without including any books.

;   (defstobj st1 fld1)
;   (defstobj st2$c fld2$c)
;
;   (defun update-st2$c (st1 st2$c)
;      (declare (xargs :stobjs (st1 st2$c)))
;      (update-fld2$c (fld1 st1) st2$c))
;
;   (defun-nx update-st2$a (st1 st2$a)
;      (declare (xargs :stobjs (st1)))
;      st1)
;
;   (defun create-st2$a ()
;      (declare (xargs :guard t))
;      (list nil))
;
;   (defun-nx st2-corr (st2$c st2$a)
;      (and (st2$cp st2$c)
;           (equal st2$c st2$a)))
;
;   (local (in-theory (e/d (update-nth nth len)
;                           ((st2-corr)))))
;
;   (local (defthm equal-of-len
;             (implies (syntaxp (quotep y))
;                      (equal (equal (len x) y)
;                             (if (zp y)
;                                 (and (equal y 0) (atom x))
;                               (and (consp x)
;                                    (equal (len (cdr x)) (1- y))))))))
;
;   (progn
;    (defthm create-st2{correspondence}
;      (st2-corr (create-st2$c) (create-st2$a))
;      :rule-classes nil)
;    (defthm create-st2{preserved}
;      (st2$cp (create-st2$a))
;      :rule-classes nil)
;    (defthm update-st2{correspondence}
;      (implies (and (st2-corr st2$c st2) (st1p st1))
;           (st2-corr (update-st2$c st1 st2$c)
;                     (update-st2$a st1 st2)))
;      :rule-classes nil)
;    (defthm update-st2{preserved}
;      (implies (and (st2$cp st2) (st1p st1))
;           (st2$cp (update-st2$a st1 st2)))
;      :rule-classes nil)
;    (defabsstobj st2
;      :concrete st2$c
;      :creator (create-st2 :logic create-st2$a
;                        :exec create-st2$c)
;      :recognizer (st2p :logic st2$cp :exec st2$cp)
;      :corr-fn st2-corr
;      :exports ((update-st2 :logic update-st2$a
;                         :exec update-st2$c))))
;
;   (defun update-st2-again (a b st1 st2)
;     (declare (xargs :stobjs (st1 st2))
;              (ignorable a b))
;     (update-st2 st1 st2))

; Below is the proof of nil from Sol Swords for the bug involving failure to
; return a stobj producer variable.  We also intersperse a simpler version of
; his example that doesn't prove nil but does provide unexpected behavior.

;   (defstobj st1 fld1)
;   (defstobj st2 fld2)
;   (defstobj st3 (fld3 :type st2))
;
;   ; The following simpler version of Sol's example leads to the unexpected
;   ; behavior shown below.
;
;   (set-irrelevant-formals-ok t) ; oddly needed for the next definition
;
;   (defun bad-alt (st1 st3 val)
;     (declare (xargs :guard t :stobjs (st1 st3)))
;     (stobj-let ((st2 (fld3 st3))) ;; unused
;                (st1)
;                (update-fld1 val st1)
;                nil))
;
;   ACL2 !>(fld1 st1)
;   NIL
;   ACL2 !>(bad-alt st1 st3 7)
;   NIL
;   ACL2 !>(fld1 st1) ; St1 was not returned above, but has changed!
;   7
;   ACL2 !>
;
;   ; Now returning to Sol's example:
;
;   (defun bad ()
;     (declare (xargs :guard t))
;     (with-local-stobj st1
;       (mv-let (res st1)
;         (let* ((st1 (update-fld1 'abcd st1)))
;           (with-local-stobj st3
;             (mv-let (res st3)
;               (prog2$
;                ;; updates st1 but doesn't return it
;                (stobj-let ((st2 (fld3 st3))) ;; unused
;                           (st1)
;                           (update-fld1 'wxyz st1)
;                           nil)
;                (mv (equal (fld1 st1) 'abcd) st3))
;               (mv res st1))))
;         res)))
;
;   (defthm bad-conflicts
;     nil
;     :hints (("goal" :use bad :in-theory (disable bad)))
;     :rule-classes nil)

; Fixed error message for illegal :exit form of trace$, which had complained
; about :entry instead of :exit.  Thanks to David Rager for bringing this error
; to our attention.

; Enhanced error message from Step 1 of certify-book to clarify how packages
; may be the issue, pointing to :DOC certify-book.  Thanks to Ben Selfridge for
; bringing this issue to our attention and for helpful follow-up emails.

; Fixed an error message for ill-formed :expand hints to mention that :lambdas
; is legal.

; Improved the error message when attempting to apply trace$ to a macro.

; Here we provide the comment about the ``mbe and invariant-risk''
; modification, as promised below.  We begin with the example from Jared Davis
; that led us to this modification.  The example assumes svn versions of
; acl2+books from early June 2014.  It shows how an undesirable error can
; occur; after that we present a simpler example illustrating the issue.  The
; guard error is coming from the :logic code of an mbe call, even though the
; intention was that by calling a :program mode function, one would have raw
; Lisp semantics, where an mbe call reduces to its :exec code.

;   (include-book "defsort/uniquep" :dir :system)
;   (include-book "std/util/defprojection" :dir :system)
;
;   ;; note: uses a local stobj:
;   (std::defprojection my-strip-cars ((x alistp)) (car x))
;
;   (defun my-sanity-check (x)
;     (declare (xargs :mode :program))
;     (and (alistp x)
;          (uniquep (my-strip-cars x))))

; and then:

;   ACL2 !>(my-sanity-check '(("foo" . 1) ("bar" . 2) ("baz" . 3)))
;
;
;   ACL2 Error in TOP-LEVEL: The guard for the function call
;   (ACL2::NO-DUPLICATESP-EQL-EXEC$GUARD-CHECK ACL2::L), which is
;   (EQLABLE-LISTP ACL2::L), is violated by the arguments in the call
;   (ACL2::NO-DUPLICATESP-EQL-EXEC$GUARD-CHECK '("foo" "bar" "baz")).
;   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.

; Here is a simpler example to illustrate the issue.  The point is that
; typically, when one calls a :logic mode function from a :program mode
; function (where safe-mode is off and guard-checking isn't set to :none or
; :all), one expects to slip into raw Lisp, resulting in raw Lisp execution for
; that :logic mode function call.  So in that case, if the :logic mode function
; has a call of mbe, one expects its :exec code to execute, not its :logic
; code.

;   (defstobj st (fld :type integer :initially 0))
;
;   (defun lgc (st)
;     (declare (xargs :mode :logic
;                     :stobjs st
;                     :verify-guards nil))
;     (mbe :logic (prog2$ (cw "@@@LOGIC@@@~%")
;                         (update-fld 3 st))
;          :exec (prog2$ (cw "@@@EXEC@@@~%")
;                        (update-fld 4 st))))
;
;   (defun pgm (st)
;     (declare (xargs :mode :program
;                     :stobjs st))
;     (lgc st))

; Then in Version_6.4:

;   ACL2 !>(pgm st)
;   @@@LOGIC@@@
;   <st>
;   ACL2 !>

; After this fix:

;   ACL2 !>(pgm st)
;   @@@EXEC@@@
;   <st>
;   ACL2 !>

; As a final note, we consider functions with "invariant-risk": :program mode
; functions for which a call might lead to a call of a stobj updater with a
; non-trivial guard.  We need to avoid ill-guarded stobj updates; but guards
; aren't checked in raw Lisp.  Our solution is to generate *1* code for any
; such function that treats guard-checking values t and nil more or less as
; :all and :none, respectively, and also binds a global (Lisp special) variable
; *mbe-as-exec* [since renamed to **1*-as-raw*] to t, which (in the source
; function, oneify) replaces a :logic mode return-last call as its (oneified)
; :exec code.  The upshot is that when safe-mode is off and guard-checking
; isn't :all or :none, then any mbe call under a :program mode function call
; will reduce to its :exec code, even if that mbe call is in a :logic mode
; function -- either because we have slipped into raw Lisp or because
; invariant-risk has resulted in binding *mbe-as-exec* to t.  Subtle exception:
; We bind *mbe-as-exec* to nil when calling raw-ev-fncall on a :logic mode
; function, in case that raw-ev-fncall is called for invoking a function during
; a proof, where we must stick to logical semantics for mbe.  Note that all
; this can be defeated, leading to better performance but rendering the system
; potentially unsound, by evaluating the following form in raw Lisp: (setq
; *ignore-invariant-risk* t).

; Fixed a bug in with-base-10, which had used eq instead of eql to compare
; numbers.

; Tweaked convert-type-set-to-term.

; Improved a warning in chk-acceptable-linear-rule2 to clarify that only
; relevant triggers are a problem for free variables.

; Added function find-symbol-in-current-package, and used it to speed up (we
; think) some printing routines.  Thanks to Jared Davis for pointing out
; potential value of such a change.

; Here is the example sent by Dmitry Nadezhin to illustrate the tau soundness
; bug, described below and now fixed.

;   (in-package "ACL2")
;
;   (defund p (x)
;      (or (equal x 0) (equal x 1)))
;
;   (defund q (x)
;      (equal x x))
;
;   (defthmd lemma
;      (implies
;        (and (integerp x) (> x 5))
;        (q x))
;      :hints (("Goal" :in-theory (enable q))))
;
;   (defthm bad-theorem
;      (not (p x))
;      :hints (("Goal" :use (:instance lemma))))
;
;   (defthm nonsense
;      nil
;      :hints (("Goal" :use (:instance bad-theorem (x 0))))
;      :rule-classes nil)

; Fixed a bug in memoize-raw.lisp, function
; memoize-summary-after-compute-calls-and-times, found in a GCL-based
; regression of ACL2(h).

; The following email sent on 3/19/2014 summarizes the reduction in regression
; time due to a suggestion from Sol Swords regarding make-event (described in
; the section Changes to Existing Features) that improved the new ``rolling
; back'' feature (described in the section on Heuristic Improvements).
;
;   I implemented (acl2-devel svn revision 1235, acl2-books svn revision
;   2550) Sol's great idea of not considering make-event (with non-nil
;   :check-expansion) for determining the world roll-back, and in fact not
;   doing the check-expansion when including the book at the end of
;   certification.  (And happily, it only took me about an hour to write
;   the code and update the documentation.)  The speed-up was much more
;   impressive this time on an "everything" regression -- in the range of
;   10%.  We might expect even more on average, since that regression
;   includes one book that takes over an hour to prove and probably has
;   very few include-books.  Here are the numbers.
;
;   ; new
;   46987.408u 1663.583s 2:18:07.87
;
;   ; old
;   52573.741u 2077.561s 2:32:35.99
;
;   ; speedup based on user+system times
;   (- 1 (/ (+ 46987.408 1663.583)
;           (+ 52573.741 2077.561)))
;   = 0.10979264501328811
;
;   ; speedup based on wall-clock time
;   (- 1 (/ (+ (* 60 138)  7.87)
;           (+ (* 60 152) 35.99)))
;   = 0.09481443295591185

  :parents (release-notes)
  :short "ACL2 Version  6.5 (August, 2014) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes to ACL2 since Version 6.4 into the
 following categories of changes: existing features, new features, heuristic
 improvements, bug fixes, changes at the system level, Emacs support, and
 experimental versions.  Each change is described in just one category, though
 of course many changes could be placed in more than one category.</p>

 <p>See also @(see note-6-5-books) for a summary of changes made to the ACL2
 Community Books since ACL2 6.4, including the build system.</p>

 <h3>Changes to Existing Features</h3>

 <p>The @(tsee brr@) command now supports inputs @(':initial-ttree') and
 @(':final-ttree').  Thanks to David Rager for a request leading to these
 enhancements.  See @(see ttree) for a discussion of the tag-tree structures
 returned for these inputs.</p>

 <p>(GCL only) A restriction for structure-sharing (as described in a remark,
 ``Remark on print-circle-files''; see @(see print-control)) involving GCL has
 been removed, since this is no longer required for the latest GCL
 versions (2.6.8 and 2.6.10).  Thanks to Jared Davis and Camm Maguire for
 useful discussions and this GCL improvement.</p>

 <p>The keyword commands @(':exit') and @(':quit') are disabled inside @(see
 brr), in order to avoid accidental exits from ACL2.  Thanks to David Rager for
 suggesting such a change.</p>

 <p>For calls of @(tsee make-event) made during the @(tsee include-book) phase
 of @(tsee certify-book), keyword @(':check-expansion') no longer causes
 evaluation of the first argument of @('make-event'); rather, the value of
 @(':check-expansion') is simply used as the expansion.  Thanks to Sol Swords
 for suggesting this change, which made it reasonable to ignore such
 @('make-event') forms when determining the ``rolling back'' before that
 @('include-book') phase, as described in the next section.</p>

 <p>The form @('(reset-prehistory nil)') now is a no-op if @(see state) global
 <tt>'</tt>@('skip-reset-prehistory') has a non-@('nil') value.  Thanks to Sol
 Swords for requesting this feature (in support of infrastructure for
 certifying the @(see community-books)).</p>

 <p>The output from @(':')@(tsee pr), @(':')@(tsee pr!), @(':')@(tsee pl), and
 @(':')@(tsee show-bodies) has been tweaked.  Thanks to a suggestion from Ben
 Selfridge, such output now shows the hypotheses (the @('Hyps') field) above
 the left-hand side and right-hand side of a @(see rewrite) rule (@('Lhs') and
 @('Rhs'), respectively).  The @('Equiv') field has also been moved up before
 the @('Lhs') field in such output for rewrite rules, and this field has been
 added for @(see elim) rules.  Finally, the @('Hyps') field now appears above
 the @('Term') field in such output for @(see type-prescription) rules.</p>

 <p>Rules of class @(':')@(tsee linear) may now be @(see monitor)ed.  Thanks to
 David Rager for requesting this enhancement.</p>

 <p>When forcing (see @(tsee force)) is applied, we now always see the
 appropriate @(see executable-counterpart) @(see rune), @(`*force-xrune*`), in
 the proof output and summary; this hadn't previously been the case.  Thanks to
 Robert Krug for bringing this issue to our attention.</p>

 <p>The default value for the @(':write-port') keyword argument of @(tsee
 certify-book) is now @('t'), as was already claimed by the documentation.
 Thus, a @('.port') file will be written when a book is certified, making it
 more likely that a subsequent @(tsee include-book) will complete without error
 even if the book has been modified without recertification.  Note that a
 change by Sol Swords to the build system for the @(see community-books) now
 sets an environment variable to guarantee that @('write-port') is true,
 independent of this change.  On a related note: the unadvertised environment
 variable @('ACL2_WRITE_PORT') is now handled more appropriately, by interning
 its upcased argument into the ACL2 package.</p>

 <p>The following changes can make it easier to include books that are
 uncertified or have corrupted compiled files.  Thanks to Sol Swords for
 sending helpful, relevant examples and for subsequent discussions helping to
 lead to these changes.</p>

 <ul>

 <li>It is no longer illegal to call @('set-compiler-enabled') within @(see
 books).  See @(see compilation), which shows how to do this in order to avoid
 loading the compiled file not only for a book specified by @(tsee
 include-book) but also for all books included under that book.  Also see @(see
 compilation) for an analogous utility, @('(set-port-file-enabled nil state)'),
 to avoid loading @('.port') files.  (For background on @('.port') files, see
 @(see uncertified-books)).</li>

 <li>In situations where it is legal to include an uncertified book (typically,
 any time other than during @(tsee certify-book), ACL2 nonetheless could fail
 to do so when an error occurred while reading a @(see certificate) file.  ACL2
 can now instead include the book successfully as an uncertified book.</li>

 <li>When hard raw Lisp errors occur during loading of compiled files on behalf
 of an @(tsee include-book) event, that event can now complete successfully
 much as though the compiled file were simply missing.</li>

 </ul>

 <p>(SBCL only) The function @(tsee setenv$) is now supported in SBCL, which
 had been the one supported host Lisp for which @('setenv$') had not been
 supported.  Thanks to Jared Davis for pointing the way to this
 improvement.</p>

 <p>Built-in @(see equality-variants) have been modified in order to support
 suitable guard-checking.  For example, evaluation of the form @('(member-eq 3
 '(4 5))'), or equivalently, @('(member 3 '(4 5) :test 'eq)'), had produced a
 value of @('nil'), but now we get what one should have expected: a guard
 violation (since @(tsee member-eq) is intended to compare symbols).  Thanks to
 Yan Peng for raising a question on the acl2-help mailing list that led us to
 make this improvement.</p>

 <p>When the @(':')@(tsee pe) command is supplied the macro alias for a
 function symbol (see @(see macro-aliases-table)), the system will now print
 @(see events) not only for the macro symbol but also for the corresponding
 function symbol.  Thanks to Cuong Chau, Jared Davis, Shilpi Goel, Sol Swords,
 and Warren Hunt for requesting this enhancement.</p>

 <p>Some evaluations of forms @('(mbe :logic L :exec E)') are more efficient or
 avoid guard violations, by evaluation of the @(':exec') form (@('E')) instead
 of the @(':logic') form (@('L')).  If the @(tsee mbe) call is in a
 @(':')@(tsee program) mode function definition, the @(':exec') code will be
 evaluated, where unlike before, this is true even when guard-checking is
 @(':all') or @(':none') (see @(see set-guard-checking)).  If the @('mbe') call
 is in a @(':')@(tsee logic) mode function definition, the change is that the
 @(':exec') code will be evaluated when there is a superior call of a
 @(':program') mode function, except when guard-checking is @(':all') or
 @(':none') or in a couple of technical cases (see a comment in the source code
 for constant @('**1*-as-raw*') [formerly @('*mbe-as-exec*')] for details).
 This use of @(':exec') code had been defeated when the superior @(':program')
 mode function had an ``invariant-risk'' of making ill-guarded stobj updates.
 However, there is no change in the case of safe-mode, which is used during
 evaluation of @(tsee defconst), @(tsee value-triple), and @(tsee defpkg)
 forms, and during macroexpansion: the @(':logic') and @(':exec') forms are
 still both evaluated and checked for equality.  Thanks to Jared Davis for
 reporting this issue and for helpful chats about it.  For more information,
 see the comment about ``mbe and invariant-risk'' in the form @('(defxdoc
 note-6-5 ...)') in @(see community-books) file
 @('books/system/doc/acl2-doc.lisp').</p>

 <p>The utility @(tsee save-exec) has a new (optional) keyword argument,
 @(':init-forms'), which specifies a list of forms to evaluate when first
 entering the ACL2 read-eval-print loop, @(tsee lp).  Thanks to Jared Davis for
 requesting this enhancement.</p>

 <h3>New Features</h3>

 <p>A @(tsee defstobj) event may now include the keyword argument
 @(':non-memoizable').  When its value if @('t'), then for ACL2(h) builds (see
 @(see hons-and-memoization)), code will run somewhat faster.  In a little test
 doing just reads and writes to a stobj array in ACL2(h), it took 26% less time
 when the stobj to be written was introduced by @(tsee defstobj) using
 @(':non-memoizable t').  Thanks to Warren Hunt for requesting this
 feature and helping to develop the test.</p>

 <p>See @(tsee set-print-base-radix) for a utility that may be preferable to
 @(tsee set-print-base), since it essentially calls @(tsee set-print-radix)
 automatically.  Thanks to David Rager, Shilpi Goel, and David Hardin for
 participating in an acl2-help mailing list discussion that motivated this
 feature.</p>

 <h3>Heuristic Improvements</h3>

 <p>One of the steps performed by @(tsee certify-book) has traditionally been
 to check for local incompatibilities (see @(see local-incompatibility)) after
 admitting all the events in the book.  This step involved rolling back the
 logical @(see world) to what it was at the start of certification, and then
 including the book (see @(see include-book)).  As an optimization, we now
 avoid rolling back the world more than necessary; see @(tsee certify-book),
 specifically the discussion of Step 3.  We thank Sol Swords for requesting
 this optimization and for making a suggestion that improved it, pertaining to
 @(tsee make-event) (described above).  We also thank Jared Davis for alerting
 us to an issue that turned out to be caused by a bug in our initial
 implementation.  Sol has reported a nearly 20% reduction in time for
 certifying a certain large collection of books.</p>

 <p>The test for redundancy of @(tsee encapsulate) @(see events) has been made
 more efficient.  Also, while the criterion itself remains unchanged, the
 documentation has been made more accurate; see @(see redundant-encapsulate).
 We observed more than a 2% reduction in time for the ``everything'' regression
 target, but we observed more than 23% of the time eliminated for the form
 @('(time$ (include-book \"doc/top\" :dir :system))') after building the
 documentation.  Thanks to David Rager for bringing that particular book to our
 attention, as one that took a long time to include.</p>

 <p>The function @(tsee pairlis$) is now tail-recursive, hence potentially more
 efficient.  More precisely, its definition for the logic remains unchanged,
 but using @(tsee mbe), for execution it calls a new tail-recursive function,
 @('pairlis$-tailrec').  Thanks to Jared Davis for requesting this
 improvement.</p>

 <p>@(see Linear) arithmetic has been strengthened slightly so that immediately
 after simplification has ``settled down'' (see @(see
 hints-and-the-waterfall)), the unrewritten conclusion of a @(':')@(tsee
 linear) rule may be used when normally this would not be the case.  Thanks to
 Robert Krug for reminding us of examples we had encountered that could benefit
 from some such a change, and for pointing us to some relevant source code.
 This improvement generally causes an extra pass through the simplifier; hence
 we have observed approximately a 2% slowdown in the regression suite.  Note
 that machinery is now in place for installing additional ``desperation
 heuristics''; perhaps the ACL2 community will have some to suggest.</p>

 <h3>Bug Fixes</h3>

 <p>We fixed a soundness bug in how the @(see tau-system) processed calls of
 @('if').  Thanks to Dmitry Nadezhin for reporting this bug by sending a simple
 example that exploited it to prove @('nil').  To see that example, see the
 comment about ``tau soundness bug'' in the form @('(defxdoc note-6-5 ...)') in
 @(see community-books) file @('books/system/doc/acl2-doc.lisp').</p>

 <p>We fixed a soundness bug for nested @(see stobj)s (see @(see stobj-let)).
 In the case of a stobj producer variable that is not a child stobj, it had
 been possible to update that stobj without returning it.  Thanks to Sol Swords
 for reporting this bug and providing a corresponding proof of @('nil'), which
 is included in a comment in the form @('(defxdoc note-6-5 ...)') in @(see
 community-books) file @('books/system/doc/acl2-doc.lisp').)</p>

 <p>We fixed a soundness bug in the case of a @(see stobj) with a field that is
 a resizable array of stobjs.  Thanks to Sol Swords for sending a proof of
 @('nil') exploiting this bug, together with some helpful analysis attributing
 the bug to a mistake in the generated logical definition of the corresponding
 resize function.  (His example is included in a comment in the form
 @('(defxdoc note-6-5 ...)') in @(see community-books) file
 @('books/system/doc/acl2-doc.lisp').)</p>

 <p>(ACL2(h) only) We fixed a soundness bug involving the interaction of @(tsee
 stobj-let) and @(tsee memoize), which thus is only a bug in ACL2(h) (see @(see
 hons-and-memoization)), not in ACL2.  The fix was to add code to
 @('stobj-let') that clears the memoization table for the parent stobj if any
 child stobj is updated.  An example proof of @('nil') before this fix may be
 found in the ACL2 source file @('translate.lisp'), in a comment in the
 function @('stobj-let-fn-raw').</p>

 <p>(Allegro CL and CMUCL only) We fixed bugs in function @(tsee princ$) when
 invoked in an ACL2 image with Allegro CL or CMUCL as the host Lisp
 implementation.  In Allegro CL, when printing a complex number in base 16,
 lower case characters were produced, for example printing @('#C(c d)') instead
 of the characters predicted by the axioms, namely @('#C(C D)').  In some
 recent versions of CMUCL, after executing the forms @('(set-print-base 16
 state)') and @('(set-print-case :downcase state)'), hex digits were printed in
 lower case, unlike other host Lisps and contrary to the ACL2 axioms: for
 example, 1000 base 10 was printed as @('3e8') rather than as predicted by the
 ACL2 axioms, @('3E8').  Thanks to Jared Davis for bringing these bugs to our
 attention, and also for pointing out excessive printing of a big note about
 such printing in Allegro CL.  We now avoid that note altogether, which had
 warned that printing numbers in base 16 can be slow for Allegro CL.  In fact,
 that performance issue has been eliminated: for example, after evaluating
 @('(defconst *c* (expt 2 200000))') and @('(set-print-base 16 state)'), the
 form @('(time$ (pprogn (princ$ *c* *standard-co* state) state))') reports
 taking about 3 seconds before the change but about 1/100 seconds after the
 change.  Thanks to David Margolies of Franz Inc. for passing along a remark
 from a colleague that showed how to make this improvement.</p>

 <p>The utility @(tsee sys-call+) can now only be called if there is an active
 @(see trust-tag), which is the restriction that was already in place for
 @(tsee sys-call).  This plugs a potential soundness hole.</p>

 <p>We have made several system functions untouchable (see @(see
 remove-untouchable)), in order to prevent soundness bugs.  We thank Jared
 Davis and Sol Swords for sending us an example that used a call of one of
 these functions to prove @('nil').  We have placed that example into a comment
 in Community Books file <tt>system/doc/acl2-doc.lisp</tt>, form @('(defxdoc
 note-6-5 ...)').</p>

 <p>The @('brr') command, @(':wonp'), had not been installed for use after
 @(':eval') even though this was claimed in the documentation (see @(see
 brr-commands)).  This has been fixed.  Thanks to David Rager for bringing this
 issue to our attention.</p>

 <p>Fixed a bug in @(tsee make-event) that could cause @(tsee include-book) to
 fail with a bogus message about ``the set of ttags permitted
 in the current context.''  Thanks to Sol Swords and Anna Slobodova for
 reporting this bug, and to Sol for sending a small example that illustrated
 the problem.</p>

 <p>Fixed a bug that was wrongly disallowing certain calls of exported
 functions for abstract stobjs (see @(see defabsstobj)).  Thanks to Sol Swords
 for reporting this bug, supplying an example illustrating the bug, and
 suggesting a nice fix.  A slight variant of his example is included in a
 comment in Community Books file <tt>system/doc/acl2-doc.lisp</tt>, form
 @('(defxdoc note-6-5 ...)').</p>

 <p>When a macro symbol @('mac') was a macro-alias for a function symbol
 @('f') (see @(see macro-aliases-table)), then the form @('(verify-guards+
 mac)') caused an error when encountered while including an uncertified book.
 This problem has been fixed.  Thanks to Jared Davis for pointing out the
 problem and sending a simple example to illustrate it.  Technical Note: the
 actual problem was that @(tsee verify-guards+) generates a call of @(tsee
 make-event) with an @(':expansion?') argument, and that argument needed to be
 ignored (as it now is, after the fix) when including an uncertified book.</p>

 <p>The @(tsee walkabout) utility could cause hard Lisp errors when the current
 package is other than @('\"ACL2\"').  This has been fixed.  Thanks to Sol
 Swords for bringing this bug to our attention and suggesting a fix.</p>

 <h3>Changes at the System Level</h3>

 <p>(SBCL only) Fixed the executable script generated for SBCL so that
 @('SBCL_HOME') is set to the SBCL @('obj/sbcl-home/') directory if it exists,
 since that fix seems needed for some recent versions of SBCL (1.1.14 in
 particular).</p>

 <p>File @('GNUmakefile') in the ACL2 sources directory wasn't passing the
 value of shell variable @('ACL2') from target @('certify-books-fresh') to
 target @('certify-books'), and similarly for target
 @('books/system/doc/render-doc.cert') (invoked by target @('DOC')).  This has
 been fixed.  We thank Jared Davis and Camm Maguire for helpful
 discussions.</p>

 <p>The \"make DOC\" command was not completing correctly when variable
 @('ACL2') was not set.  Also, for host Lisp CMUCL at least, it stalled at the
 terminal unless a quit command was issued twice (as ACL2 was stuck without
 exiting).  Those problems have been resolved.  Thanks to Jim Ward for bringing
 these issues to our attention</p>

 <p>Improved the error message when encountering an illegal comma while reading
 input (i.e., for a comma not within a suitable nesting of backquotes).  Thanks
 to Jared Davis for bringing this issue to our attention and for a helpful
 discussion.</p>

 <p>(GCL only) Arranged for state global @(''tmp-dir') to be set to GCL's
 @('si::*tmp-dir*'), even on Windows; this may be important for compilation on
 Windows.  Thanks to Camm Maguire for pointing out the need to set
 @(''tmp-dir') for ACL2 built on GCL on mingw.</p>

 <p>(GCL only) Now, @(tsee gc$) may be called with no arguments, in which case
 the missing argument for @('system::gc') is @('t').</p>

 <h3>EMACS Support</h3>

 <p>Improvements to the @(see ACL2-Doc) browser include the following.</p>

 <ul>

 <li>A new `@('w')' command displays the topic name in the minibuffer, together
 with the manual name (ACL2+Books Manual or ACL2 User's Manual).</li>

 <li>Improved the `@('control-t .')' command so that the default topic is
 selected just as in acl2-doc mode.  (Technically: the same syntax table is
 used for `@('control-t .')' as is used in the @('acl2-doc') buffer for that
 command and the `@('g')' command.)</li>

 <li>Improved the search commands so that the display doesn't move when the
 next occurrence is already displayed on the screen.</li>

 <li>Eliminated the deprecated commands `@('Control-x a A')',
 `@('Control-x a a')', and `@('Control-t G')'.</li>

 </ul>

 <h3>Experimental/Alternate Versions</h3>

 <p>For ACL2(r), Ruben Gamboa found a bug in constraints for functions
 introduced with @('defun-std'), and also kindly provided a fix, which has been
 incorporated.</p>

 <p>Modified ACL2(hp) so that two system functions that had been @(tsee
 unmemoize)d when turning on @(see waterfall-parallelism) &mdash;
 @('fchecksum-obj') and @('expansion-alist-pkg-names-memoize') &mdash; now
 remain memoized.  This can greatly improve performance when using ACL2(hp)
 with @(see waterfall-parallelism) on, in particular community book
 @('books/system/doc/render-doc-combined.lisp').</p>

 <p>Made miscellaneous small improvements to ACL2(h).</p>

 <p>The utilities @('hons-shrink-alist') and @('hons-shrink-alist!') have
 essentially been renamed to @(tsee fast-alist-fork) and @(tsee
 fast-alist-fork!), respectively.  The old names are deprecated but remain as
 macros that are macro-aliases for the respective new names (see @(see
 macro-aliases-table)).  New utilities, @(tsee fast-alist-clean) and @(tsee
 fast-alist-clean!) are similar to the above but take just one argument and, if
 it is a fast alist, associates the result with the hash table link of that
 argument.  Thanks to Jared Davis for providing a concrete proposal, together
 with the new names, for what had been only a concept.</p>")

(defxdoc note-7-0

; Total number of release note items: 82.

; Fixed the guard error message for pkg-imports to report a violation for that
; function, not (as had been the case) for function pkg-witness.  More
; generally, did miscellaneous cleaning of of code pertaining to those two
; functions.

; Modified the handling of print-number-base-16-upcase-digits so that it is
; automatically installed when appropriate in princ$ and prin1$, rather than
; specifically for Allegro CL and CMUCL.  This way, ACL2 printing will be kept
; consistent with the axioms even if future versions of other host Lisps print
; hex digits in lower case.

; Made a small GCL-only related change to user-homedir-pathname, after
; consultation with Camm Maguire.

; Just below is Eric Smith's example showing the problem with :pl and :pl2 that
; we fixed.  (Eric actually mentioned :pl, but we use :pl2 below to restrict
; output to the problematic rule.)  The free variable was being instantiated by
; search-ground-units (under a second call made by pc-relieve-hyp under
; pc-relieve-hyps1, which was under pc-relieve-hyps, which was under
; unrelieved-hyps, which was under show-rewrites-linears).  Note that printing
; of :meta rules and :type-prescription rules by :pl and :pl2 already didn't do
; this additional search for ground units.
;
;   (defun foo () 'foo)
;   (defthm symbolp-foo (symbolp (foo)))
;   :pl2 (symbol-< 'x 'z) symbol-<-transitive

; We now avoid a raw Lisp error for encapsulate events occurring when trying to
; check for redundancy.  The problem was that getprop was being called by
; find-first-non-local-name with a non-symbol first argument.  Thanks to Jared
; Davis for reporting this bug by sending the following example:
;
;   (encapsulate () ((x)))

; Here is a proof of nil that exploits the ACL2(h) soundness bug in function
; memoization, mentioned below.  The following book can be certified in ACL2(h)
; Version 6.5 using CCL, specifically its static-cons feature (even more
; specifically, a bug in pons-addr-of-argument).

;   (in-package "ACL2")
;
;   (defn foo (x y) (+ (len x) (nfix y)))
;
;   (memoize 'foo :recursive nil)
;
;   ; Create some static conses, put their indices in the memo table for foo,
;   ; and then garbage collect those conses.
;   (value-triple (progn$ (foo (hons-copy '(a)) 0)
;                         (foo (hons-copy '(b)) 0)
;                         (foo (hons-copy '(c)) 0)
;                         (foo (hons-copy '(d)) 0)
;                         (hons-wash) ; or (hons-clear t)
;                         nil))
;
;   ; The new static cons created by hons-copy just below has an index that
;   ; remains stored in the memo table of foo, so that the call of foo below
;   ; is computed by looking up the value of that (stale) index.
;   (defthm mistake
;     (equal (foo (hons-copy '(a b)) 0)
;            1)
;     :hints (("Goal" :in-theory (e/d (foo (hons-copy))
;                                     (hons-copy))))
;     :rule-classes nil)
;
;   (defthm contradiction
;     nil
;     :hints (("Goal" :use mistake))
;     :rule-classes nil)

; The following book certified in ACL2(h) Version  6.5 because of a bug in
; function never-memoize-fn, which has been fixed.

;   (in-package "ACL2")
;
;   (defthm nmf-is-t
;     (equal (never-memoize-fn 'foo) t)
;     :hints (("Goal" :do-not '(preprocess)))
;     :rule-classes nil)
;
;   (defthm nmf-is-nil
;     (equal (never-memoize-fn 'foo) nil)
;     :rule-classes nil)
;
;   (defthm contradiction
;     nil
;     :hints (("Goal" :in-theory (theory 'minimal-theory)
;              :use (nmf-is-nil nmf-is-t)))
;     :rule-classes nil)

; Evaluating the forms in the following book, which uses the :commutative
; keyword argument of memoize, caused a hard Lisp error in ACL2(h) Version 6.5.
; Formerly, the body of the memoized function had first swapped the formals so
; that the first is suitably ``smaller'' than the second.  Now, that swap only
; occurs for storing and looking up results.

;   (in-package "ACL2")
;
;   (defun my-cddr (x)
;     (declare (xargs :guard (and (consp x) (consp (cdr x)))))
;     (cddr x))
;
;   (defun f (x y)
;     (declare (xargs :guard (and (consp x) (consp (cdr x))))
;              (ignore y))
;     (prog2$ (my-cddr x) 17))
;
;   (memoize 'f :commutative t)
;
;   (defn g ()
;     (prog2$ (hons 9 10)
;             (f (hons 5 (hons 7 9)) (hons 9 10))))
;
;   (make-event
;    (prog2$ (g)
;            (value '(value-triple nil))))

; It had been possible to lose a setting of :aokp t when the function when the
; function rememoize-all was called, which occurs when memoize-call-array-grow
; is called.  Here is an example.

;   (defstub stub (x) t)
;   (defn impl (x) x)
;   (defattach stub impl)
;   (defn top (x) (stub x))
;   (memoize 'top :aokp t)
;   ; Optional:
;   ; :q
;   ; (rememoize-all)
;   ; (lp)
;   (progn$
;   (top 3)
;   (top 3)
;   (top 3)
;   (top 3)
;   )
;   ; The following shows 3/4 for TOP hits/calls.  But formerly, calling
;   ; rememoize-all as shown would instead show 0/4.
;   (memsum)

; Modified our-time (hence, time$) to use essentially infinite right margins.
; This probably won't normally affect anyone, but is potentially useful if
; our-time is later extended to provide more information.

; Moved the definition of load-compiled, so that it will be compiled.  Thanks
; to Camm Maguire for noticing that it was running interpreted.'

; Here we say a little about efficiency improvements made to with-output and
; other system code.  First we give some statistics; then we give some
; technical details (probably too low-level to be of interest to most users).
;
; The following experiments were all run on a MacBook Pro with 8 GB of RAM in
; directory books/centaur/vl/, using ACL2(h) built on CCL.  The first results
; show significant speed-up in include-book.
;
; ----------
;
; ; Forms run:
;
; #!acl2(set-inhibit-output-lst
;        (set-difference-eq *valid-output-names* '(error)))
; (time$ (include-book "parsetree"))
;
; ; Results:
;
; ;;; previous ACL2(h):
; ; 25.48 seconds realtime, 24.74 seconds runtime
; ; (1,957,018,816 bytes allocated).
;
; ;;; new ACL2(h):
; ; 16.22 seconds realtime, 15.61 seconds runtime
; ; (1,137,288,128 bytes allocated).
;
; ;;; previous ACL2(h) but where first we executed:
; ;;; (defmacro with-output (&rest args) (car (last args)))
; ; 17.76 seconds realtime, 17.03 seconds runtime
; ; (1,286,754,944 bytes allocated).
;
; ----------
;
; ; Forms run:
;
; #!acl2(set-inhibit-output-lst
;        (set-difference-eq *valid-output-names* '(error)))
; (time$ (include-book "top"))
;
; ;;; previous ACL2(h):
; ; 133.91 seconds realtime, 131.01 seconds runtime
; ; (6,952,084,640 bytes allocated).
;
; ;;; new ACL2(h):
; ; 105.22 seconds realtime, 96.84 seconds runtime
; ; (4,073,142,576 bytes allocated).
;
; ;;; previous ACL2(h) but where first we executed:
; ;;; (defmacro with-output (&rest args) (car (last args)))
; ; 107.14 seconds realtime, 104.44 seconds runtime
; ; (4,615,512,992 bytes allocated).
;
; ----------
;
; ; Forms run (starting with include-book forms from the top of parsetree.lisp,
; ; so as to focus this time on the time executing with proofs instead of
; ; include-book):
;
; (include-book "expr")
; (include-book "util/commentmap")
; (include-book "util/warnings")
; ; (include-book "tools/flag" :dir :system) ; redundant
; (local (include-book "util/arithmetic"))
; #!acl2(set-inhibit-output-lst
;        (set-difference-eq *valid-output-names* '(error)))
; (time$ (ld "centaur/vl/parsetree.lisp" :dir :system))
;
; ;;; previous ACL2(h):
; ; 124.47 seconds realtime, 121.68 seconds runtime
; ; (9,613,894,128 bytes allocated).
;
; ;;; new ACL2(h):
; ; 116.75 seconds realtime, 114.22 seconds runtime
; ; (8,752,482,112 bytes allocated).
;
; ----------
;
; Technical changes included the following.
;
; - Lazy trans-eval: Formerly trans-eval first translated a term and then
;   evaluated it, but now the term can now be repeatedly macroexpanded, and if
;   the result is a call of IF, then only the true or false branch will be
;   translated (and evaluated), depending of course on the result of evaluating
;   the test.  This change can speed up, in particular, calls of value-triple
;   during include-book, by avoiding needless translation.
;
; - Check-vars-not-free is now handled directly by translate11, saving the
;   expense of translating its translate-and-test expansion.
;
; - There is less code to translate from acl2-unwind-protect when cleanup1 and
;   cleanup2 are the same.  Related to that (but probably minor):
;   state-global-let* uses let-binding to share cleanup forms, which can allow
;   the two cleanup forms to be EQ and hence speed up their new equality test.
;
; - With-output essentially expands to its last argument during include-book.
;   (This change takes advantage of the change to trans-eval.)
;
; - (Not really about efficiency) We eliminated one of the two kinds of forms
;   from translated-acl2-unwind-protectp4, which had seemed impossible to
;   generate.
;
; Finally, here is the list of all symbols whose definitions were changed or
; added in support of those improvements.
;
;   acl2-unwind-protect
;   check-vars-not-free
;   macroexpand1* (new)
;   macroexpand1*-cmp (new)
;   state-global-let*
;   trans-eval
;   trans-eval1 (new)
;   translate11
;   translated-acl2-unwind-protectp4
;   with-output

; The following functions are now defined unconditionally in the ACL2 logic (in
; :program mode), rather than merely in raw Lisp when #+hons:
; hons-union-ordered-string-lists and expansion-alist-pkg-names-memoize.

; Here is a proof of nil that exploits the weakness of the previous guard for
; alpha-char-p.  This proof succeeds in every host Lisp for ACL2 except for GCL
; (and future versions of GCL might also evaluate (alpha-char-p (code-char
; 232)) to true).
;
;   (defthm false-prop
;     (not (alpha-char-p (code-char 232)))
;     :hints (("Goal" :in-theory (e/d (alpha-char-p) ((:e alpha-char-p)))))
;     :rule-classes nil)
;
;   (defthm true-prop
;     (alpha-char-p (code-char 232))
;     :rule-classes nil)
;
;   (defthm contradiction
;     nil
;     :hints (("Goal" :use (true-prop false-prop)))
;     :rule-classes nil)

; It had been possible to get a raw Lisp error when invoking the proof-builder
; S or SL command with a non-numeric backchain-limit.  Here is an example.
;
;   (defthm foo
;     (implies (consp x) (< 0 (len x)))
;     :rule-classes ((:rewrite :backchain-limit-lst 0)))
;   (verify (implies (and (character-listp x) x)
;                    (characterp (nth 0 x))))
;   ; Each of these caused a raw Lisp error, but now cause a graceful ACL2
;   ; error:
;   (sl abc)
;   (s :backchain-limit abc)
;
; Error-checking has also been added for the :repeat argument of S, though we
; haven't seen a raw Lisp error for a bad :repeat argument.

; Technical fix to encapsulate-fn: it now calls install-event with a namex of 0
; instead of nil in the case of an empty signature list.  As a result, (getprop
; nil 'absolute-event-number :none 'current-acl2-world (w state)) returns the
; true absolute event number for the introduction of the constant nil, rather
; than being increased every time we execute (encapsulate () ...).

; In support of the hard-error enhancement, we eliminated the initial newline
; printed by error-fms-channel.  However, we preserved the functionality of its
; callers, error-fms and print-failure, by adding a call of newline in each of
; those functions immediately before their calls of error-fms-channel.

  :parents (release-notes)
  :short "ACL2 Version  7.0 (January, 2015) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes to ACL2 since Version 6.5 into the
 following categories of changes: existing features, new features, efficiency
 improvements, bug fixes, changes at the system level, Emacs support, and
 experimental versions.  Each change is described in just one category, though
 of course many changes could be placed in more than one category.</p>

 <p>A particularly major change with this release is that by default, ACL2
 executables are @(see hons-enabled): see @(see hons-and-memoization).  We
 expect this change to be backward compatible for current ACL2 users, other
 than a change to the name of the executable, as described below.</p>

 <ul>

 <li>As before, there are two ways to build ACL2: either @(see hons-enabled),
 to produce ACL2(h) with executable name @('saved_acl2h'); or not hons-enabled,
 to produce ``classic ACL2'', which we now call ACL2(c), with executable name
 @('saved_acl2').  [Note: These defaults were changed after Version_7.0.]</li>

 <li>Unlike before, the default build of ACL2 is now ACL2(h), hence with name
 @('saved_acl2h') [after Version_7.0, once again @('saved_acl2')].  It is still
 possible to build ACL2(c) (hence with name @('saved_acl2')) [after
 Version_7.0, @('saved_acl2c')], but this is not the default.</li>

 <li>The change to building ACL2(h) by default may require you to change
 scripts and environment variables to point to @('saved_acl2h') rather than
 @('saved_acl2').  [This change is only for Version_7.0, not later
 versions.]</li>

 </ul>

 <p>Note that after the next ACL2 release, we might only support @(see
 hons-enabled) ACL2 builds.</p>

 <p>See also @(see note-7-0-books) for a summary of changes made to the ACL2
 Community Books since ACL2 6.5, including the build system.</p>

 <h3>Changes to Existing Features</h3>

 <p>Three new theorems have been built into ACL2 to allow some additional
 simple arithmetic reasoning.  For example, the following failed before this
 change, typically causing the user to include an arithmetic book; but that is
 no longer necessary.</p>

 @({
 (thm (implies (natp x)
               (equal (expt 2 (+ 1 -1 x))
                      (expt 2 x))))
 })

 <p>Thanks to Jared Davis for suggesting these, and for providing seven small
 modifications to the community books to keep proofs from failing after the
 changes.  (So, if you have a proof failure involving `plus' (@('+')) that
 formerly succeeded, consider disabling one or more of these rules.)  Here are
 the three new built-in theorems.</p>

 @(def commutativity-2-of-+)

 @(def fold-consts-in-+)

 @(def distributivity-of-minus-over-+)

 <p>@(csee Type-set) reasoning has been improved for a few built-in functions,
 including @('first-n-ac'), @(tsee substitute), @(tsee nthcdr), and @(tsee
 subseq), and thus for some functions whose computed type depends on one of
 these: for example, @(tsee take) and therefore, also @(tsee butlast) and
 @(tsee subseq-list), are now known to return @(tsee true-listp) results.
 Thanks to Jared Davis for a request that led us to these changes.  In
 particular, the definitions of @('first-n-ac') and @('substitute-ac') have
 been modified to call @(tsee revappend) instead of @(tsee reverse), and the
 following @(':')@(tsee type-prescription) rules have been added to source file
 @('axioms.lisp') (and can be seen using @(':')@(see pe)).</p>

 <ul>

 <li>true-listp-first-n-ac-type-prescription</li>
 <li>stringp-substitute-type-prescription</li>
 <li>true-listp-substitute-type-prescription</li>
 <li>true-listp-nthcdr-type-prescription</li>
 <li>stringp-subseq-type-prescription</li>
 <li>true-listp-subseq-type-prescription</li>

 </ul>

 <p>Technical note on the above change: in some cases, the built-in
 @(':')@(tsee type-prescription) rule has been changed, essentially for the
 better, but new rules have also been added.  Consider for example the
 function, @(tsee substitute).  This function calls @('substitute-ac'), which
 in turn now calls @(tsee revappend) instead of @(tsee reverse), which allows
 ACL2 to deduce a @(':type-prescription') rule saying that @('substitute')
 returns a string or a true-list.  However, new @(':type-prescription') rules
 @('stringp-substitute-type-prescription') and
 @('true-listp-substitute-type-prescription') allow the stronger conclusion
 that @('substitute') returns a string or true-list, respectively depending on
 whether @(see type-set) reasoning can deduce that the given sequence is or is
 not a string.  The deduced @(':type-prescription') rule can still be of some
 use in cases that type-set reasoning cannot establish whether or not the input
 sequence is a string.</p>

 <p>We removed support for processing legacy @(see documentation) strings
 (those starting with @('\":Doc-Section\"')), since the @(see xdoc) system has
 been stable for some time.  Thanks to Jared Davis for assisting in that effort
 and to David Rager for his encouragement.  The ACL2 system and @(see
 community-books) still have code to support such processing, but it is
 essentially commented out: specifically, each such piece of code is prefixed
 by @('#+acl2-legacy-doc').  We expect to delete such code entirely before the
 next release.</p>

 <p>The @(tsee with-output) macro now takes a new keyword, @(':evisc'), that
 specifies @(see evisc-tuple)s.  Thanks to Warren Hunt for requesting a way to
 submit @(tsee defun) forms in a way that avoids printing large @(see guard)
 goals during guard verification.  The following example illustrates a way to
 arrange this.</p>

 @({
 (defmacro defun/ (&rest args)
  (mv-let (evisc args)
          (cond ((eq (car args) :evisc)
                 (mv (cadr args) (cddr args)))
                (t (mv '(:gag-mode (evisc-tuple 3 4 nil nil)) args)))
          `(with-output :evisc ,evisc
                        (defun ,@args))))

 ; example:
 (defun/ h (x)
  (declare (xargs :guard t))
  (append (cons (make-list 10) x) x))
 })

 <p>The utility @(':')@(tsee pl2) no longer automatically instantiates free
 variables; similarly for calls of @(':')@(tsee pl) on a term.  Thanks to Eric
 Smith for sending an example showing the problem with the previous
 implementation.</p>

 <p>When the @(see ld-evisc-tuple) is non-@('nil'), the utilities @(':')@(tsee
 pe), @(':')@(tsee pc), and @(':')@(tsee pcb!) now abbreviate their output
 accordingly.  See @(see set-evisc-tuple).  Thanks to David Rager for bringing
 the need for this change to our attention.</p>

 <p>The utility @(tsee disabledp) now accepts runic abbreviations such as
 @('(:d append)').  (See @(see theories) for a discussion of runic
 abbreviations.)  Thanks to Shilpi Goel for requesting this enhancement.</p>

 <p>Gc-verbose now takes an optional second argument, which is only relevant
 when the host Lisp is CCL, where that argument specifies verbosity for
 EGC.</p>

 <p>Nests of @(tsee car) and @(tsee cdr) calls are now printed
 (``untranslated'') differently.  The old method availed itself of all 28 of
 the car-cdr macros.  The new method only introduces 6 of them: @('cadr'),
 @('caddr'), @('cadddr'), @('cddr'), @('cdddr'), @('cddddr').  It never
 introduces such macros as @('caar') or @('cddaar'), preferring @('car')s and
 @('cdr')s when necessary.  Lisp programmers tend to recognize @('cadr'),
 @('caddr'), and @('cadddr') as the accessors for the 1st, 2nd, and
 3rd (0-based) elements of a list.  See community book
 @('books/system/untranslate-car-cdr.lisp') for further discussion and a
 correctness proof.</p>

 <p>It is now possible to create more efficient @(':')@(tsee meta) rules by
 writing metafunctions that create ``implicit hypotheses.''  See
 @(see meta-implicit-hypothesis).</p>

 <p>We improved a few built in rules: @('lower-case-p-char-downcase'),
 @('upper-case-p-char-upcase'), @('lower-case-p-forward-to-alpha-char-p'), and
 @('upper-case-p-forward-to-alpha-char-p').  We also improved the rule
 @('alpha-char-p-forward-to-characterp') by replacing it with two rules,
 @('alpha-char-p-forward-to-standard-char-p') and
 @('standard-char-p-forward-to-characterp').  The new rules are, as before, in
 ACL2 source file @('axioms.lisp').</p>

 <p>The reader macro sharp-comma (@('#,')), which has been deprecated
 since ACL2 Version  3.5 (May, 2009), has been eliminated.  Use sharp-dot
 (@('#.')) instead; see @(see sharp-dot-reader).</p>

 <p>A @(tsee defthm) or @(tsee defaxiom) event is now redundant when there is
 already a syntactically identical event in the logical @(see world), even if
 the rules suggested by the two @(see events) differ.  See @(see
 redundant-events).  Thanks to Jared Davis and Sol Swords for sending the
 following example, which illustrates the change.  Previously, the final event
 was not redundant, and hence failed.  Now, it is redundant, even though the
 @(':typed-term') suggested by the new @(tsee type-prescription) rule is
 @('(booleanp (foop x))') where the existing rule's @(':typed-term') is
 @('(foop x)').</p>

 @({
 (defund foop (x) (consp x))

 (defthm booleanp-of-foop
   (booleanp (foop x))
   :rule-classes :type-prescription)

 (in-theory (disable booleanp-compound-recognizer))

 (defthm booleanp-of-foop
   (booleanp (foop x))
   :rule-classes :type-prescription)
 })

 <p>In the case that summary output is inhibited but error output is not (see
 @(see set-inhibited-summary-types)), failed @(see events) did not print an
 error message.  Now they do.</p>

 <p>When a call of @(see encapsulate) with empty @(see signature) introduces no
 @(see events), it now has no effect on the ACL2 logical @(see world).
 Formerly, such an @(see encapsulate) form would create an event even in this
 case.  For example, the form @('(encapsulate nil (local (defun f (x) x)))')
 formerly created an event in the world, as well as a @(see command) when
 executed at the top-level; but now it is truly a no-op.  See @(see
 encapsulate).  Note: An idiom sometimes used for testing is
 @('(encapsulate () (local ...) (local ...) ...)'), that is, a trivial
 encapsulate where each sub-event is @(see local).  With this change, that
 idiom is now properly supported.  (Formerly, the second such encapsulate was
 considered redundant with the first; but that is no longer the case, since the
 first will not be stored in the @(see world).)</p>

 <p>We replaced an error with a warning for cases where a classic @(see
 congruence) rule is unnecessary.  Thanks to Jared Davis for sending us an
 example suggesting the need for a change.  (See ACL2 source function
 @('chk-acceptable-congruence-rule') for his example and more explanation.)</p>

 <p>We removed support for three @(tsee declare) forms that had been permitted
 in ACL2(h) only, but were not advertised: @('dynamic-extent'), @('inline') and
 @('notinline'), because they seem difficult or impossible to support
 correctly.  For alternatives to using @('inline') and @('notinline')
 declarations, see @(see defun-inline) and  @(see defun-notinline).</p>

 <p>The nu-rewriter contained special provisions for rewriting expressions
 composed of @(tsee nth), @(tsee update-nth), and @(tsee update-nth-array),
 together with @(tsee let) expressions and other applications of non-recursive
 functions or @(tsee lambda) expressions.  An email query was sent to the acl2
 mailing list on 10/24/2014, giving people an opportunity to object to the
 removal of this feature.  Nobody objected, so we have removed it in order to
 simplify the ACL2 code base.  Thanks to David Rager for suggesting this sort
 of code clean-up.  Note that some system functions, for example
 @('all-equal'), have been deleted in support of this change.</p>

 <p>@(csee Guard)s have been added for some system functions that support the
 implementation of the @(see tau-system): @('lower-bound-<='),
 @('upper-bound->='), @('lower-bound->'), @('upper-bound-<'), and
 @('squeeze-k').  Thanks to Dmitry Nadezhin for supplying these improvements
 (which he also used in modifications to the community book,
 @('books/tau/bounders/elementary-bounders.lisp')).</p>

 <h3>New Features</h3>

 <p>The new command @(':btm') has been added to the list of valid @(see
 brr-commands), to show the bottom-most frame in the path.  Thanks to David
 Rager for requesting this feature.</p>

 <p>A new @(tsee xargs) keyword, @(':')@(tsee measure-debug), decorates each
 termination proof goal with @(tsee extra-info) calls that show the source of
 the goal.  Thanks to Jared Davis (first in 2008!), Sol Swords, and Anna
 Slobodova for requesting this feature.</p>

 <p>A new reader macro, @('#{\"\"\"...\"\"\"}'), has been contributed by Jared
 Davis to support the writing of strings without escape characters.  See his
 community book @('books/system/fancy-string-reader-test.lisp') for
 examples.</p>

 <p>(For those who program in raw Lisp) A new Lisp variable,
 @('*hard-error-is-error*'), has a default of @('nil') that preserves existing
 behavior; but it can be set to a non-@('nil') value in order to cause
 so-called ACL2 ``hard errors'' to result in Lisp errors whose condition, when
 printed with @('format') directive @('~a'), is the same error message that
 ACL2 would otherwise print.  See @(see hard-error).  Thanks to Jared Davis for
 requesting this feature.</p>

 <p>A new value for @(tsee include-book) keyword argument @(':uncertified-okp')
 is @(':ignore-certs'), which specifies that all certificate files are to be
 ignored during inclusion of this book and all of its sub-books.  See @(see
 include-book).  Thanks to Sol Swords for requesting this feature and for
 helpful discussions on its details.</p>

 <h3>Efficiency Improvements</h3>

 <p>The heuristics have changed for guessing the @(':typed-term') field for a
 @(':')@(tsee type-prescription) rule when that field is not explicitly
 specified.  Specifically, consider the case that the conclusion of the rule is
 a function call @('(p u)') for some term @('u'), such that there is an enabled
 @(tsee compound-recognizer) rule for @('p').  Formerly, the @(':typed-term')
 was @('u') in this case.  Now, it must be the case that the most recent
 enabled such @(tsee compound-recognizer) rule is `strong', in the following
 sense: if @('ts1') is the @(see type-set) implied by assuming the conclusion
 true and if @('ts2') is the @(see type-set) implied by assuming the conclusion
 false, then @('ts1') and @('ts2') are complementary.  Thanks to Jared Davis
 for an email that prompted us to make this change.</p>

 <p>We have made several efficiency improvements (arguably heuristic in
 nature), which may apply in many settings but especially in handling of
 several forms during the execution of @(tsee include-book) &mdash; most
 notably @('with-output') forms, as <tt>(with-output ... FORM)</tt> is now
 essentially just <tt>FORM</tt> during @('include-book').  For some details,
 including statistics showing up to 1/3 of @(tsee include-book) time eliminated
 by these changes (and even significant time saved outside @('include-book')),
 see the comment about ``efficiency improvements'' in Community Books file
 <tt>system/doc/acl2-doc.lisp</tt>, form @('(defxdoc note-7-0 ...)').  Thanks
 to Sol Swords for noticing inefficiencies that led us to these improvements,
 and for helpful discussions.</p>

 <p>The @(see dmr) utility has been made much more efficient, yielding a
 performance penalty of perhaps 10% instead of perhaps more than a factor of
 30 (3000%).</p>

 <p>We made a low-level implementation tweak that resulted in a speed-up of
 2.6% in wall-clock time for a CCL-based regression (using ``@('make')'' with
 @('-j 8') and target ``everything'').  (Technical note: We eliminated the Lisp
 special variable @('*attached-fn-called*'), using another variable @('*aokp*')
 instead.  Special variable bindings can apparently be expensive!)</p>

 <p>Some space has been saved in ACL2 executables by avoiding the duplication
 of certain constants.  Specifically: for each event @('(defconst name (quote
 val))') in the ACL2 source files, @('val') is stored in the Lisp image in
 several places, but not all of these had been identical: they were all @(tsee
 equal), but not all @(tsee eq).  (We believe that these were already all
 @('eq') for user-defined @(tsee defconst) events.)  For example, in Linux
 builds of ACL2(h) on host Lisp CCL, we have seen a space saving of
 approximately 18.9 MB, which is 12.6%.  Thanks to Jared Davis for pointing out
 duplicate strings that he noticed using his @(see spacewalk) tool.</p>

 <h3>Bug Fixes</h3>

 <p>We fixed two bugs in @(tsee spec-mv-let).  The first was pointed out to us
 by Jared Davis using essentially the following example, where the result
 should be @('nil') given that @('spec-mv-let') is intended to have the
 semantics of @(tsee mv?-let).</p>

 @({
 ACL2 !>(set-ignore-ok t)
  T
 ACL2 !>(let ((a t)
              (xval nil))
          (spec-mv-let (yval)
                       xval
                       (mv?-let (xval)
                           a
                           (if xval
                               yval
                             nil))))
 T
 ACL2 !>
 })

 <p>The second @(tsee spec-mv-let) bug was to allow the two lists of bound
 variables to intersect.  In the following example, given that @('spec-mv-let')
 is semantically just @('mv?-let'), the result should have been 46, not 34.
 This has been fixed.  Thanks to David Rager for encouraging these two fixes
 and checking them over.</p>

 @({
 ACL2 !>(set-ignore-ok t)
  T
 ACL2 !>(spec-mv-let
         (x)
         17
         (mv?-let (x)
             23
             (if t
                 (+ x x)
               \"bad\")))
 34
 ACL2 !>
 })

 <p>The guard for function @(see alpha-char-p) was strengthened to require that
 its argument is a standard character.  The previous guard required only that
 the argument is a character, and was a soundness bug; for a proof of @('nil')
 before this fix, see the comment about ``alpha-char-p'' in Community Books
 file <tt>system/doc/acl2-doc.lisp</tt>, form @('(defxdoc note-7-0 ...)').</p>

 <p>Errors were possible when evaluating functions @(tsee pkg-imports) and
 @(tsee pkg-witness) while including a book with a compiled (or expansion)
 file.  Such errors have been eliminated.</p>

 <p>Fixed a bug in @('oracle-apply-raw').</p>

 <p>(GCL CLtL1 only) Fixed a bug that was preventing @(tsee
 set-debugger-enable) from taking full effect in non-ANSI GCL.</p>

 <p>(GCL only) The utility @(tsee gc-verbose) was broken, but has been
 fixed.</p>

 <p>Fixed a bug in @(see provisional-certification) that incorrectly caused an
 error during the convert step for @(tsee verify-guards+) forms.  More
 generally, this error occurred when encountering a @(tsee make-event) form
 with a non-@('nil') value supplied for the @(':expansion?') keyword.  Thanks
 to David Rager for reporting this bug.</p>

 <p>A raw Lisp error could occur with @(see guard)-checking turned off, because
 type declarations were mistakenly left in the executable counterparts
 (so-called ``*1* functions'') when ACL2 processed function definitions.  The
 following example shows how a type violation could occur in some Lisps (we saw
 this in SBCL but not in CCL, for example).</p>

 @({
  (defun f (x)
    (declare (xargs :guard (natp x)))
    (let ((y (1+ x)))
      (declare (type (integer 0 *) y))
      y))
  (set-guard-checking nil)
  ; Possible raw Lisp error:
  ; \"The value -2 is not of type UNSIGNED-BYTE.\"
  (f -3)
 })

 <p>Thanks to Jared Davis for sending us an example that brought this bug to
 our attention.</p>

 <p>Fixed a bug that was causing a low-level assertion, saying:
 ``Implementation error: see 'replace-free-rw-cache-entry.''  Thanks to Anna
 Slobodova for bringing this bug to our attention via an example, and to Sol
 Swords for simplifying that example.</p>

 <p>The @(see iprint) feature, which allows abbreviated output to be read back
 in, did not work as one might expect when using the @(see break-rewrite)
 feature (see @(see brr)).  Thanks to David Rager for reporting this problem.
 More generally: the problem was that values associated with @(see iprint)
 indices during a @(see wormhole), for example after breaking on a @(see
 rewrite) rule, were forgotten when exiting the wormhole.  (Technical note for
 those interested: the fix restores the main iprinting structure after exiting
 a wormhole, just before reading the next top-level form.  That restoration
 uses raw Lisp, with logic-only code based on @(tsee read-acl2-oracle).)  The
 example below failed before the fix but now works.</p>

 @({
 (set-evisc-tuple (evisc-tuple 3 3 nil nil)
                  :iprint t
                  :sites :all)
 (defthm my-rule (equal (car (cons x x)) x))
 (brr t)
 (monitor '(:rewrite my-rule) t)
 (thm (equal (car (cons a a)) a) :hints ((\"Goal\" :do-not '(preprocess))))
 ; Now entering a :brr break:
 (make-list 10) ; printed without evisceration
 ; Set evisceration with iprinting:
 (set-evisc-tuple (evisc-tuple 3 3 nil nil)
                  :iprint t
                  :sites :all)
 (make-list 10) ; printed with evisceration
 (a!) ; quit break-rewrite
 ; The following formerly caused a hard Lisp error, because although #@3#
 ; was printed in the output from (make-list 10) just above, iprint index 3
 ; was lost when exiting the break-rewrite wormhole.  Now, this works
 ; because iprinting information from the wormhole is retained.
 '#@3#
 })

 <p>There was a bug in how so-called ``hidden packages'' were handled by @(tsee
 encapsulate) forms (see @(see hidden-death-package)), which was preventing
 package axioms from being visible in certain contexts.  (Technical remark:
 packages that were hidden after the second pass but not the first were treated
 as not-hidden, even though their package axioms were not introduced.)  That,
 in turn, could cause an @(tsee include-book) form to fail when the book
 contains a @(tsee deftheory-static) form.  Here is an example failure.  First,
 in a fresh ACL2 session evaluate the form @('(defpkg \"FOO\" nil)') and then
 evaluate the form @('(certify-book \"foo\" 1)'), where file @('foo.lisp') is
 as follows.</p>

 @({
 (in-package \"ACL2\")
 (defun foo::foo (x) x)
 (deftheory-static foo-theory
   (current-theory :here))
 })

 <p>Now evaluate the following sequence of forms.  In previous versions of
 ACL2, the final (@(tsee include-book)) form failed.</p>

 @({
 (encapsulate () (local (include-book \"foo\")) (defun h (x) x))
 (encapsulate () (local (include-book \"foo\")) (defun h2 (x) x))
 (include-book \"foo\") ; failed before the fix
 })

 <p>We have cleaned up handling of interrupts and aborts when inside the @(see
 break-rewrite) loop, or indeed any @(see wormhole).  Thanks to David Russinoff
 for bringing to our attention a case in which ACL2 quit a proof with
 ``Aborting due to an interrupt'' when in fact no interrupts had taken place.
 Here is an example where that no longer happens but did, previously.  (For a
 different example, see the comment in the ACL2 sources definition of macro
 @('bind-acl2-time-limit').)</p>

 @({
 (defun foo (x) (cons x x))
 (brr t)
 (monitor '(:definition foo) t)
 (thm (equal (foo y) z))
 (defun h (x) (declare (xargs :mode :program)) (car x))
 ; Raw Lisp error:
 (h 3)
 ; Previously, unexpected proof abort \"due to interrupt\":
 (thm (equal (append (append x y) x y) (append x y x y)))
 })

 <p>When aborting with @(':')@(tsee a!) inside the @(see break-rewrite) loop
 from within the @(see proof-builder), a raw Lisp error could subsequently
 occur saying, ``Attempt to execute *wormhole-cleanup-form* twice!''.  This has
 been fixed.  Thanks to Sol Swords for reporting a bug in our original fix.
 Here is an example that formerly caused that behavior.</p>

 @({
 (defthm silly (implies (null x) (equal (append x y) y)))
 (defconst *c* (make-list 10))
 :brr t
 :monitor (:rewrite silly) t
 (verify (equal (append x (append *c* y)) (append y (append *c* x))))
 bash
 :go
 :a!
 bash ; formerly caused error
 })

 <p>The utility @(tsee redo-flat) no longer worked when interrupting a
 proof (with Control-c), due to a bug in Version 7.0.  This has been fixed.
 Thanks to Dave Greve for reporting this problem.</p>

 <h3>Changes at the System Level</h3>

 <p>As mentioned near the top of this @(see documentation) topic, default
 builds of ACL2 are now @(see hons-enabled).</p>

 <p>(GCL only) GCL Versions prior to 2.6.12 are no longer supported.</p>

 <p>Modified code used in distributing Debian releases that allows books
 certified in one directory to be distributed in another.  This change,
 together with the fact that such relocation is <b>not</b> truly supported, is
 explained in comments in source function @('make-certificate-file-relocated').
 Thanks to Camm Maguire for discussions leading to this change.</p>

 <p>(GCL only) Modified how home directory is calculated.  Thanks to Camm
 Maguire for help in making this change.</p>

 <p>(SBCL only) Fixed a check done at build time that was preventing builds in
 SBCL 1.2.2 because of its new backquote implementation.  Thanks to Harsh Raju
 Chamarthi and Pete Manolios for bringing this issue to our attention.</p>

 <p>Development snapshots of ACL2 (and of the @(see community-books)) are now
 available between releases from <a href='https://github.com/acl2/acl2'>an ACL2
 github repository</a>; they are no longer available via svn.  Thanks to David
 Rager and Jared Davis for taking the lead on this conversion.  As a result,
 the banner printed at startup for those snapshots has changed slightly.  For a
 quick start guide for using git with ACL2, see @(see git-quick-start).</p>

 <p>(CCL only) Control-d now quits ACL2 in raw Lisp just as it has done for a
 long time in the loop and, for ACL2(h) (i.e., @(see hons-enabled) ACL2), even
 in raw Lisp.</p>

 <p>(Should essentially affect GCL only) Significant re-work has been done for
 function proclaiming, which is still only done when the host Lisp is GCL.  In
 particular, the build process now has extra steps even for other Lisps though
 for them, the extra steps are trivial (technical details may be found in the
 comment labeled ``Essay on Proclaiming'' in source file acl2-fns.lisp).  We
 now use GCL's automatic proclaiming mechanism to calculate function types
 during the build (boot-strap), as we have seen it perform better than our own.
 Thanks to Camm Maguire for helpful discussions, in particular for explaining
 that mechanism and for pointing out that the re-proclaiming that had been done
 previously during the build could lead to buggy behavior.</p>

 <p>For Makefile targets for testing such as @('regression'), the default ACL2
 image used is now the same one that would be built for the same Makefile
 variables.  In particular, the command @('make regression') is equivalent to
 @('make regression ACL2_HONS=h'), which uses the executable @('saved_acl2h'),
 not @('saved_acl2') as was formerly the case.  Thanks to Harsh Raju Chamarthi
 for finding a bug in a first attempt to make this change.</p>

 <h3>EMACS Support</h3>

 <h3>Hons-enabled and Experimental Versions</h3>

 <p>(For @(see hons-enabled) executables only) Fixed a soundness bug related to
 function memoization.  For a proof of @('nil') exploiting this bug in Version
 6.5, see the comment about ``pons-addr-of-argument'' in Community Books file
 <tt>system/doc/acl2-doc.lisp</tt>, form @('(defxdoc note-7-0 ...)').  Thanks
 to Jared Davis for improving our original fix: by noting its applicability to
 @(tsee hons-clear) (not just @(tsee hons-wash)); by tweaking our fix so that
 it works even if a @('control-c') interrupts (@('hons-clear') or)
 @('hons-wash'); and later by finding another bug in source function
 @('pons-addr-of-argument') and suggesting a fix, which we incorporated.</p>

 <p>(For @(see hons-enabled) executables only) Fixed a soundness bug due to the
 fact that function @('never-memoize-fn') returned @('nil') in the logic but
 returned @('t') in raw Lisp.  For a proof of @('nil') exploiting this bug in
 Version 6.5, see the comment about ``never-memoize-fn'' in Community Books
 file <tt>system/doc/acl2-doc.lisp</tt>, form @('(defxdoc note-7-0 ...)').</p>

 <p>Static honsing for @(see hons-enabled) ACL2, an efficiency enhancement
 formerly only available for CCL, is now incorporated into builds on
 sufficiently recent GCL versions.</p>

 <p>ACL2 executables that were @(see hons-enabled) could fail to use
 previously-compiled definitions for @(tsee memoize)d functions when @(tsee
 include-book) is invoked.  This has been fixed.</p>

 <p>(For @(see hons-enabled) executables only built on other than CCL or SBCL)
 Calls of @(tsee memoize) only compile the memoized definition when the
 original function is compiled, rather than unconditionally as before.</p>

 <p>Several changes been made to function memoization (see @(see memoize)).
 Here is a list of changes visible at the user level; for implementation
 details, see @(see note-7-0-memoize).</p>

 <ul>

 <li>It is now legal to call @(tsee memoize) on functions with special raw-Lisp
 code (such as @(tsee len)) provided the value of the @(':inline') keyword
 argument is @('nil').</li>

 <li>Bug fix: Fixed bug that was making @(tsee memsum) attribute the count of
 making of hash tables to ``Heap bytes allocated'' instead of to ``Number of
 calls to mht.''</li>

 <li>Memoize keyword @(':trace') is no longer supported, as the @(tsee trace$)
 utility provides much more flexibility.</li>

 <li>Bug fix: Fixed a bug in handling of the @(':commutative') argument of
 @(tsee memoize) that could cause a hard Lisp error.  For a book that exhibits
 this bug, see the comment about ``:commutative'' in Community Books file
 <tt>system/doc/acl2-doc.lisp</tt>, in the form @('(defxdoc note-7-0
 ...)').</li>

 <li>When @(tsee memoize) is called with keyword argument @(':commutative')
 having value @('t'), the benefit of that argument can apply to rational number
 arguments even when not using static honsing.  Moreover, now only one argument
 needs to be a rational or to be ``static'' according to the
 implementation (technically: to have an @('hl-staticp') value).</li>

 <li>Bug fix: Calls of @(tsee memoize) with keyword argument @(':commutative
 t') were sometimes inappropriately treated as redundant @(see
 redundant-events).  This has been fixed.  Here is a simple example of what
 formerly went wrong.</li>

 @({
 (defn f (x y) (equal x y))
 (memoize 'f :commutative t)
 (unmemoize 'f)
 (memoize 'f :commutative t) ; was redundant, so did not memoize
 })

 <li>(For those who memoized directly in raw Lisp) @('Memoize-fn') now requires
 its first argument to be a defined (fboundp) function symbol.  (It seemed odd
 and needlessly arcane to allow memoize-fn to define an undefined
 function.)</li>

 <li>(For those who memoized directly in raw Lisp) @('Memoize-fn') now causes
 an error when it fails.</li>

 <li>Bug fix: It had been possible to lose a memoization setting of @(':aokp
 t') when many functions were memoized.  For an example, see the comment about
 ``rememoize-all'' in Community Books file <tt>system/doc/acl2-doc.lisp</tt>, in
 the form @('(defxdoc note-7-0 ...)').</li>

 <li>We eliminated undocumented utilities @('memoize-on') and @('memoize-off'),
 which were not used as far as we know.</li>

 <li>When a memoized function call fails to satisfy the specified
 condition, that call is no longer counted as a ``hit'', at least by
 default.  This can be changed with raw Lisp variable,
 @('*condition-nil-as-hit*').</li>

 <li>The utility @(tsee memsum) had reported one more pons call and (CCL only)
 one more byte than was correct, and could perhaps report one call when there
 were actually zero.  That has all been fixed.</li>

 <li>Bug fix: Some sorting of results based on ``self'' time and ``other
 functions'' time had been wrong.  (Technical remark: the problem was that the
 implementation confused ``ticks'' with ``time''.)  This has been fixed.</li>

 <li>Statistics reporting (see @(see memsum)) often has a more uniform look.
 It is now done with a right margin of 79 instead of 70.  For @(tsee memsum),
 thanks to a suggestion from Warren Hunt, the @('defun') formerly printed to
 start each entry is now omitted, and after the name is printed at the start, a
 newline is printed before the ``hits'' or ``hits/calls'' information is
 printed.  A related change: when @('*report-hits*') and @('*report-calls*')
 are both @('nil'), ``calls'' is no longer printed.  Other cosmetic changes
 were also made to @(tsee memsum) output.</li>

 <li>The output from @(tsee memsum) on the line ``Time of all outermost calls''
 no longer includes a percentage, which had been at best misleading and at
 worse nonsensical.  Suppose for example that @('f') calls @('g'), which does
 all the work.  Then @('memsum') had reported 50% of the ``Time of all
 outermost calls'' for each of @('f') and @('g'), even though 100% of the time
 was spent under each.</li>

 <li>On Mac OS (Darwin), the physical memory is now accurately computed
 (using shell command ``sysctl hw.memsize'', which works in some versions of
 Mac OS, maybe all recent ones; tested on 10.6 and 10.7).  Before, the physical
 memory value had been assumed to be 2^32 bytes.  The physical memory value is
 used in CCL for triggering garbage collections.  (Technical remark: this is
 implemented in function @('start-sol-gc').)</li>

 <li>Bug fix: in the pons summary, misses had been reported instead of hits on
 the ``hits/calls'' line.</li>

 <li>Fixed @(tsee memsum) so that package names are printed with the symbols.
 Also, printing is done with respect to the current package, not the
 @('\"ACL2\"') package.</li>

 <li>It is now legal to @(see profile) functions that take @(tsee state) as an
 argument.  Thanks to Sol Swords for requesting this change.  In the course of
 making this change, we took a conservative approach and put the same
 requirement regarding illegal memoization of functions involving user-defined
 @(tsee stobj)s: that is, when memoization must have value @('nil') for the
 @(':condition') keyword, it must also have value @('nil') for the @(':inline')
 keyword.  We can perhaps remove this additional restriction if necessary.</li>

 <li>For every built-in memoized function defined in the ACL2 logic, the
 memoization is done in the usual way (during the ACL2 build), using the @(tsee
 memoize) event during the ACL2 build.  Such functions can thus be @(tsee
 unmemoize)d by users in the usual way.  Thanks to David Rager for requesting
 this enhancement.</li>

 <li>A new @('memoize') keyword, @(':stats'), can control whether statistics
 will be saved for reporting with @('(memsum)').</li>

 <li>Memoization in @(see hons-enabled) ACL2(p) is no longer affected by calls
 of @(tsee set-waterfall-parallelism).</li>

 </ul>

 <p>(ACL2(p) only, either @(see hons-enabled) or not) The function @(see
 Cpu-core-count) is now sensitive to environment variable @('ACL2_CORE_COUNT').
 See @(see cpu-core-count).  Thanks to Jared Davis for requesting this
 enhancement.</p>

 <p>Support for multi-threading has been added for memoization.  Thanks to
 Jared Davis for contributing an initial implementation.  Note that this may
 slow down @(see hons-enabled) ACL2(p) by several percent on
 memoization-intensive applications.  Undocumented function
 @('mf-multiprocessing') is available for low-level system hackers to turn
 on/off this feature, which by default is off for @(see hons-enabled) ACL2 and
 on for @(see hons-enabled) ACL2(p).</p>

 <p>(ACL2(p) only, either @(see hons-enabled) or not) We fixed a bug in @(tsee
 pand), which we believe was also a bug in @(tsee por), @(tsee pargs), and
 @(tsee plet). (Technical remark: this bug had a low-level cause, pertaining to
 maintenance of a Lisp variable, @('*ld-level*'), that holds the number of
 nested calls of @(tsee ld).)  Thanks to Jared Davis for reporting this bug and
 to David Rager for assisting in its repair.  Below is a slightly simplified
 version of Jared's example, which formerly caused an assertion error but now
 works as expected.</p>

 @({
 (defmacro pand* (x y)
   `(spec-mv-let (yval)
                 ,y
                 (mv?-let (xval)
                          ,x
                          (if xval
                              yval
                            nil))))
 (defn f3 (x)
   (pand* x x))
 (defn f4 (x)
   (pand x
         (f3 x)))
 (value-triple (f4 5))
 })

 <p>(Only for @(see hons-enabled) executables on Windows) Certain memory
 management is avoided on Windows (technically: by avoiding a call of source
 function @('start-sol-gc')), where it was causing errors.  Thanks to Harsh
 Raju Chamarthi and Sol Swords for testing on Windows that led us to this
 change.</p>

 ")

(defxdoc note-7-0-memoize
  :parents (note-7-0)
  :short "ACL2 Version  7.0 Notes on Changes to Memoization Implementation"
  :long "<p>See @(see memoize) for a user-level introduction to function
 memoization.  Here we summarize technical changes made in Version 7.0 of ACL2
 to the implementation of function memoization; most ACL2 users should have no
 need to read further in this topic.  We thank Jared Davis for helpful
 conversations.</p>

 <p>The function @('memoize-init') now resets the table @('*memo-max-sizes*'),
 which is used when creating memo tables and pons tables.  This change may be
 irrelevant, since generally memoize-init is only called at startup.  But it
 seemed appropriate to reset it along with all other globals involved in the
 memoization implementation.</p>

 <p>Lisp variable *print-pretty* is no longer globally set to @('t') by
 certain memoization code.  Probably this change will not generally be
 observable.</p>

 <p>The utility @(tsee clear-memoize-statistics) now resets data for the pons
 summary, but implementation function @('clear-memo-tables') no longer does
 so (it only calls @('clear-memoize-tables')).</p>

 <p>Avoided some recklessness in computing statistics related to ponsing
 (specifically, replaced @('very-unsafe-incf') by macro @('safe-incf-pons'),
 which is a wrapper for @('safe-incf')).</p>

 <p>@('Clear-memo-tables') no longer takes @('&rest') arguments, since it is
 merely a wrapper for @(tsee clear-memoize-tables), which does not (and did
 not) take @('&rest') arguments.</p>

 <p>For the utility @('pons-summary'), we no longer use @('our-syntax-nice');
 so far example, @('*print-case*') is not bound to @(':downcase').</p>

 <p>Function @('internal-real-ticks') (formerly @('internal-real-time')) now
 uses @(tsee logand) in its implementation, which should improve performance.
 It also replaces, for non-static-hons implementations, the call
 @('(get-internal-real-time)') by @('(the mfixnum (get-internal-real-time))'),
 which can also help performance.</p>

 <p>More principled, consistent use is made of @('our-syntax') for suitable
 printing.</p>

 <p>Added ``TO DO'' comments near the top of source file
 @('memoize-raw.lisp').  Thanks to Jared Davis for suggesting some of
 these.</p>

 <p>We improved many comments in source file @('memoize-raw.lisp').</p>

 <p>We did some renaming, including the following (note that
 this is probably not a complete list):</p>

 @({
 - number-of-arguments       -> mf-len-inputs
 - number-of-return-values   -> mf-len-outputs
 - *compute-array*           -> *callers-array*
 - maybe-count-pons-calls    -> incf-pons-calls
 - maybe-count-pons-misses   -> incf-pons-misses
 - print-alist               -> mf-print-alist
 - shorten                   -> mf-shorten
 - outside-p                 -> outside-caller-p
 - ofni                      -> mf-make-symbol
 - ofnum                     -> mf-num-to-string
 - internal-real-time        -> internal-real-ticks
 - dcls                      -> mf-dcls
 - hl-without-interrupts     -> without-interrupts [which already existed]
 - *ma-initial-max-symbol-to-fixnum* -> *initial-max-symbol-to-fixnum*
 - REPLACEMENT:
   *initial-max-memoize-fns* -> *initial-2max-memoize-fns*
 })

 <p>We eliminated some dead code, including the following functions (probably
 not a complete list): @('our-syntax-brief'), @('ofnm'), @('uses-state'),
 @('global-restore-memoize'), @('prine-alist'), @('set-gc-threshold'),
 @('our-gctime'), and @('short-symbol-name'), and all variants of format
 functions with names starting with \"of\" except for @('ofni') (now
 @('mf-make-symbol')) and @('ofnum') (now @('mf-num-to-string')).  Also, we
 moved @('memoize-here-come') to community book
 @('books/centaur/memoize/old/profile-raw.lsp').  Regarding
 @('our-syntax-brief'): there had been one call, in @('print-call-stack'), but
 that call did not seem appropriate so we deleted it.</p>

 <p>The variable @('*count-pons-calls*') was deleted.  It had been set to
 @('t') and was only used during macroexpansion of @('incf-pons-calls') and
 @('incf-pons-misses') (formerly @('maybe-count-pons-calls') and
 @('maybe-count-pons-misses')), where that macroexpansion was done at ACL2
 build time &mdash; hence user setting of @('*count-pons-calls*') had no
 effect.</p>

 <p>We eliminated a needless error check that prevented loading
 @('memoize-raw.lisp') without @('#+hons'), since we don't currently ever
 expect to try to do that.</p>

 <p>Miscellaneous additional code cleanup has been done.  Here is a (probably
 very incomplete) list.</p>

 <ul>

 <li>@('Float-ticks/second-init') uses a default rather than duplicating the
 default's code, and has improved treatment of errors.</li>

 <li>Removed unused @(':before') field of @('memoize-info-ht-entry')
 record.</li>

 <li>The implementations of @('number-of-arguments') and
 @('number-of-return-values') (now called @('mf-len-inputs') and
 @('mf-len-outputs'), respectively) have been made cleaner, in particular,
 starting with an empty @('*number-of-arguments-and-values-ht*').</li>

 <li>New macros such as @('ma-index') provide some abstraction, to give the
 illusion that @('*memoize-call-array*') is two-dimensional.</li>

 <li>We broke up some definitions, in particular substantially shortening
 @('memoize-fn') by moving parts of it into new functions
 @('memoize-fn-inner-body'), @('memoize-fn-outer-body'), and
 @('memoize-fn-def').  A benefit: it is easy to see the definition that is
 actually created when memoizing, by tracing @('memoize-fn-def').</li>

 <li>Added raw Lisp interface function @('mf-note-arity') for informing
 @('memoize-fn') of input and output arities.</li>

 <li>@('Coerce-index') asserts that an index is in range rather than treating
 an out-of-range index as a symbol.</li>

 <li>We renamed some variables to make them clearer.  In particular, it is
 whether a variable stores time or ticks.</li>

 <li>We now make complete and correct (we hope) the use of suitable @('fixnum')
 and @('mfixnum') declarations, many of which had been missing or
 incorrect.</li>

 <li>Both @(tsee memoize) and @(tsee unmemoize) are now safe for control-c and
 unexpected errors.</li>

 <li>We no longer set @('ccl::*save-definitions*') or
 @('ccl::*fasl-save-definitions*') to @('t').  This may improve performance,
 but it may require explicitly calling @('mf-note-arity'), as is now done in
 @('books/centaur/aig/bddify.lisp').  However, this removes CCL-only behavior;
 in particular, we removed dependence on #+Clozure in
 @('books/centaur/aig/bddify.lisp') for profiling @('count-branches-to').</li>

 <li>We use @('#+ccl') instead of @('#+Clozure'), for consistency with most of
 the rest of ACL2.</li>

 <li>We no longer set @('ccl::*save-source-locations*') or
 @('ccl::*record-source-file*') to @('t'), as there is no clear advantage to
 doing so, and in fact there is a comment near the end of source file
 @('acl2.lisp') suggesting that there could be slowdown from setting (at least)
 the first of these variables to @('t').</li>

 <li>We slightly modified @('internal-real-time') to improve its
 performance (see comments there).</li>

 <li>We fixed a performance bug in function @('addr-for') (parenthesis error
 was needlessly putting us in the ``large-case'').</li>

 <li>Fixed a typo: declaim of fixnum type for @('*initial-max-memoize-fns*')
 had instead been for nonexistent variable
 @('*initial-2max-memoize-fns*').</li>

 <li>In @('memoize-fn'), we removed support for @(':condition') to be a
 function symbol, which was at best confused.</li>

 <li>The table @('*never-memoize-ht*') is now populated mostly automatically,
 by @('initialize-never-memoize-ht').</li>

 <li>Slight optimization: the form @('(update-attached-fn-called
 ,*attached-fn-temp*)'), which had been in the definition of @('memoize-fn')
 but now is in @('memoize-fn-inner-body'), is conditioned on
 @(',*attached-fn-temp*').</li>

 </ul>")

(defxdoc note-7-1

; Total number of release note items: 52.

; Fixed a bug in string-prefixp, which continues to be used only in support of
; moving system books directories.

; In the course of fixing :puff, we introduced function remove-lisp-suffix and
; used it in several functions, as well as in a fix for event tuples for
; include-book forms so that the access-event-tuple-form is a legal
; include-book, not using the ".lisp" suffix.

; Removed an irrelevant (always false) test in function ffnnamesp-eq.

; Function print-pstack-and-gag-state has been modified and renamed
; print-summary-on-error, in support of printing rules and hint-events when
; interrupting a proof.

; Made trivial efficiency edit in trans-eval.

; While fixing the "bug in the printing of user-level terms involving
; nth (etc.) and stobjs (see below), we also simplified the code for
; untranslate1 by removing special cases for calls of binary-+, unary-/, and
; unary--, which are all handled by the untrans-table.

; The following examples illustrate the bugs in the storing of the
; backchain-limit-lst for rules.

; - Example (type-prescription) of ignored :backchain-limit-lst:

;   (defstub f1 (x) t)
;   (defstub f2 (x) t)
;   (defstub f3 (x) t)
;   (defstub f4 (x) t)
;   (defaxiom f1->f2
;     (implies (f1 x) (f2 x))
;     :rule-classes :type-prescription)
;   (defaxiom f2->f3
;     (implies (f2 x) (f3 x))
;     :rule-classes :type-prescription)
;   (defaxiom f3->f4
;     (implies (f3 x) (f4 x))
;     :rule-classes ((:type-prescription :backchain-limit-lst 1)))
;   ; The following THM should fail, but instead succeeds (before the fix).
;   ; Note: If instead of using :backchain-limit-lst we first evaluate
;   ; (set-default-backchain-limit 1)
;   ; then the following fails, as expected.
;   (thm (implies (f1 x) (f4 x)))

; - Example (type-prescription) of hard Lisp error:

;   (defstub f1 (x) t)
;   (defstub f2 (x) t)
;   (defstub f3 (x) t)
;   (defstub f4 (x) t)
;   (defaxiom f1->f2
;     (implies (f1 x) (f2 x))
;     :rule-classes :type-prescription)
;   (defaxiom f2->f3
;     (implies (f2 x) (f3 x))
;     :rule-classes :type-prescription)
;   ; Hard Lisp error:
;   (defaxiom f3->f4
;     (implies (and (f2 x) (f3 x))
;              (f4 x))
;     :rule-classes ((:type-prescription :backchain-limit-lst (2 1))))
;   ; Fails as expected after the bug fix:
;   (thm (implies (f1 x) (f4 x)))

; - Example (meta):

;   (defstub f1 (x) t)
;   (defstub f2 (x) t)
;   (defstub f3 (x) t)
;   (defstub f4 (x) t)
;   (defaxiom f1->f2
;     (implies (f1 x) (f2 x))
;     :rule-classes :rewrite)
;   (defaxiom f2->f3
;     (implies (f2 x) (f3 x))
;     :rule-classes :rewrite)
;   (defevaluator evl evl-list
;         ((f3 x) (f4 x)))
;   (defun my-meta-hyp-fn (x)
;     (if (equal x '(f4 x))
;         '(f3 x)
;       x))
;   (defun my-meta-fn (x)
;     (if (equal x '(f4 x))
;         *t*
;       x))
;   (set-default-backchain-limit 1)
;   (defaxiom my-meta
;     (implies (and (pseudo-termp x)
;                   (alistp a)
;                   (evl (my-meta-hyp-fn x) a))
;              (equal (evl x a)
;                     (evl (my-meta-fn x) a)))
;     :rule-classes ((:meta ; :backchain-limit-lst 1
;                     :trigger-fns (f4))))
;   ; The following THM should fail, but instead succeeds (before the fix).
;   ; Note: this THM does fail, even before the fix, if we uncomment the
;   ; :backchain-limit-lst above, regardless of whether or not we first
;   ; evaluate the set-default-backchain-limit call above.
;   (thm (implies (f1 x) (f4 x)))

; Here are some remarks on the fix, "Fixed a bug in the processing of certain
; operations on pathnames containing "..\"."  The bug was discovered with the
; ld-error-action mod (described below), with an error message complaining
; about a non-existent filename upon executing the command (ld
; "../lib2.delta1/../support/logand.port") in support of certifying community
; book books/rtl/rel11/rel9-rtl-pkg/support/lib3.delta3/gl.lisp.  The problem
; was that function remove-after-last-directory-separator (now split into two
; functions, get-parent-directory and get-directory-of-file) was failing to
; return a parent directory when what was being removed was a trailing "..".
; In the course of fixing that bug, we also realized that we had not properly
; accounted for filenames that include ".." as part of their names (as opposed
; to indicating a parent directory), so we fixed that too; see the new function
; find-dot-dot.

; Removed a premature mention of the expansion file in output for Step 4 of
; certify-book.

; Following a suggestion from Gary Byers, we now avoid process-interrupt in
; start-sol-gc.

  :parents (release-notes)
  :short "ACL2 Version  7.1 (May, 2015) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes to ACL2 since Version 7.0 into the
 following categories of changes: existing features, new features, heuristic
 and efficiency improvements, bug fixes, changes at the system level, Emacs
 support, and experimental versions.  Each change is described in just one
 category, though of course many changes could be placed in more than one
 category.</p>

 <p>The default build is @(see hons-enabled), as for the previous release; but
 the generated executable is now @('saved_acl2'), as discussed below.  Please
 note that ACL2(c) (``classic ACL2'', i.e., ACL2 that is not @(see
 hons-enabled)) now builds as @('saved_acl2c'), is deprecated, and will likely
 be unsupported or even eliminated in future releases.</p>

 <p>See also @(see note-7-1-books) for a summary of changes made to the ACL2
 Community Books since ACL2  7.0, including the build system.</p>

 <h3>Changes to Existing Features</h3>

 <p>For both @(tsee add-include-book-dir) and @(tsee add-include-book-dir!),
 the second argument is no longer evaluated (which we think could perhaps have
 been exploited to get unsound behavior, by arranging for the value of the
 second argument to depend on @(tsee state)).  Moreover, that argument can not
 only be a string, but also can be a <i>sysfile</i>: an object @('(:system
 . filename)'), where @('filename') is a file name.  When filename is a
 relative pathname, the meaning of such an object is the file with that
 pathname under the system books directory.</p>

 <p>The event summary had not been printed when a proof is interrupted
 (that is, with Control-C).  Now, summary information is printed for two
 summary types (see for example @(see set-inhibited-summary-types)): rules and
 hint-events.</p>

 <p>By default, @('(memsum)') is now truncated to 100 entries rather than to 20
 entries.  (Implementation note: raw Lisp variable @('*memoize-summary-limit*')
 is 100 instead of 20.)</p>

 <p>Calls of @('THE') no longer cause a @(see guard) violation when
 guard-checking is @('nil').  Also see @(see the) and see @(see
 set-guard-checking).</p>

 <p>Type declarations for @(tsee let) and @(tsee mv-let) forms are now @(see
 guard)-checked.  Consider for example the definition: @('(defun
 foo () (let ((x t)) (declare (type integer x)) x))').  Previously, evaluation
 of the call @('(foo)') had failed to result in a guard violation error; now,
 it does, provided guard-checking is on (i.e., not @('nil') or @(':none'); see
 @(see set-guard-checking)).</p>

 <p>The symbols @('ctx'), @('hist'), @('pspv'), @('unquote'), and @('value')
 have been added to @(tsee *acl2-exports*).  Thanks to Jared Davis for
 suggesting these additions.</p>

 <p>Consider @(':use') or @(':by') @(see hints) in which a variable bound using
 the @(':instance') keyword is in the wrong package.  For example, for the hint
 @(':use ((:instance foo (x 3)))'), suppose that the lemma @('foo') mentions
 the variable @('bar::x'), but not @('x').  This situation formerly caused an
 error, but now, @('x') indicates the variable @('bar::x') from the lemma
 @('foo').  See @(see lemma-instance), in particular Condition (4), which has
 been updated accordingly.  Thanks to David Rager for a remark that led us to
 implement this enhancement.</p>

 <p>The @(tsee ld) special @('ld-error-action') may now have a value @('(:exit
 N)'), where @('N') is a natural number.  If an error occurs for a call of
 @('ld'), then this value causes the ACL2 process to quit with exit status
 @('N').  See @(see ld-error-action).  Note that @('ld-error-action') is set to
 this new value when using the @('cert.pl') utility provided with the community
 books; see @(see BUILD::pre-certify-book-commands).  Thanks to David Rager for
 presenting an example showing how this change can make it easier to locate
 certain certification failures, and thanks to Sol Swords for helping in the
 design of this enhancement.</p>

 <p>A \"@(csee Theory)\" warning is still printed when @(see definition)s of
 certain built-in functions, such as @(tsee mv-nth), are @(see disable)d;
 similarly for some built-in @(see executable-counterpart) rules.  However, we
 now print such warnings only when the disabling occurs, rather than every time
 an @(tsee in-theory) event or hint is evaluated.  For example, if you evaluate
 @('(in-theory (disable mv-nth))') followed by @('(in-theory (disable
 append))'), then the second event will no longer produce a warning about
 @('mv-nth').  Thanks to Eric Smith for (most recently) suggesting such a
 change.</p>

 <p>(SBCL only) ACL2 built on SBCL now reports bytes usage, both in @(tsee
 time$) and in @(tsee memsum), essentially exactly as has already been done for
 ACL2 built on CCL.  Thanks to Jared Davis for suggesting this enhancement.</p>

 <p>(SBCL only) @(csee Fast-alists) can now be garbage collected (we believe)
 in SBCL, as they had already been done in CCL.  (Implementation note: The
 change was to use weak hash tables in the implementation of SBCL fast-alists.)
 Thanks to Jared Davis for suggesting this enhancement.</p>

 <p>The utility @(tsee ec-call) can now be applied to calls of symbols
 introduced with @(tsee defun-inline), or with @(tsee define) using keyword
 argument @(':inline t'), thanks to a request from Jared Davis.  For example,
 the following is now legal.</p>

 @({
 (defun-inline foo (x)
   (cons x x))

 (defun bar (x)
   (ec-call (foo x)))
 })

 <p>The @(see proof-builder) is now sensitive to the current @(see
 case-split-limitations).</p>

 <h3>New Features</h3>

 <p>The Common Lisp function @(tsee sleep) is now defined in ACL2.  Thanks to
 Jared Davis for requesting this addition.</p>

 <p>Custom error messages may now be created for guard violations.  See @(see
 set-guard-msg).</p>

 <p>The new macro @(tsee assert*) is like @(tsee assert$), except that
 @('assert*') only generates a @(see guard) proof obligation, not a runtime
 check.  @('Assert*') is defined using a new macro @(see mbt*), which is a
 variant of @(tsee mbt): a call of @('mbt*') logically returns @('t'), but
 generates the same @(see guard) proof obligation as @('mbt').  Thanks to
 Shilpi Goel for a query that led us to add these macros.</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>We fixed an inefficiency that could occur in calls of @(see program)-mode
 functions that update @(see stobj)s.  See the discussion of invariant-risk in
 the @(see documentation) topic, @(see program-wrapper).  Thanks to Jared Davis
 for bringing this issue to our attention.</p>

 <p>We improved the ``worse-than'' heuristic, providing modest speed-up and
 eliminating the use of memoization for it.  Thanks to Jared Davis for useful
 discussions on the topic, and to Camm Maguire for an observation that led us
 to do some investigations that led to this improvement.  For more information
 see comments in source function @('worse-than-builtin-clocked') (source file
 @('type-set-b.lisp')).</p>

 <p>We avoid the cost of translating ACL2 terms (see @(see term)) to user-level
 syntax after applying the ``preprocess'' simplifier (see @(see
 hints-and-the-waterfall)), and also after applying either @(':use') or
 @(':by') @(see hints).  Thanks to David Rager for helpful discussions towards
 this change.  Note: On rare occasions, this might change the prover flow as
 follows.</p>

 <ul>

 <li>Consider the case that the input goal, \"Goal\", simplifies with the
 ``preprocess'' simplifier to a new goal that prints the same as \"Goal\".
 Formerly, this case avoided labeling the new goal as \"Goal'\"; it was as
 though the new goal was actually the user input.  The new criterion for
 avoiding \"Goal'\" is somewhat weaker: the internal syntax must suitably match
 for \"Goal\" and its simplification, rather than their displayed forms.</li>

 <li>Consider the application of a @(':use') or @(':by') hint.  In such cases,
 the resulting constraint (if any) is simplified with the ``preprocess''
 simplifier.  Formerly, the rules used by that simplifier were not recorded if
 the printed version of the simplified constraint was equal to the original
 constraint, which was really a bug since the comparison was between the
 user-level syntax of the simplified constraint and the internal syntax of the
 original constraint.  Now, ACL2 compares the internal syntax of each.</li>

 </ul>

 <p>We fixed an inefficiency that could occur in processing of @(tsee
 make-event) forms.  Thanks to Sol Swords for reporting and diagnosing the
 problem.  (Technical note: The fix involves avoiding, in most cases, looking
 up world global @(''boot-strap-flg') by using a new state global instead of
 the same name.)</p>

 <p>We changed the heuristics for equality substitution so that so-called
 <i>cross-fertilization</i>, where an equality substitution is made on only one
 side of the goal's conclusion, is not made when generalization is turned off,
 as with the hint @(':do-not '(generalize)').  Instead, the equality is used
 throughout the goal in that case.  Thanks to David Hardin for bringing an
 example to our attention that led us to make this change.</p>

 <p>Some clause-building (essentially, goal-building) operations already
 avoided duplication, but now consider clauses to be ``duplicates'' when the
 only difference is commuted arguments of @(tsee equal) or @(tsee iff).  (Note:
 This change was made in support of @(tsee assert*) and @(tsee mbt*), mentioned
 above.)</p>

 <p>(SBCL only) It had been the case for host Lisp SBCL that the use of @(tsee
 defun-inline) to define functions in @(see books) had failed to result in
 inlined code, when those functions were called after including those books.
 This has been fixed (and appears not to have been a problem for host Lisp
 CCL).  Thanks to Jared Davis for bringing this issue to our attention.</p>

 <h3>Bug Fixes</h3>

 <p>A potential soundness issue could result from the application of @(see
 meta)functions and @(see clause-processor)s: although ACL2 checked that their
 outputs contain only legal @(see term)s, it did not check for the absence of
 calls of certain ``forbidden'' function symbols.  For example, @(see sys-call)
 should be prohibited unless there is an active trust tag (see @(see defttag)),
 but a metafunction was able to introduce a call of @('sys-call').  We have
 added the necessary checks, in a way that we hope has negligible impact on
 performance.  To avoid that impact or to learn more about this issue, see
 @(see set-skip-meta-termp-checks); this new utility, which requires a trust
 tag, avoids not only the new checks but even the above-mentioned checks for
 legal terms.</p>

 <p>The edited log below illustrates a bug that we have fixed, involving the
 processing of @(tsee include-book) @(see events) in the certification @(see
 world) whose filename starts with the tilde (@('~')) character.</p>

 @({
 ~/temp/incl$ cat sub/bad.acl2
 (include-book \"~/acl2/acl2/books/arithmetic/top\")
 ~/temp/incl$ acl2h
 [[.. output elided ..]]
 ACL2 !>(ld \"sub/bad.acl2\")
 [[.. output elided ..]]
 ACL2 !>(certify-book \"foo\" 1)


 HARD ACL2 ERROR in ABSOLUTE-PATHNAME-STRING-P:  Implementation error:
 Forgot to apply expand-tilde-to-user-home-dir before calling absolute-
 pathname-string-p. Please contact the ACL2 implementors.



 ACL2 Error in TOP-LEVEL:  Evaluation aborted.  To debug see :DOC print-
 gv, see :DOC trace, and see :DOC wet.

 ACL2 !>
 })

 <p>Fixed several issues with the @(':puff') command, and updated its
 documentation accordingly.  See @(see puff).</p>

 <p>Fixed a bug in the @(see proof-builder)'s @('wrap') command.  Thanks to
 Keshav Kini for sending a simple example that illustrated this bug.</p>

 <p>(Allegro CL only) Fixed a bug in @(tsee trace!), which for example was
 evidenced when evaluating @('(trace! (nth :native t))').</p>

 <p>Fixed a bug in the printing of user-level terms that failed to account for
 @(tsee untrans-table) entries for @(tsee nth), @(tsee update-nth), and @(tsee
 update-nth-array), when printing the first argument as a symbolic constant
 corresponding to a @(see stobj) argument.  Thanks to Warren Hunt for reporting
 this issue with an example much like the following.  When submitting the forms
 below, ACL2 output for the final form displayed the user-level term
 @('(update-nth *fld* v st)') instead of the expected form, @('(!nth *fld* v
 st)').</p>

 @({
 (defstobj st fld)

 (defmacro !nth (x y z)
   `(update-nth ,x ,y ,z))

 (add-macro-fn !nth update-nth)

 (thm (equal (update-fld v st)
             xxx)
      :hints ((\"Goal\" :in-theory (disable update-nth))))
 })

 <p>Fixed a failure to @(see guard)-check @(see type) declarations for @(tsee
 let) and @(tsee mv-let) forms.  Consider for example:</p>

 @({
 (defun foo (x)
   (let ((a (car x)))
     (declare (type string a))
     a))
 })

 <p>Previously, the call @('(foo '(3 4))') did not cause a guard violation,
 even though it should have done so.  (Indeed, the event @('(verify-guards
 foo)') failed, and continues to fail.)</p>

 <p>Fixed a bug in redundancy checking for @(tsee mutual-recursion) events that
 specify @(':')@(tsee ruler-extenders) in an @(tsee xargs) @(tsee declare)
 form.  Thanks to Sol Swords for sending an example that illustrates the bug: a
 @(tsee mutual-recursion) event that, when executed twice, caused an error the
 second time rather than being redundant (see @(see redundant-events)).  The
 bug was actually in how ACL2 stores information about the @(see
 ruler-extenders) used in definitions: the @(':ruler-extenders') specified for
 the first @(tsee defun) was being mistakenly stored for the second @('defun').
 This mishandling of redundancy for @(tsee mutual-recursion) events appears to
 be the only consequence of that bug.</p>

 <p>The following bug was probably not observable, but violated our claim that
 the system behaves as logically specified.  When a @(see guard) check failed
 during execution, the error message that was printed could differ slightly
 from what is logically specified.  (Technical detail: the error actually
 printed by source function @('ev-fncall-rec') was appropriately showing the
 original guard, but the specification function @('ev-fncall-rec-logical') was
 showing the untranslation of the translated guard.)  This has been fixed.</p>

 <p>The @('save') and @('retrieve') commands for the @(see proof-builder) (see
 @(see acl2-pc::save) and @(see acl2-pc::retrieve)) now cause an error when the
 supplied name is not a symbol; similarly for the @(':event-name') argument of
 @(tsee verify).  The behavior wasn't as expected for non-symbol names; for
 example, after issuing the instruction @('(save 'abc)') in the @(see
 proof-builder), the command @('(retrieve 'abc)') failed to resume the
 proof-builder session.  (Notice the erroneous use of the quoted symbol
 @(''abc'), i.e., @('(quote abc)'), rather than of the symbol @('abc').)
 Thanks to Keshav Kini for bringing this problem to our attention.</p>

 <p>We fixed the following two bugs in the processing of backchain limits
 stored for rules.  Thanks to Dave Greve for bringing these to our
 attention.</p>

 <ul>

 <li>For rules of class @(':')@(tsee type-prescription), the specification of
 @(':backchain-limit-lst') within the @(':')@(tsee rule-classes) could be
 ignored or cause a hard Lisp error.</li>

 <li>For rules of class @(':')@(tsee meta), preceding calls of @(tsee
 set-default-backchain-limit) were ignored.</li>

 </ul>

 <p>Fixed a bug in the processing of certain operations on pathnames containing
 @('\"..\"').</p>

 <h3>Changes at the System Level</h3>

 <p>By default, the ACL2 executable once again is named @('saved_acl2'), though
 unlike previous versions, this executable is @(see hons-enabled).
 Correspondingly, the ACL2(c) executable (that is, the executable that is not
 @(see hons-enabled)) is by default @('saved_acl2c').  Thanks to David Hardin
 for suggesting these changes.</p>

 <p>Links from the home page to user's manual topics now point to the
 ACL2+Books combined manual, not the ACL2 (only) User's Manual, except for the
 one link that explicitly points to the latter.  Thanks to David Hardin for
 feedback leading to this change, which was incorporated into the ACL2 Version
 7.0 home page several days after the release of that version.</p>

 <p>Garbage collection notification has been turned off by default, not only
 for ACL2(c) as before, but also for (the default build) ACL2(h).  Thanks to
 Eric Smith for suggesting this change.  See @(see acl2-customization) and see
 @(see gc-verbose) for how to turn such notification back on in your own
 environment.</p>

 <p>It is now possible to move the system books directory after certifying its
 books, without invalidating their status as certified.  Users should generally
 not notice this change.  We thank Harsh Raju Chamarthi and Camm Maguire for
 reporting problems with hacks we have produced over the years to support
 distribution of books with their @(see certificate) files.  Those hacks are no
 longer necessary: as a byproduct of this change, we have deleted both the
 @(see community-books) directory @('books/fix-cert/') and the source function
 @('make-certificate-file-relocated').  For a bit more detail see the final
 remark in the topic @(see full-book-name).  We also thank Eric Smith, Jared
 Davis, and Sol Swords for reporting bugs in our initial implementations of
 this enhancement.</p>

 <p>The @('certify-books') target for @('make') now excludes other expensive
 directories in addition to @('workshops').</p>

 <p>(SBCL only) Modified the handling of environment variable @('SBCL_HOME').
 Thanks to Jared Davis for pointing out a problem leading to this change,
 namely, failure on his platform when evaluating @('(require :sb-sprof)') in
 raw Lisp.</p>

 <p>Intended compiler optimizations are now guaranteed to be in place.  We
 observed, thanks to communication from Jared Davis, that when ACL2 is built
 using SBCL 1.2.10, ACL2 starts up without the compiler optimizations that had
 been installed during the build.  Perhaps that has been true for other SBCL
 versions or even other Lisps.  Now, ACL2 explicitly restores those
 optimizations when it starts up.  We observed a 5% time reduction for
 SBCL-based regression after this change.</p>

 <p>Environment variable @('ACL2_WRITE_PORT') is now ignored when doing @(see
 provisional-certification).  Thanks to Sol Swords for discussing this issue,
 which arose from a failure in @(see community-books) directory
 @('books/workshops/2011/verbeek-schmaltz/sources/'), which uses @(see
 provisional-certification).</p>

 <p>(GCL only) A few tweaks were made in support of GCL changes starting with
 pre-releases of GCL 2.6.13 in late April 2015 (but these tweaks are backward
 compatible with older GCL releases).  Resulting ACL2 builds for a new GCL show
 dramatic speed-ups for a single user, perhaps cutting between a third and half
 the time, with less dramatic improvements when running regressions with @('-j
 8').  Thanks to Camm Maguire for pointing us to the changes and for improving
 GCL.</p>

 <h3>EMACS Support</h3>

 <p>The commands @('Control-t e') and @('Control-t Control-e'), defined in file
 @('emacs/emacs-acl2.el'), now check that the @('*acl2-shell*') buffer exists,
 has a live process, and has a last line matching the specification in
 @('*acl2-insert-pats*'), which has Emacs documentation (using @('Control-h
 v')) but is set to a default based on shell prompts.  Thanks to David Rager,
 Jared Davis, and Shilpi Goel for helpful discussions leading to this
 change.</p>

 <p>We installed the following two patches to file @('emacs/emacs-acl2.el'),
 both contributed by Keshav Kini.</p>

 <ul>

 <li>Emacs highlighting for forms starting with \"@('(def')\" now works when
 the \"@('def')\" symbol has a package prefix, for example,
 \"@('(fty::deflist')\".</li>

 <li>The Control-d character is no longer explicitly bound to the default,
 @('delete-char'), but instead is unbound in @('comint-mode-map'), so that the
 global binding of Control-d will take effect.  Thus, users who bind Control-d
 themselves will no longer have that binding overridden in shell-mode (or
 comint-mode).</li>

 </ul>

 <p>We made several improvements to the @(see acl2-doc) Emacs browser for ACL2
 @(see documentation).</p>

 <ul>

 <li>Fixed a bug that could occur when Emacs variable
 @('large-file-warning-threshold') is @('nil').  Thanks to Bob Boyer for
 bringing this bug to our attention.</li>

 <li>Links are now in color (blue, by default).  See @(see acl2-doc) for
 instructions on how to change or remove this color.  Thanks to Jared Davis for
 suggesting the use of color.  We are open to suggestions for improvements;
 this might be just a first step.</li>

 <li>Allow limiting search and index commands to ancestors (sub-topics,
 sub-sub-topics, etc.) of a command (including the command itself), by
 supplying a prefix argument.</li>

 <li>New @('\"p\"'), @('\"<\"'), and @('Control-TAB') commands are analogues of
 @('\"n\"'), @('\",\"'), and @('TAB') &mdash; for search, index, and next-link
 commands, respectively &mdash; to go backward instead of forward.</li>

 </ul>

 <h3>Experimental Versions</h3>

 <p>(For ACL2(p) users only; see @(see parallelism)) If parallel execution is
 enabled (see (@see set-parallel-execution)), as it is by default in ACL2(p),
 then @('hons-wash') and @('hons-clear') may be no-ops (other than to print a
 warning), in order to avoid thread-unsafe behavior.  (However, In CCL you are
 unlikely to see this restriction unless you are running more than one thread.)
 To get around this restriction, you can instead use @(tsee hons-wash!) or
 @(tsee hons-clear!), which however require a @(see trust-tag).  Thanks to Bob
 Boyer for bringing this issue to our attention.</p>

 ")

(defxdoc note-7-2

; Total number of release note items: 91.

; A non-symbol hypothesis metafunction now causes a reasonable ACL2 error
; instead of a hard Lisp error.

; (ACL2(p) only) After consulting with David Rager, tweaked wait-on-semaphore
; to accommodate change in SBCL 1.2.13.

; Improved an error message, for when guard verification inside an encapsulate
; may depend on local properties.

; Improved the error printed when :dir is given a non-keyword, to say that the
; argument is not a keyword; thanks to Eric Smith for this suggestion.

; Improved an error message produced when the import lists disagree for an
; existing defpkg and a proposed defpkg, to use words "existing" and "proposed"
; consistently.  Thanks to Eric Smith for suggesting such an improvement.

; Added :doc computed-hints as the primary parent of using-computed-hints.

; Fixed :pe so that for build-ins, a misleading comma is removed.  For example,
; :PE INTEGERP no longer has the following confusing comma: "INTEGERP is built
; into ACL2, without a defining event."  Thanks to Alessandro Coglio for
; suggesting this change.

; In support of new function read-file-into-string, eliminated the hypotheses
; of built-in rewrite rule assoc-add-pair.

; Technical note regarding the invariant-risk item below in the section on Bug
; Fixes: functions extend-32-bit-integer-stack and aset-32-bit-integer-stack
; had already been included in system constant
; *boot-strap-invariant-risk-symbols*, but that constant had been mishandled by
; the boot-strap.

; In support of new function get-skipped-proofs-p, the shape of event-tuples
; has changed, replacing the type field (accessed with access-event-tuple-type)
; by the cons of that and a new skipped-proofs-p (accessed with
; access-event-tuple-skipped-proofs-p).

; In the course of implementing the extension of :monitor to allow (for
; example) symbols, we arranged that if "Monitor" warnings are off, then
; certain computation is avoided.

; We now check at build time (near the end) that plist-worldp-with-formals
; holds of the initial ACL2 world.

; All vestiges of defdoc have been removed.  It was already undefined; for
; example, (defstub foo (x) t :doc "hi") caused an error saying that DEFDOC is
; undefined.  An item below mentions the related elimination of the keyword
; argument, :doc, for defstub, deflabel, deftheory, and defttag.  We kept the
; optional argument for defpkg simply because it might have been a lot of work
; to eliminate it, because it's not in the last position.

; Function rememoize-all now takes an optional argument to do lighter-weight
; state modification, in support of the item below about "multiprocessing".

; Added comments in memoize-call-array-grow, following a suggestion by Sol
; Swords, for how to get around messing up statistics because of resizing
; memoization structures.

; Replaced many uses of state-global-let* in table events by corresponding uses
; of with-output, with corresponding elimination of many elements of the list
; (primitive-event-macros).

; Fixed get-event-data to clear out old data even when aborting a proof from
; within the debugger (hence after (set-debugger-enable nil)), which wasn't
; happening previously.

; The following log shows why with-guard-checking cannot be applied to a form
; that can read the state.

;   ACL2 !>(defun foo (state)
;            (declare (xargs :stobjs state
;                            :guard
;                            (f-boundp-global 'guard-checking-on state)))
;            (with-guard-checking :all
;                                 (f-get-global 'guard-checking-on state)))
;   [[ .. output elided ..]]
;    FOO
;   ACL2 !>(foo state)
;   :ALL
;   ACL2 !>(thm (equal (foo state) (f-get-global 'guard-checking-on state)))
;
;   Q.E.D.
;
;   Summary
;   Form:  ( THM ...)
;   Rules: ((:DEFINITION FOO)
;           (:DEFINITION GET-GLOBAL)
;           (:DEFINITION GLOBAL-TABLE))
;   Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
;   Prover steps counted:  25
;
;   Proof succeeded.
;   ACL2 !>(equal (foo state) (f-get-global 'guard-checking-on state))
;   NIL
;   ACL2 !>

; The following is another such example.

;   (set-debugger-enable t)
;   (defun foo (x) (declare (xargs :mode :program)) (car x))
;   (with-guard-checking ; error-triple
;    :all
;    (state-global-let*
;     ((guard-checking-on nil))
;     (value (foo 3))))
;   :q
;   (@ guard-checking-on) ; :all, but should be t

; We added state-free-global-let*-safe, for use in avoiding the potential for
; bad interaction with subsidiary calls of acl2-unwind-protect (in the scope of
; with-local-state, or called in raw Lisp).  Now, state-free-global-let* pushes
; onto the *acl2-unwind-protect-stack*.  We tried to use
; state-free-global-let*-safe everywhere state-free-global-let* was used, but
; there was about a 4% slowdown in the regression suite and, at least in one
; example we investigated carefully (community book
; books/rtl/rel11/support/sqrt.lisp), there was significantly more consing.
; Changing with-guard-checking alone to use (essentially)
; state-free-global-let* didn't seem to help with consing or speed for that
; book.

; Here is an example of the bug, "ACL2 no longer prints a message for a failed
; @(':induct') hint" (which, by the way, was fixed by passing, to
; induct-msg/lose, the pspv to get the ens, rather than using (ens state)).
;
;   (set-gag-mode nil)
;   (defund foo (x) (if (consp x) (foo (cdr x)) x))
;   (thm (equal (foo x) (car (cons y y)))
;        :hints (("Goal" :in-theory (enable (:d foo)))
;                ("Goal'" :induct (foo x))))
;
; Formerly:
;
;   No induction schemes are suggested by the induction hint.  (Note that
;   FOO (including its :induction rune) is disabled, so it cannot suggest
;   an induction scheme.  Consider providing an :in-theory hint that enables
;   FOO or (:INDUCTION FOO).)  Consequently, the proof attempt has failed.
;
; Now:
;
;   No induction schemes are suggested by the induction hint.  Consequently,
;   the proof attempt has failed.

; Changed the macro name maximum-positive-32-bit-integer-minus-1 to
; minimum-negative-32-bit-integer.  Thanks to Alessandro Coglio for pointing
; out the odd name.

; The undocumented function defevaluator-form/defthms now takes an additional
; argument, evfn-lst.

; Eliminated system macro git (superseded by getpropc).

; Here is an example showing how free variables in forced hypotheses were not
; properly handled before fixing the relevant bug discussed below.

;   (defstub f1 (x) t)
;   (defstub f2 (x) t)
;   (defaxiom f1-3
;     (f1 3))
;   (defaxiom f2-prop
;     (implies (f1 y)
;              (f2 x)))
;   ; The following succeeds, both before and after the fix.
;   (thm (f2 a))
;   (ubu 'f2)
;   (defaxiom f2-prop
;     (implies (force (f1 y))
;              (f2 x)))
;   ; We appropriately get a forcing round.
;   (thm (f2 a))
;   (defaxiom f1-useless
;     (f1 (f1 x)))
;   ; There was no forcing round before this bug was fixed.
;   (thm (f2 a))

; Lowered -dynamic-space-size on CMUCL-based ACL2 executable script to 1150 on
; Darwin (Mac), to avoid error.

; Trivially tweaked dmr-string to avoid a LispWorks warning.

; Changed lexical variable *new-memoize-info-ht* to new-memoize-info-ht in
; rememoize-all to avoid LispWorks warnings.

; We eliminated LispWorks style warnings during the build.  We were getting a
; lot of them due to aggressive type-checking (e.g. unreachable code
; (with-live-state ... (f-get-global ...) ...)).

; Improved the error message when translating (mv ... <form> ...), where form
; is a non-variable form whose value is a stobj.  Thanks to Ben Selfridge for
; providing an example that led to this enhancement.

; Fixed bugs in the raw-Lisp code for LispWorks in function
; set-gc-threshold$-fn.  Thanks to David Rager for his help with the fix.  Note
; that this function is only used by ACL2(p), which is currently broken for
; LispWorks.

  :parents (release-notes)
  :short "ACL2 Version  7.2 (January, 2016) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes to ACL2 since Version 7.1 into the
 following categories of changes: existing features, new features, heuristic
 and efficiency improvements, bug fixes, changes at the system level, Emacs
 support, and experimental versions.  Each change is described in just one
 category, though of course many changes could be placed in more than one
 category.</p>

 <p>See also @(see note-7-2-books) for a summary of changes made to the ACL2
 Community Books since ACL2 7.1, including the build system.</p>

 <h3>Changes to Existing Features</h3>

 <p>The utility @(tsee with-guard-checking) is now limited to forms that do not
 reference the ACL2 @(see state).  A related new utility, @(tsee
 with-guard-checking-error-triple), may be used for forms that evaluate to
 @(see error-triple)s.  For an example showing a bug when
 @('with-guard-checking') was applied to forms that access @(see state), see
 the comment about ``with-guard-checking'' in Community Books file
 <tt>system/doc/acl2-doc.lisp</tt>, in the form @('(defxdoc note-7-2 ...)').
 We thank Jared Davis for sending us an example showing that our preliminary
 fix was not adequate; for details, and for how a trust tag can avoid the new
 restriction (at the potential cost of unsoundness), see the remark for
 advanced users in the documentation for @(see with-guard-checking).</p>

 <p>Several built-in functions are now in @(':')@(tsee logic) mode with @(see
 guard)s verified: @(tsee term-order), @('merge-sort-term-order'), @(tsee
 arity), @(tsee termp), @(tsee term-listp), and @(tsee term-list-listp) &mdash;
 new functions @('arities-okp') and @('plist-worldp-with-formals'); and (thanks
 to Eric Smith for the suggestions) @('collect-by-position'),
 @('make-lambda-application'), @('>=-len'), @('all->=-len'), @('strip-cadrs'),
 and @('alist-to-doublets').  (Technical note: This enhancement followed the
 usual process: adding or extending community books in directory
 @('books/system/'), including any new such books in
 @('books/system/top.lisp'), and updating source constant
 @('*system-verify-guards-alist*').)</p>

 <p>Deprecated utilities @('clear-hash-tables') and @('wash-memory') have been
 eliminated.  For @('clear-hash-tables'), you can get the same effect by first
 invoking @(tsee clear-memoize-tables), and then invoking either @('(hons-clear
 t)') or instead, if your executable uses static honsing, @('(hons-wash)').
 For @('wash-memory') you can invoke @('(clear-memoize-tables)') and then
 @('(hons-wash)').  Thanks to Jared Davis for helpful discussions.</p>

 <p>The @(see command)s @(':')@(tsee ubt) and @(':')@(tsee ubu) have been
 changed.  Their previous functionality is available with the commands
 @(':')@(tsee ubt?) and @(':')@(tsee ubu?), respectively.  Now, @(':')@(tsee
 ubt) and @(':')@(tsee ubu) behave much more like @(':')@(tsee ubt!) and
 @(':')@(tsee ubu!) (which have not been changed), in that they do not cause
 queries; however, unlike @(':')@(tsee ubt!) and @(':')@(tsee ubu!), the @(see
 command)s @(':')@(tsee ubt) and @(':')@(tsee ubu) do report errors.  Thanks to
 Eric Smith for requesting this change.</p>

 <p>Now, @(':')@(tsee puff*) has an optional argument that can avoid rollback
 of the world when there is an error.  See @(see puff*).</p>

 <p>After invoking @(':')@(tsee redef) and redefining functions in a @(tsee
 mutual-recursion) event, it was necessary to answer @('Y') repeatedly in order
 to complete the redefinitions.  A new option, @('Y!'), will complete the
 remaining such redefinitions without further query.  Thanks to Eric Smith for
 requesting this feature.</p>

 <p>A harmless but somewhat annoying superfluous declaration @('(DECLARE (XARGS
 :NON-EXECUTABLE T))') was, by default, included in the generated @(tsee defun)
 for a @(tsee defun-sk) event.  This has been fixed.  Thanks to Eric Smith for
 bringing this issue to our attention.</p>

 <p>The @(see proof-builder) command @('show-rewrites') (or @('sr'); see @(see
 acl2-pc::show-rewrites)) now shows additional bindings of free variables that
 would be generated when a third argument of @('t') is supplied for the
 @('rewrite') (or @('r'); see @(see acl2-pc::rewrite)) command.  Thanks to Ben
 Selfridge for noting that this information was missing.  Note that we also
 made a few trivial formatting changes for @('sr').</p>

 <p>The redundancy check for @(tsee encapsulate) @(see events) has changed in
 two small ways.  One change is described below (see ``Redundancy checking for
 @(tsee encapsulate)'').  The other change is the redundancy check now properly
 identifies a previous subsidiary @(tsee make-event) form with its expansion,
 ignoring the @('record-expansion') wrapper.  See the example labeled
 ``Redundant after Version_7.1 (as of mid-September 2015)'' in community book
 @('books/make-event/local-elided.lisp').</p>

 <p>A new mechanism for controlling the checking for @(see invariant-risk)
 replaces the raw Lisp global variable @('*ignore-invariant-risk*'), which is
 obsolete.  See @(see set-check-invariant-risk).  In particular, the default is
 now to print a (new) warning when encountering potential slowdown due to
 invariant-risk.  Note that more functions are now subject to the
 invariant-risk check; see the discussion below in the section on Bug Fixes
 that pertains to invariant-risk.</p>

 <p>The (undocumented) system utility @('with-ubt!'), which continues to be
 used in @(tsee trace!) and @(tsee disassemble$) and is now also used in @(tsee
 set-check-invariant-risk), now binds @(see LD) special @(tsee
 ld-pre-eval-print) to @('nil').  Thus, when @('with-ubt!') is invoked,
 subsidiary forms will not be printed to the screen even when the above LD
 special is non-nil.</p>

 <p>Formerly, @(tsee certify-book), @(tsee include-book), and @(tsee puff)
 operated with guard-checking off; technically, with @(see state) global
 @('guard-checking-on') bound to @('nil').  Now, that value is bound to @('t'),
 which matches the default value in the top-level loop.  Thanks to Eric Smith
 for suggesting this change to @('certify-book') and to Jared Davis for a
 helpful conversation about it.</p>

 <p>For @(see guard) proof obligations, all conjuncts from @(see stobj)
 declarations (supplied as @(':stobjs') keywords in @(tsee xargs) declarations)
 preceded all other conjuncts (i.e., from @(tsee type) declarations or @(tsee
 xargs) @(':guard') declarations).  Previously, this was only true within a
 given @(tsee declare) form.  Thanks to Dave Greve for bringing this issue to
 our attention.</p>

 <p>A new runic abbreviation has been added: @(':r'), which abbreviates
 @(':rewrite').  For example, you may use @('(:r app-assoc)') in a theory
 expression to denote the @(see rune) @('(:rewrite app-assoc)').  See @(see
 theories).</p>

 <p>It is now possible to @(see monitor) rules by supplying a symbol or other
 runic designator other than a theory (see @(see theories)), thus relaxing the
 previous requirement that a @(see rune) is supplied.  For example, the form
 @(':monitor nth t') is legal, as is @(':monitor (:d nth) t'), where before the
 corresponding command would necessarily have been @(':monitor (:definition
 nth) t').  Thanks to Eric Smith for requesting this enhancement.</p>

 <p>Suitable @(see warnings) are now printed when attempting to @(see monitor)
 @(see simple) rules of class @(':')@(tsee definition).  These had only been
 printed for simple rules of class @(':')(tsee rewrite), because of potential
 inefficiency in computing for such warnings in the case of large @(tsee
 mutual-recursion) @(see events), but that problem has been addressed in the
 ACL2 source code using @(see fast-alists).</p>

 <p>ACL2 sometimes produces smaller @('.cert') files, by avoiding certain
 macroexpansion.  Formerly, for each macro call encountered in a certification
 world or @(see make-event) expansion, ACL2 performed repeated single-step
 macroexpansion until an event form was obtained, and replaced the original
 form with that result.  The reason for this replacement was to modify certain
 @(tsee include-book) forms involving relative pathnames (though only under
 specific conditions).  Now, no such replacement is made except when such a
 modification is made to an @('include-book') call.  This change could result
 in smaller @(see certificate) (@('.cert')) files; for example, if a @(see
 portcullis) @(see command) is a macro call, @('(foo)'), that expands into a
 very large @(tsee defun) or @(tsee defthm) event, the certificate file will
 contain @('(foo)') rather than its macroexpansion.  Of course, this change
 could result in longer times for processing an @(tsee include-book) forms,
 because now macroexpansion may need to be done when they are processed; but
 such macroexpansion has always been necessary for all forms <i>within</i> a
 book, so such behavior is at least more consistent than before.  If you really
 want a portcullis macro call to be expanded, wrap it in a @(tsee make-event)
 call, for example, @('(make-event '(foo))') instead of @('(foo)').</p>

 <p>The macros @(tsee defund) and @(tsee defthmd) now produce less output.  In
 fact, the output is the same as for @(tsee defun) and @(tsee defthm),
 respectively, except for the printing of the return value, which (as before)
 looks like @('(:DEFUND NAME)') or @('(:DEFTHMD NAME)').  Thanks to Jared Davis
 for suggesting such a change.</p>

 <p>Remaining traces of legacy documentation have generally been eliminated,
 including all vestiges of the obsolete command, @('defdoc').  (@(csee
 Documentation) is now generally provided through the @(see xdoc) system.)  In
 particular, optional and keyword arguments, @('doc'), have been eliminated for
 the following macros.</p>

 <ul>
 <li>@(tsee defabsstobj)</li>
 <li>@(tsee defabsstobj-missing-events)</li>
 <li>@(tsee defaxiom)</li>
 <li>@(tsee defchoose)</li>
 <li>@(tsee deflabel)</li>
 <li>@(tsee defstobj)</li>
 <li>@(tsee defstub)</li>
 <li>@(tsee deftheory)</li>
 <li>@(tsee defthm)</li>
 <li>@('defthm-std') (defined only in ACL2(r); see @(see real))</li>
 <li>@(tsee defttag)</li>
 <li>@(tsee in-arithmetic-theory)</li>
 <li>@(tsee include-book)</li>
 <li>@(tsee push-untouchable)</li>
 <li>@(tsee regenerate-tau-database)</li>
 <li>@(tsee remove-untouchable)</li>
 <li>@(tsee reset-prehistory)</li>
 <li>@(tsee thm)</li>
 <li>@(tsee verify-guards)</li>
 </ul>

 <p>Note that @(tsee defabbrev), @(tsee defconst), @(tsee defmacro), @(tsee
 defpkg), and @(tsee defun) may still be supplied documentation strings, as a
 nod to Common Lisp.  In particular, for @('defun') and @('defmacro') this can
 ease the porting of Common Lisp code to ACL2.</p>

 <p>Several source-level definitions have changed, many of them unadvertised.
 Some are for unadvertised event commands like @('defthm-fn'), which no longer
 have a @('doc') argument (see ``traces of legacy documentation have generally
 been eliminated'' above).  Others, like @('flambda-applicationp'), are macros
 that were formerly defined with @(tsee defabbrev) but now are defined with
 @(tsee defmacro); thanks to Eric Smith for suggesting such
 simplifications.</p>

 <p>In prover output, terms of the form @('(not (not expr))') had been printed
 simply as @('expr').  That could cause confusion; for example, the following
 form would lead to the checkpoint @('(EQUAL (ALISTP X) (ALISTP X))'), where
 actually the checkpoint was @('(EQUAL (NOT (NOT (ALISTP X))) (ALISTP X))').
 This ``feature'' has been eliminated.  Thanks to Shilpi Goel for bringing this
 issue to our attention and supplying an illustrative example.</p>

 <p>A warning was formerly printed when encountering a macro call with
 duplicate keys, for example @('(foo 3 :y 4 :y 5)') where @(':y') is a keyword
 argument of the macro, @('foo').  Now, this is an error by default, in order
 to make it easier for users to catch bugs due to accidental repetition of a
 keyword argument.  However, the utility @(tsee set-duplicate-keys-action) can
 be used to allow such duplicate keys, with or without a warning.  Thanks to
 Jared Davis for requesting these changes.</p>

 <p>Warnings are no longer printed for @(':use') hints applied to functional
 instances of enabled rules.  Thanks to Eric Smith for suggesting this
 change.</p>

 <p>The second (optional) argument of @('show-accumulated-persistence') may now
 have a new value, @(':list'), which causes the results to be displayed as a
 single list with entries of the form @('(frames tries xrune)').  Thanks to
 David Rager for requesting a way to display useless @(see rune)s, sorted in a
 manner that can help with automating the creation of @('in-theory') forms that
 @('disable') unnecessary runes; also thanks for his
 helpful discussions in designing its functionality.  See @(see
 accumulated-persistence); in particular, @('(show-accumulated-persistence
 :useless :list)') can display a list of runes to consider disabling.</p>

 <p>The utility @(tsee print-gv) now takes additional keyword arguments,
 @(':conjunct') and @(':substitute'), which respectively show a specific
 conjunct of the @(see guard) evaluation that produced @('nil'), and avoid
 @(tsee flet) in favor of substituting actuals (even at the risk of
 duplication).  See @(see print-gv), and see @(see set-print-gv-defaults) for a
 utility that sets default values for the keyword arguments.  Thanks to Eric
 Smith for requesting these enhancements and for helpful discussions.  Note
 that the system default value for the @(':evisc-tuple') keyword is now the
 value of the form @('(print-gv-evisc-tuple)').</p>

 <p>@(see State) global variable @('global-enabled-structure') is now
 untouchable (see @(see remove-untouchable)).</p>

 <p>Users may see a change in the order, number, and size of termination proof
 obligations because of an optimization that removes trivial equality tests
 generated by @(tsee case) and @(tsee cond) statements.  (The removal of the
 tests can affect subsumption, which is how the order and number of proof
 obligations may change.)</p>

 <p>Once again, all documented constant, function, and macro symbols in the
 @('\"ACL2\"') package are included in the constant, @(tsee *acl2-exports*).
 Community book @('books/misc/check-acl2-exports.lisp') has been updated for
 the current documentation system to enforce this invariant in the future.
 Thanks to Jared Davis for pointing out that the symbol @(tsee extend-pe-table)
 was missing from @('*acl2-exports*') and would be a good addition; that led us
 to this change.  As also suggested by Jared, we added the symbols @(tsee
 exists) and @(tsee forall) to @('*acl2-exports*'), as well.</p>

 <p>The quantifier @(tsee forall) or @(tsee exists) used in the body of a
 @(tsee defun-sk) call must now be in the @('\"ACL2\"') package.  Many users
 will not notice this change, since the symbols @('forall') and @('exists') in
 the @('\"ACL2\"') package are now in the list @(tsee *acl2-exports*); see the
 paragraph just above.  Thanks to Alessandro Coglio for a remark leading to
 this change.</p>

 <p>Definitions are no longer redundant that have different values specified
 for their @(tsee xargs) keyword, @(':normalize').  (See @(see
 redundant-events).)  Although we are not aware of a need to make this change,
 this change eliminates a possible unsoundness.</p>

 <p>It is now the case that @('open-output-channel') and
 @('open-output-channel!') will attempt to create missing directories as
 needed.  (This had formerly been observed to be the case in CCL but not other
 Lisp implementations.)  Thanks to Jared Davis for requesting this
 enhancement.</p>

 <h3>New Features</h3>

 <p>It is now possible to make ACL2 avoid the well-formedness checks done when
 metafunctions and clause processors are run.  By default, when a metafunction
 or clause processor is run, ACL2 calls @(tsee termp) or @(tsee
 term-list-listp), respectively, on the new value to make sure it is
 well-formed.  Now, if you prove and provide a @(':')@(tsee
 well-formedness-guarantee) with the @(':meta') or @(':clause-processor')
 rule-class, you can skip these checks.  This can speed up the use of
 metafunctions and clause processors on big terms and formulas.</p>

 <p>It is now possible to ensure the integrity of statistics produced by @(tsee
 memsum) after functions are @(see memoize)d.  See @(see
 protect-memoize-statistics).  Thanks to Alessandro Coglio for noticing
 oddities in those statistics and to Jared Davis for providing an
 implementation of this new feature.</p>

 <p>Function @(tsee read-file-into-string) provides an efficient way to return
 the contents of a file as a string, without returning an ACL2 @(see state).
 Thanks to Jared Davis for pointing out a logical flaw in the initial
 implementation.</p>

 <p>A new function, @('get-skipped-proofs-p'), can tell system programmers
 whether or not a given event name was introduced with proofs skipped, as with
 @(tsee skip-proofs) or using @(tsee set-ld-skip-proofsp).  See @(see
 system-utilities).  Thanks to Eric Smith for requesting such a capability.</p>

 <p>A new @(see table) permits the association of names with substitute event
 forms, for use by @(see history) commands that print event forms, including
 @(':')@(tsee pe), @(':')@(tsee pc), @(':')@(tsee pcb), and @(':')@(tsee pcb!).
 See @(see extend-pe-table).  Thanks to Eric Smith for requesting such a
 capability.  Note that @(':')@(tsee pe!) now avoids use of this table.</p>

 <p>A new macro, @('ffn-symb-p'), has been introduced and then used in the
 source code to simplify some definitions.  Thanks to Jared Davis for a remark
 that led us to define and introduce this macro.  See @(see system-utilities)
 for a description of this and many other low-level system utilities.</p>

 <p>It is now possible to give @(see hints) that specify the use of termination
 or @(see guard) theorems for existing function symbols.  See @(see
 lemma-instance), @(see termination-theorem-example), and @(see
 guard-theorem-example).  Also see @(see gthm) and @(see tthm) for related
 query utilities.  Thanks to Alessandro Coglio and Eric Smith for requesting
 these features.</p>

 <p>See @(see set-print-gv-defaults) for a new utility for setting default
 values for the keyword arguments of @(tsee print-gv).  Thanks to Eric Smith
 for requesting this feature and for helpful discussions.</p>

 <p>For @(see history) commands and the function @(tsee disabledp), the notion
 of ``@(see disable)d'' is now computed inside the @(see break-rewrite) loop
 with respect to the @(see enable)d status at the current point of the current
 proof attempt, rather than with respect to the global state.  Thanks to David
 Rager for suggesting this enhancement.  Note that this change only affects
 @(see history) commands and @(tsee disabledp), not other utilities (for example
 @(tsee tau-status) and @(tsee guard-obligation)).x</p>

 <p>New system utility @(tsee getpropc) is a convenient abbreviation for @(tsee
 getprop).</p>

 <p>A new utility causes some warnings to be printed in a ``raw'' s-expression
 format.  See @(see set-raw-warning-format).  Thanks to Shilpi Goel for
 requesting this utility.</p>

 <p>The macro @('accumulated-persistence-oops') undoes the effect of
 accidentally clearing statistics with @('(accumulated-persistence t)') or
 @('(accumulated-persistence :all)').  See @(see accumulated-persistence).
 Thanks to Jared Davis for requesting this feature.</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>The redundancy check for @(tsee defconst) has been sped up in cases with a
 very large term, as in the following example.  Thanks to David Rager and Jared
 Davis for helpful related discussions.</p>

 @({
 (defun make-tree (n)
   (declare (type (integer 0 *) n))
   (if (zp n)
       nil
     (let ((x (make-tree (1- n))))
       (cons x x))))
 (make-event
 `(defconst *a* (hons-copy ',(make-tree 50))))
 ; Redundant, and formerly very slow:
 (make-event
 `(defconst *a* (hons-copy ',(make-tree 50))))
 })

 <p>Processing of @(tsee defpkg) forms may be faster, thanks to a change
 suggested by Jared Davis (who observed significant speedup in SBCL).</p>

 <p>Optimizations have been made that can speed up @(tsee include-book)
 for some large books, as follows.  In particular, for the form @('(time$
 (include-book \"centaur/sv/tutorial/alu\" :dir :system))') we have seen a 25%
 reduction (on Mac OS) for the first item below, and an additional 29%
 reduction (also on Mac OS) for the second item.</p>

 <ul>

 <li>Various optimizations have been made for @(see theory) manipulation,
 including some to make processing for efficient for @(tsee defund) and @(tsee
 defthmd).  Thanks to Sol Swords for bringing this issue to our attention in
 GitHub Issue #401 and for reporting bugs in our initial implementations.</li>

 <li>Redundancy checking for @(tsee encapsulate) @(see events) can be much
 faster.  The only functional change (with one small exception, described in an
 item above) is to check for a sub-event of the proposed @('encapsulate') event
 that is attempting to introduce a new name; if no such name is found, then the
 redundancy check is skipped, and the proposed @('encapsulate') event is
 evaluated.  This new check is quite thorough (see @(see
 redundant-encapsulate)), so we expect it to be rare that an @('encapsulate')
 event that was formerly redundant is no longer redundant.</li>

 </ul>

 <p>@(csee Certify-book) is faster in some cases; for example, we found the
 time required to certify a book whose only event is @('(include-book
 \"centaur/gl/gl\" :dir :system)') was reduced from 57 seconds to 10 seconds.
 (Implementation note: The change was to avoid installing worlds in function
 @('defpkg-items').  That had probably been done in order to speed up calls of
 @('simple-translate-and-eval') in @('defpkg-items-rec'), but that speed-up
 seems to be dwarfed by the expense of @('extend-world1') in such cases.)</p>

 <p>We tweaked a part of the so-called ``clausify'' process for doing Boolean
 simplification towards producing subgoals of a given goal, namely, the
 so-called ``subsumption-replacement-loop'' (specifically, source function
 @('find-subsumer-replacement')).  Thanks to Jared Davis for helpful
 discussions that led us to make this change.</p>

 <p>@(tsee Defevaluator) is faster, especially so when many functions are to be
 interpreted by the new evaluator.  The new version is a refactored version of
 community book @('books/tools/defevaulator-fast.lisp') used with the
 permission of its original authors Sol Swords and Jared Davis.  Thanks!</p>

 <p>The Common Lisp code generated for @(see stobj) accessors and updaters has
 been improved in the case that the @(':type') is @('T') or of the form
 @('(array T ...)').  In particular, we have seen efficiency improvements for
 host Lisp CCL when the value read from or written to the array is a
 fixnum (integers that are sufficiently small in absolute value).  Thanks to
 Bob Boyer and Gary Byers for helpful discussions that led to this
 improvement.</p>

 <h3>Bug Fixes</h3>

 <p>We fixed a soundness bug pertaining to @(see local) @(tsee defpkg) @(see
 events).  See community books directory @('misc/hidden-defpkg-checks/') for an
 example that exploits this bug to prove @('nil') in Version  7.1 and perhaps
 some other previous ACL2 versions.  Thanks to Sol Swords for helping us set up
 that test (specifically, suggesting addition of the comment ``@('; no_port')''
 after an @(tsee include-book) call that is not to be put into a @('.port')
 file).</p>

 <p>The use of @(tsee set-deferred-ttag-notes) during @(tsee make-event)
 expansion could cause some TTAG NOTE messages never to be printed.  Thanks to
 Jared Davis for a remark that led us to discover this bug, which could be
 considered a soundness bug since the TTAG NOTE mechanism is a key part of the
 soundness story.  With this change, the effects of
 @('set-deferred-ttag-notes') persist past @('make-event') expansion.</p>

 <p>It was possible to use @(':')@(tsee program) mode functions to write past
 the end of an array, leading to unsoundness.  This has been fixed.  Now,
 updaters for @(see stobj) array fields are marked as having so-called
 ``invariant-risk'', even when the element type of the array is
 @('t') (unconstrained).  Also marked with invariant-risk are built-in
 functions @(tsee aset1) and @(tsee aset2).  See @(see program-wrapper), @(see
 invariant-risk) and @(see set-check-invariant-risk), which is discussed above
 in the section Changes to Existing Features.  Thanks to Jared Davis and Sol
 Swords for sending an example to illustrate the bug.</p>

 <p>When ACL2 was interrupted while debugging was on (see @(see
 set-debugger-enable)), it was possible later to get the following error
 repeatedly:</p>

 @({
 HARD ACL2 ERROR in TIME-TRACKER:  It is illegal to specify :START for
 tag :TAU, because tracking for this tag is already in an active state.
 })

 <p>This problem has been fixed, by defining a new keyword argument for @(tsee
 time-tracker), @(':start!'), and using it to track the use of the @(see
 tau-system); see @(see time-tracker) and @(see time-tracker-tau).</p>

 <p>ACL2 would cause an error at startup when the value of environment variable
 @('ACL2_SYSTEM_BOOKS') was a string starting with the tilde
 character (@('~')).  This has been fixed.  Thanks to Shilpi Goel and Warren
 Hunt for bringing this bug to our attention.</p>

 <p>(GCL only) It had not been possible to define a @(see stobj) with more than
 64 fields in GCL.  We have removed that restriction.  (Technical note: GCL
 disallows calls of the function, @('vector'), with more than 64 arguments.  So
 instead we now build a list of stobj fields that is coerced to a vector,
 rather than calling @('vector') directly.)</p>

 <p>Fixed @(tsee deftheory-static) by declaring the @(see world) to be
 @('ignorable'), thus avoiding errors for forms that don't reference the
 world.  Thanks to Jared Davis for pointing out this bug with the example,
 @('(deftheory-static my-theory '(car-cons))').</p>

 <p>Fixed a bug that was causing the @('hiding-cars') component of the @(tsee
 ld-evisc-tuple) to be ignored when printing evaluation results.</p>

 <p>We avoid an error in the case that @(tsee skip-proofs) is used around a
 definition with no tests above a recursive call, as in the following
 example.</p>

 @({
 (skip-proofs (defun foo (x)
               (declare (xargs :measure (acl2-count x)))
               (identity
                (cond ((zp x) 17)
                      (t (foo (1- x)))))))
 })

 <p>Thanks to Dave Greve for bringing this bug to our attention.  Note that
 such a definitional event may be unsound (not surprisingly, because of the use
 of @('skip-proofs')).  For example, the following form succeeds:
 @('(thm nil :hints ((\"Goal\" :induct (foo x))))').</p>

 <p>Several improvements have been made to avoid errors in the execution of
 @(':')@(tsee puff) and @(':')@(tsee puff*).  Thanks to Eric Smith for
 reporting this issue.  (Technical implementation note: a bug in source
 function @('find-longest-common-retraction1-event'), used in reverting logical
 @(see world)s, was fixed in support of this work.)</p>

 <p>When the @(tsee default-defun-mode) was @(':')@(tsee logic), then a @(tsee
 mutual-recursion) form with @(tsee xargs) declaration of @(':')@(tsee program)
 mode, which also had one or more @(tsee defund) @(see events), would cause a
 error when attempting to @(see disable) new function symbols after admitting
 their definitions.  This has been fixed.  Thanks to Jared Davis for bringing
 this bug to our attention (GitHub Issue #464).</p>

 <p>We fixed some printing bugs for @(':')@(tsee psof), @(':')@(tsee pso), and
 raw proof format (see @(see set-raw-proof-format)).  Both @(':')@(tsee psof)
 and @(':')@(tsee pso) were printing explicit splitter notes (see @(see
 splitter)) &mdash; and worse yet, and thanks to David Rager for pointing this
 out, @(':')@(tsee psof) was printing them to the terminal.  Those explicit
 splitter notes were not appropriate during proof replay, where instead
 parenthetical phrases like ``@('(if-intro)')'' are sufficient; those phrases
 continue to be printed during proof replay, just as when @(see gag-mode) is
 off.  Raw proof format had a couple of whitespace bugs, but more important was
 its failure to indicate any information about splitters; so now it prints the
 same explicit splitter notes as are printed for gag-mode.</p>

 <p>Insufficient checking has been fixed for @(see signature)s.  Thanks to
 Jared Davis for sending the example @('((f * *) => * :formals (x) :guard (natp
 x))'), which was not flagged as illegal by ACL2 even though the specified
 arity of 2 did not match the length of the specified @(':formals').  There
 could also be mismatches between the @(see stobj)s specified, for example,
 with @('(((f * st1) => * :formals (x st2) :guard (natp x)))'), that were not
 flagged as illegal.</p>

 <p>The inclusion of uncertified books was leading to some incorrect messages
 about other books that are also uncertified.  This has been fixed (though the
 messages can still be verbose at times).  Thanks to Eric Smith for sending an
 example to bring this problem to our attention.</p>

 <p>There were some incorrect error messages produced for bad calls of @(tsee
 ec-call); these have been fixed.</p>

 <p>Fixed a bug in @(see memoization) that could occur when multiprocessing is
 turned on, as in the call @('(acl2::mf-multiprocessing t)') in community book
 @('books/centaur/vl/server/server-raw.lsp').  Thanks to Sol Swords for
 reporting a bad report from @(tsee memsum) when profiling function
 @('include-book-fn') before including system book @('\"doc/top\"').</p>

 <p>@(csee Guard) violation error messages printed @(''ACL2_INVISIBLE::|The
 Live State Itself|') where they should have printed @('STATE'); similarly for
 the utility @(tsee print-gv), which also failed to print entirely in
 user-level ``untranslated'' syntax.  These problems have been fixed.  Thanks
 to Eric Smith for bringing the ``@('STATE')'' bug to our attention.</p>

 <p>Infinite loops occurred for calls of @('(close-output-channel *standard-co*
 state)') after redirecting standard output using @('set-standard-co').  A
 clean error now occurs instead.</p>

 <p>We fixed a bug in @(tsee state-global-let*) &mdash; actually, in its
 supporting system utility @('acl2-unwind-protect') &mdash; that allowed
 capture of a lexical variable, @('temp'), to produce bad results, for example
 as follows.</p>

 @({
 (defun foo (temp state)
   (declare (xargs :stobjs state :mode :program))
   (state-global-let*
    ((x 3))
    (pprogn
     (fms \"TEMP = ~x0~%X = ~x1~%\" (list (cons #\0 temp) (cons #\1 (@ x)))
          *standard-co* state nil)
     (value nil))))
 (foo 17 state) ; should show TEMP = 17 and X = 3, but caused Lisp error
 })

 <p>ACL2 no longer prints a message for a failed @(':induct') hint (in the case
 that @(see gag-mode) is off), saying that a definition is @(see disable)d when
 that is not the case.</p>

 <p>(CCL only, probably only 32-bit CCL) We fixed a bug manifested with an
 error, ``is not of the expected type (UNSIGNED-BYTE 32).''  (Technical note:
 Function @('ccl::set-lisp-heap-gc-threshold') requires a fixnum, but was
 passed a bignum.)  Thanks to Harsh Raju Chamarthi for sending us a log that
 exhibited this bug, namely
 @('books/oracle/stv-invariant-extraction-pitfall/alu.lisp'), which seems to
 have evoked the bug by using an unusually large amount of memory.</p>

 <p>One might reasonably expect that for a @(see rewrite) or @(see linear) rule
 with a hypothesis of the form @('(force ...)') or @('(case-split ...)'), an
 attempt to relieve that hypothesis should be successful when forcing is
 enabled.  The situation is a bit tricky if the hypothesis has free variables,
 but even then, one would expect success if the @(':match-free') value is the
 default, @(':all'), or if no suitable bindings are found.  Such attempts had
 however not always been successful; but they are now, and the relevant
 documentation on @(see free-variables) has been clarified.  For an example
 exhibiting the bug, see the comment about ``free variables'' in Community
 Books file <tt>system/doc/acl2-doc.lisp</tt>, in the form @('(defxdoc note-7-2
 ...)').</p>

 <p>An inappropriate warning has been eliminated for some @(see
 type-prescription) rules, for example the following.</p>

 @({
 (defthm foo
   (implies (alistp mem)
            (or (equal (assoc loc mem) nil)
                (consp (assoc loc mem))))
   :rule-classes :type-prescription)
 })

 <p>The warning had claimed that the rule ``may be weaker than you expect''
 because the theorem itself ``is not provable using type-set reasoning''.  But
 the theorem is provable when @(see guard-holders) are removed, as could
 generally be expected; so now, the check is applied after removing
 guard-holders from the theorem.</p>

 <p>The @(see guard)s stored for @(see macros) now include @(see type)
 declarations.  Formerly the guards stored for macros were based only on the
 @(':')@(tsee xargs) @(':guard') keyword.  Consider for example the following
 definition.</p>

 @({
 (defmacro foo (x)
   (declare (type integer x))
   x)

 (defun bar (y)
   (foo y))
 })

 <p>Formerly, no error occurred when processing the definition of @('bar'),
 because the guard stored for @('foo') was @('t').  Now, the guard stored for
 @('foo') is @('(integerp x)'); since the variable @('y') is not an integer (it
 is a symbol), the attempted @(tsee defun) for @('bar') causes an error.</p>

 <h3>Changes at the System Level</h3>

 <p>ACL2 is now defined to incorporate its @(see hons-enabled) features.  We
 formerly supported building ACL2 without these features, resulting in
 so-called Classic ACL2, also called ``ACL2(c)''.  Such builds are no longer
 supported: although it is still technically possible to build ACL2(c), we do
 not stand behind such builds; in particular, we do not test them, and we have
 removed the @('GNUmakefile') target, @('saved_acl2c').</p>

 <p>(CCL only) Starting with CCL Version 16384, EGC (the ephemeral garbage
 collector) is enabled in ACL2 by default, in place of a ``@('start-sol-gc')''
 memory management scheme, but with some of the delay in full garbage
 collection that had been provided by that scheme.  That scheme is still
 available to users, under a different name and inside the ACL2 loop; see @(see
 set-gc-strategy).  (Note that both @('set-gc-strategy') and @('gc-strategy')
 have been added to @(tsee *acl2-exports*).)  Thanks to Gary Byers for CCL
 improvements leading to this change, and to him, Bob Boyer, Jared Davis, and
 Sol Swords for helpful discussions.  The default behavior can be restored to
 the previous behavior at ACL2 build time, by setting @('Make') variable
 @('ACL2_EGC_ON=nil') when building an ACL2 executable.</p>

 <p>A new mechanism allows importing of theorems into the ACL2 source code,
 thus extending the existing mechanism for importing termination and guard
 verification for system functions (see the item above about @(tsee
 term-order), @('merge-sort-term-order'), and so on).  Using this mechanism,
 some theorems have been imported from a new community book,
 @('books/system/termp.lisp').  (For an example of how ACL2 developers use this
 mechanism, see the call of @('system-events') in ACL2 source file
 @('boot-strap-pass-2.lisp').)</p>

 <p>File @('GNUmakefile') in the (top-level) ACL2 sources directory now sets
 environment variable @('TIME_CERT') so that regressions will generate timing
 information.</p>

 <p>(SBCL only) The @('--control-stack-size') argument for ACL2 executables
 saved for SBCL is now 64 (formerly 16).  Thanks to Jared Davis for requesting
 this increase.</p>

 <p>The existing utility @(tsee get-event-data) is now documented.  Moreover,
 it can be used for determining whether an interrupt (Control-C) occurred
 during execution of an event.  (This capability is used in a new utility,
 @(tsee removable-runes).)  See @(see get-event-data).</p>

 <p>The startup banner now shows the git commit hash for development
 snapshots.  Thanks to Bob Boyer for suggesting such a modification and to
 Jared Davis for bringing to our attention the appropriate git command for
 retrieving the hash.</p>

 <p>(CMUCL only) It is now the case for CMUCL that @(tsee setenv$) modifies the
 environment of the underlying Lisp process.  Thanks to Jared Davis for this
 suggestion, and for pointing out that CCL and SBCL [at least] already have
 this behavior.</p>

 <p>A new optimize declaration for @(tsee defun), @('(:stack-access 3)'), can
 result in some speed up for evaluations done when the host Lisp is CCL (but is
 likely to be a no-op in other host Lisps).  Thus, you may write: @('(defun
 foo (x) (declare (optimize (:stack-access 3))) ...)').  Thanks to Gary Byers
 and the CCL team for their excellent compiler work, including the new
 @('stack-access') feature, and to Bob Boyer and Warren Hunt for helpful
 discussions.  To build ACL2 on CCL with this feature, add the variable setting
 @('ACL2_STACK_ACCESS=3') to the @('make') command that you invoke to build
 ACL2.  NOTE: The use of ACL2_STACK_ACCESS relies on recognition by CCL of the
 @(':stack-access') keyword for optimize expressions, hence will only have
 effect for CCL versions starting with 16678.</p>

 <p>(CMUCL only) Updated saved_acl2 for CMUCL to use maximum heap for CMU
 Common Lisp snapshot-2016-01 and beyond.  Thanks to Raymond Toy for updating
 CMUCL such that one can specify with @('-dynamic-space-size 0') that the
 maximum heap is used.</p>

 <h3>EMACS Support</h3>

 <p>We made several improvements in the @(see acl2-doc) browser.</p>

 <ul>

 <li>A bug has been fixed in the @('S') command (@('acl2-doc-re-search')).</li>

 <li>The help message is displayed more often (but only, we think, when
 appropriate) in the echo area (i.e., below the mode line).</li>

 <li>The @('q') command (@('acl2-doc-quit')) now can be run from any buffer in
 @('acl2-doc') mode, for example after typing the @('H') command.  Moreover,
 all such buffers will be buried after @('q'); formerly, if you quit from the
 main @('acl2-doc') buffer you could have been left in the
 @('acl2-doc-history') buffer.</li>

 </ul>

 <p>@(tsee Verify-termination) calls are now indented like @(tsee defun) calls.
 Thanks to Alessandro Coglio for suggesting this change to
 @('emacs/emacs-acl2.el').</p>

 <p>The @(see acl2-doc) Emacs browser now allows handling of topics with square
 brackets.  This fix was necessary because a new topic, <tt>SV::4VEC-[=</tt>,
 broke acl2-doc; it wouldn't initialize.  The fix simply replaces characters
 @('#\\[') and @('#\\]') with @('#\\<') and @('#\\>'), respectively.  It's not
 a perfect fix, but it seems awkward to try to escape @('#\\[') (which Emacs
 Lisp thinks starts a vector).  See community book
 @('system/doc/render-doc-base.lisp').</p>

 <h3>Experimental Versions</h3>

 <p>Fixed some interleaved output that could appear with @(see
 waterfall-parallelism) enabled.  Thanks to Eric Smith for reporting this
 problem and to David Rager for a helpful chat.</p>

 ")

; Just below is a roughly alphabetical list of all community books modified in
; support of the following item from :doc note-7-3, together with a bit of
; information about the change (more can be found in comments in the books that
; mention "April 2016").  A "*" indicates modification in our second round of
; changes for this item: the *ts-one* case was included for source function
; obj-table, and so-called "strong handling of *ts-one*" was permitted in some
; cases where initially we never permitted that.
;
;   The collection of primitive @(see type-set)s supported by ACL2 has been
;   changed, by splitting the type of positive integers into two sets: the set
;   consisting solely of the number 1, and the set of integers greater than 1.
;
;   books/arithmetic-3/bind-free/integerp-meta.lisp
;   books/arithmetic-5/lib/basic-ops/integerp-meta.lisp
; Needed symbolic constants for type-set numbers

; * books/centaur/bitops/ihsext-basics.lisp
; The rule acl2::<-+-negative-0-1 now sends the proof in a different
; direction.

;   books/centaur/gl/g-logbitp.lisp
; * books/centaur/gl/hyp-fix.lisp
; Stronger reasoning allowed an additional rule to be applied, sending the
; proof in a different direction.

;   books/coi/bags/eric-meta.lisp
; Needed symbolic constants for type-set numbers

;   books/coi/records/mem-domain.lisp
; Eliminated obsolete definition of bitp.

; * books/coi/super-ihs/bit-twiddling-logops.lisp
; Stronger reasoning allowed an additional rule to be applied, sending the
; proof in a different direction, and only after eliminating destructors.

;   books/coi/super-ihs/super-ihs.lisp
; Old bitp($inline) was already disabled, so needed a hint.
; * A second change disabled the new rule bitp-compound-recognizer,
; exactly as in books/misc/mult.lisp.

;   books/ihs/logops-definitions.lisp
; Bitp$inline no longer exists.

; * books/ihs/logops-lemmas.lisp
; Disabled a type-prescription rule that had become stronger.

;   books/misc/check-acl2-exports.lisp
; Not related to this change, except that this is a good time to update.

;   books/misc/int-division.lisp
; Stronger type-set reasoning sent proof in a different direction; easy fix
; by eliminating two lemma instances in the :use hint.

; * books/misc/mult.lisp
; Disabled the new rule bitp-compound-recognizer,
; exactly as in books/coi/super-ihs/super-ihs.lisp.

; * books/models/jvm/m5/demo.lisp
; * books/projects/symbolic/m5/demo.lisp
; * books/workshops/2003/moore_vcg/support/demo.lisp
; These three are essentially the same.  A long comment in ACL2 source file
; obj-table explains something about this one.

;   books/projects/x86isa/machine/instructions/fp/fp-cmp-base.lisp
; Stronger type-set reasoning sent proof in a different direction.

;   books/projects/x86isa/proofs/zeroCopy/zeroCopy.lisp
; Bitp$inline no longer exists.

;   books/rtl/rel1/support/logdefs.lisp
;   books/rtl/rel1/lib1/bits.lisp
;   books/workshops/1999/multiplier/proof.lisp
; Restored type-prescription rule for bitn to be merely natp instead of a
; member of {0,1}; see comment about "April 2016" in logdefs.lisp.

;   books/rtl/rel1/support/merge.lisp
;   books/rtl/rel1/lib3/bits.lisp
; Deleted essentially redundant theorem.

; * books/rtl/rel11/rel9-rtl-pkg/support/lib1.delta1/float-extra2.lisp
; * books/rtl/rel9/support/lib1.delta1/float-extra2.lisp
; These two closely-related books had a failure that was easily solved by
; separating out a lemma instead of using a :cases hint, resulting in
; elimination of a subgoal hint.

;   books/std/basic/arith-equiv-defs.lisp
; Commented out bitp-compound-recognizer.

;   books/std/basic/defs.lisp
; Eliminated definition of bitp (and its defsection).

;   books/system/doc/acl2-doc.lisp
; Updated documentation (* including this comment).

;   books/workshops/2003/gamboa-cowles-van-baalen/support/kalman-defs.lisp
; Stronger type-set reasoning sent proofs in a different direction.

;   books/workshops/2003/sumners/support/n2n.lisp
; Eliminated definition of bitp.

;   books/workshops/2003/toma-borrione/support/bv-op-defuns.lisp
; Eliminated definition of bitp.

;   books/workshops/2004/sawada/support/defpkg.lsp
; Eliminated conflict in definitions of bitp.

;   books/workshops/2004/smith-et-al/support/bags/eric-meta.lisp
; Needed symbolic constants for type-set numbers.

; * books/workshops/2006/cowles-gamboa-euclid/Euclid/ed4ab.lisp
; * books/workshops/2006/cowles-gamboa-euclid/Euclid/ed4bb.lisp
; * books/workshops/2006/cowles-gamboa-euclid/Euclid/ed4cb.lisp
; * books/workshops/2006/cowles-gamboa-euclid/Euclid/ed4db.lisp
; Subgoal numbering changes.

; * books/workshops/2006/cowles-gamboa-euclid/Euclid/prime-fac.lisp
; New type-set representation caused free-variable matching to fail.

; * books/workshops/2006/pike-shields-matthews/core_verifier/Fibonacci/proof-fibs.lisp
; * books/workshops/2006/pike-shields-matthews/core_verifier/RC6/proof-RC6.lisp
; Disable a type-prescription rule that had become stronger.

(defxdoc note-7-3

; Total number of release note items: 124.

; The first type-set reasoning improvement provides big speed-up on the
; following example, essentially from Jared Davis and Sol Swords (which is even
; much slower when the list (a b ...) is lengthened).

;   (defthm tp1
;     (implies (consp a) (consp (append a b)))
;     :rule-classes :type-prescription)
;   (defthm tp2
;     (implies (consp b) (consp (append a b)))
;     :rule-classes :type-prescription)
;   (in-theory '(tp1 tp2))
;   ; 14.24 seconds before the change; 0.24 seconds after
;   (time$ (thm (consp (append a b c d e f g h i j k l m))))

; Renamed :doc topic well-founded-relation to well-founded-relation-rule, to
; accommodate the form (define well-founded-relation ...)  in
; books/kestrel/utilities/world-queries.lisp.

; We added to :doc redundant-encapsulate to add discussion of redefinition.
; Also, we tweaked a redundancy message for encapsulate so that it says "might
; not be equal" instead of "are not equal" when the encapsulate is redundant
; with a previous encapsulate that contained a make-event, as in the final
; (new) example of that :doc topic.

; Introduced a LET into the definition of signed-byte-p to improve execution
; efficiency, as suggested by Bob Boyer.

; Added :doc file-write-date$.  Thanks to Eric Smith for pointing out that this
; utility was not documented and for helping with its documentation.

; Added append-strip-cars (in :program mode, like append-strip-cdrs).

; Avoided potential quadratic time behavior by tweaking function
; newly-defined-top-level-fns-rec, to use append instead of union-eq.
; (But this seems unlikely to make much difference in practice.)

; Made trivial mod to source function subsumes1-equality-with-const, adding
; (signed-byte 30) output declaration.

; Cleaned up top-level GNUmakefile a bit, setting ACL2 if not already set;
; added check-acl2-exports target.

; Using ACL2 Version 7.2, the following script introduces a metafunction that
; rewrites a term to a ``term'' containing a :program mode function.  We even
; prove the :well-formedness-guarantee theorem for it.  Then we demonstrate a
; thm that produces a checkpoint that contains a :program mode function.  These
; events are all to be carried out before our fix to the bug discussed below,
; "The handling of metafunctions allowed an invariant to be violated...".
;
;   (defun prog-mode-fn (x)
;     (declare (xargs :mode :program))
;     x)
;
;   (defun target-fn (x flg)
;     (if (equal flg t)
;         x
;         nil))
;
;   (defun flag-hider (x)
;     (declare (ignore x))
;     t)
;
;   ; Now we introduce the metafunction simp which transforms (target-fn ... T)
;   ; to (target-fn ... (flag-hider (prog-mode-fn ...))) and we can prove this
;   ; correct without needing anything about prog-mode-fn because flag-hider is
;   ; identically T.
;
;   (defun simp (x)
;     (cond ((and (consp x)
;                 (eq (car x) 'target-fn)
;                 (equal (caddr x) *t*))
;            (list 'target-fn
;                  (cadr x)
;                  (list 'flag-hider
;                        (list 'prog-mode-fn (cadr x)))))
;           (t x)))
;
;   (defevaluator sev sev-lst ((target-fn x flg) (flag-hider x)))
;
;   (defthm simp-correct
;     (equal (sev x a)
;            (sev (simp x) a))
;     :rule-classes ((:meta :trigger-fns (target-fn))))
;
;   ; This next event is optional: whether we know simp produces a termp or we
;   ; do the runtime check after simp is applied, the result is the same: in
;   ; the thm below a :program mode function symbol is introduced into the
;   ; theorem.
;
;   (defthm simp-is-well-formed
;     (implies (and (termp x w)
;                   (arities-okp '((TARGET-FN . 2)
;                                  (PROG-MODE-FN . 1)
;                                  (FLAG-HIDER . 1))
;                                w))
;              (termp (simp x) w))
;     :rule-classes nil)
;
;   (in-theory (disable target-fn
;                       flag-hider
;                       (:type-prescription flag-hider)))
;
;   (thm (equal (target-fn x t) xxx))
;
;   *** Key checkpoint at the top level: ***
;
;   Goal'
;   (EQUAL (TARGET-FN X (FLAG-HIDER (PROG-MODE-FN X)))
;          XXX)

; Changed mf-shorten to print "///" instead of "..." when shortening for
; (memsum).  Thanks to Bob Boyer for pointing out that "..." could interfere
; with the use of READ.

; Weakened an assertion for memoize-look-up-def-raw in the case of SBCL, to
; account for SBCL output from function-lambda-expression.  Thanks to Bob Boyer
; for this fix.  We haven't seen problems that this fixes, presumably because
; of how we have avoided calling memoize-look-up-def-raw in most or all cases.

; The code in the body of verify-guards-formula is now in a new function,
; verify-guards-formula-fn.

; In GNUmakefile, changed the assignment of ACL2_HONS to h to be unconditional,
; now that classic ACL2 is unsupported.

; Fixed an error message as in the following example; thanks to Eric Smith for
; the example and the fix.

;   (thm t :hints (("Goal" :use (:instance (:XXX car-cons (car car))))))

; We made some technical changes in the implementation of iprinting.  For one,
; we no longer compress iprint-ar when exiting a wormhole, since that array is
; already compressed.  More important, we fixed a bug in the interaction
; between hard-bounds and rollovers, as noted in the :doc below.  The following
; caused a hard Lisp error but now works properly.
;
;   (set-evisc-tuple (evisc-tuple 3 3 nil nil) :sites :all :iprint t)
;   (set-iprint t :hard-bound 3)
;   (set-iprint :same :hard-bound 1000)
;   (quote ((a b c d) (a b c d)
;       (a b c d) e))
;   (quote ((a b c d) (a b c d)
;       (a b c d) e))
;   ; Hard Lisp error:
;   (quote ((a b c d) (a b c d)
;       (a b c d) e))

; We changed the order of files in *acl2-files*, so that "hons-raw" comes
; immediately after "hons".  We think we have seen inlining of hons-related
; functions with under-the-hood raw Lisp code in a tentative implementation of
; eviscerate-stobjs-top, while implementing the set-iprint :share keyword.

; Here is the example mentioned in the item below regarding "interaction
; between iprinting and brr".  The #@i# indices are generated sequentially as
; expected now, but were not in Version_7.2.

;   (in-theory (disable nth-0-cons nth-add1))
;   (brr t)
;   (monitor '(:definition nth) ''(:eval :go t))
;   (set-iprint t)
;   (set-gag-mode nil)
;   (set-evisc-tuple (evisc-tuple 3 4 nil nil) :iprint :same :sites :all)
;   (thm (equal (cons (nth 8 (list a b c d e f g h i j))
;                     (hide (nth 8 (list u a b c d e f g h i j))))
;               '((1 2 3 4 5 6 7) (1 2 3 4 5 6 7)
;                 (1 2 3 4 5 6 7) (1 2 3 4 5 6 7)))
;        :hints (("Subgoal 1" :expand ((:free (x) (hide x))))))

; Remove-lambdas no longer puts terms into quote-normal form, although it still
; preserves quote-normal form (i.e., the result is in quote-normal if the input
; is).  Thanks to Eric Smith for suggesting such a change.  Note that
; remove-lambdas is now a guard-verified :logic mode function.

; Fixed error message from (defattach f g) when f is a built-in primitive like
; acl2-numberp.

; The defstub macro now calls a new function defstub-fn to generate the
; macroexpansion.

; Added a blank line before the following message (thanks to a remark from Eric
; Smith that led us to consider this change).

;   [NOTE: A goal of NIL was generated.  See :DOC nil-goal.]

; Fixed a bug in system-verify-guards-fn-1 that was failing to verify guards
; when the original defun specified xargs :verify-guards nil.  Also fixed a bug
; in check-none-ideal that was failing to consider certain event tuples, and
; thus was allowing :ideal mode functions (of the sort mentioned in the
; preceding sentence) to exist at start-up.

; "Infected" warnings now point to a new :doc topic, infected-constraints.

; Here is an example for which attachments weren't used properly for the second
; argument of prog2$.

;   (defstub undef (x) t)
;   (defun foo (x)
;     (declare (xargs :guard t))
;     (cw "#### HI ~x0 ####~%" x))
;   (defattach undef foo)
;   (undef 3)                                  ; prints
;   (defund bar (x)
;     (prog2$ (undef x) (cons x nil)))
;   (bar 3)                                    ; prints
;   ; In the following, the proof failed and didn't invoke the cw call above.
;   ; That has been fixed.
;   (thm (equal (append (bar 3) y)(cons 3 y)))
;   (verify-guards bar)
;   ; The theorem proved successfully and printed (even before the fix).
;   (thm (equal (append (bar 3) y)(cons 3 y)))

; We added experimental support for apply$, not yet advertised.

; Changed the name doubleton-list-p to doublet-listp, as suggested by
; Alessandro Coglio.

; The constant *acl2-defaults-table-macros* lists macro names that can't be
; called in a local context because they set the acl2-defaults-table.  This
; constant is used in chk-embedded-event-form; the big quoted list was formerly
; there, but Eric Smith found it useful to have it installed as a defconst.

; With the change for :s to use linear arithmetic, we now flatten the governors
; when creating the full set of assumptions.  That may not make a difference in
; the type-alist computed, but it can help with derivation of the linear
; pot-lst.

; Here are a couple of examples where the additional use of linear arithmetic
; strengthens the :s command.  Neither of the two theorems at the end were
; proved before that change.

;   (defstub p1 (x) t)
;   (defstub p2 (x) t)
;   (defstub p3 (x) t)
;   (defstub p4 (x) t)
;   (defaxiom p1-type (integerp (p1 x)) :rule-classes :type-prescription)
;   (defaxiom p2-type (integerp (p2 x)) :rule-classes :type-prescription)
;   (defaxiom p3-type (integerp (p3 x)) :rule-classes :type-prescription)
;   (defaxiom p4-prop (implies (< (p1 x) (p3 x)) (p4 x)))
;   (in-theory (disable (tau-system)))
;   (defthm test1
;     (implies (and (< (p1 a) (p2 a)) (< (p2 a) (p3 a)))
;              (p4 a))
;     :rule-classes nil
;     :instructions (:promote (s :backchain-limit 500)))
;   (defthm test2
;     (if (and (< (p1 a) (p2 a)) (< (p2 a) (p3 a)))
;         (p4 a)
;       t)
;     :rule-classes nil
;     :instructions ((:dv 2) (s :backchain-limit 500) :top :s-prop))
;

; Improved proof-builder print-main command to avoid noise in output.

  :parents (release-notes)
  :short "ACL2 Version  7.3 (December, 2016) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes to ACL2 since Version 7.2 into the
 following categories of changes: existing features, new features, heuristic
 and efficiency improvements, bug fixes, changes at the system level, Emacs
 support, and experimental versions.  Each change is described in just one
 category, though of course many changes could be placed in more than one
 category.</p>

 <p>Note that only ACL2 system changes are listed below.  Changes to the @(see
 books) are no longer summarized in a documentation topic, but can be found by
 browsing the <a href='https://github.com/acl2/acl2/'>ACL2+Books GitHub
 repository</a>, in particular, the raw <a
 href='https://github.com/acl2/acl2/commits/master'>commit log</a>.</p>

 <h3>Changes to Existing Features</h3>

 <p>The name of ACL2's interactive goal manager has been changed from
 ``proof-checker'' to ``(interactive) proof-builder''.  Thanks to several
 people in the ACL2 community for feedback leading to this more descriptive
 name.  In particular, we thank Stephen Westfold for noting that as a new user,
 references in the @(see documentation) to ``proof-checker'' didn't help him to
 realize that ACL2 has an interactive proof capability similar to what is found
 in some other interactive theorem provers.</p>

 <p>Now, @(see set-raw-warning-format) causes all warnings to be printed in a
 raw format, not merely those warnings for which custom raw-warning-format code
 has been developed.  Thanks to Shilpi Goel for recommending this
 enhancement.</p>

 <p>Utilities for formatted printing to strings no longer take an @(':')@(tsee
 iprint) keyword argument, and they never print using @(see iprinting).  See
 @(see printing-to-strings).  The reason is that for each iprint index, @('i'),
 that is bound during creation of the result string, that binding would
 disappear after the string is returned; so it would be misleading or an error
 to read @('#@i#') after that return.  For a similar reason, when raw Lisp
 errors occur because variable @('*hard-error-is-error*') is non-@('nil') (see
 @(see hard-error)), iprinting is not used.</p>

 <p>Any @(':')@(tsee measure) supplied in an @(tsee xargs) declaration of a
 @(tsee defun) form must be a legal @(see term).  Formerly, this requirement
 only applied to @(':')@(tsee logic) mode definitions, but now it also applies
 to @(':')@(tsee program) mode definitions.  Thanks to Jared Davis for pointing
 out that this restriction wasn't applied to @(':program') mode
 definitions.</p>

 <p>For a @(tsee defun) form, it is now illegal by default for a non-recursive
 definition to have a @(':')@(tsee measure) in an @(tsee xargs)
 declaration (other than @(':measure nil'), which means ``no measure'') unless
 the definition is within a @(tsee mutual-recursion).  Thanks to Eric Smith
 for suggesting this restriction.  See @(see set-bogus-measure-ok) for a way to
 avoid this new default behavior.</p>

 <p>Several symbols have been added to the list @(tsee *acl2-exports*).</p>

 <p>It is now legal to specify a @(':clause-processor') hint using a symbol,
 regardless of the signature of the relevant clause-processor function.  A
 symbol had only been legal when that function took a single input.  Now, the
 function may also take a hint argument followed by zero or more @('stobj')
 arguments, in which case the hint is implicitly @('nil') and the stobjs are
 passed appropriately.  See @(see clause-processor).  Thanks to Eric Smith for
 requesting this enhancement.</p>

 <p>By default, the checksum values in @(see certificate) files for @(see
 books) have been replaced by a faster (though somewhat less secure) mechanism.
 See @(see book-hash) for an explanation, including a way to restore the use of
 checksums.  (Our experiments in certifying all community @(see books) showed
 about a 7% reduction in total time.  Speed-up for @(tsee include-book) may be
 somewhat greater; for example, on a modern Macbook Pro the form</p>

 @({
 (time$ (include-book \"centaur/vl/mlib/datatype-tools\" :dir :system))
 })

 <p>took 21.67 seconds after certifying books in a default manner, but only
 15.80 seconds after certifying books using @('ACL2_BOOK_HASH_ALISTP=t')
 &mdash; a 27% reduction.)  Thanks to Bob Boyer for emphasizing slowdown from
 checksum computation, to Jared Davis and Eric Smith for several helpful
 emails, and to the ACL2 community in general for continuing to push for faster
 evaluation of @(tsee include-book) calls.</p>

 <p>The utility @(tsee show-accumulated-persistence) now prints results in base
 10 with radix @('nil') (see @(see set-print-base) and @(see set-print-radix)).
 Thanks to Sol Swords for pointing out the odd printing that formerly could
 result when evaluating @('(set-print-base-radix 16 state)') before calling
 @('show-accumulated-persistence').</p>

 <p>We have changed how ACL2 automatically computes @(see type-prescription)
 rules for @(tsee defun) forms &mdash; so-called ``runic type-prescriptions''
 &mdash; in the following cases:</p>

 <ul>

 <li>(1) when including a certified book; and</li>

 <li>(2) in the second pass for a call of @(tsee encapsulate) or @(tsee
 certify-book).</li>

 </ul>

 <p>For (1), ACL2 retrieves runic type-prescriptions from the book's @(see
 certificate).  For (2), ACL2 combines the runic type-prescription rule that is
 computed as usual with the rule previously computed in the first pass.
 Because of (1), the runic type-prescription rule for a function symbol
 introduced by an included book is no longer sensitive to the current logical
 @(see world); previously, for example, that rule could be different if one
 first includes other books.  Also, some @(tsee include-book) calls may
 complete more quickly because of (1); for example, we saw a reduction in time
 of 4.7% for @('(include-book \"doc/top\" :dir :system)').  Because of (2),
 runic type-prescriptions may be stronger than was previously the case.  Thanks
 to Jared Davis for suggesting this enhancement and for helpful discussions
 during its development.  This change can be viewed as just one of the hundreds
 of heuristic components of ACL2 that need not be understood in any detail by
 users; that said, those who are curious about implementation details are
 welcome to read the comment entitled ``Essay on Cert-data'' in the ACL2 source
 code.</p>

 <p>The utility @(tsee save-exec) now causes an error if the directory of its
 first argument does not exist; for example, @('(save-exec
 \"subdir/my-acl2\")') causes an error if there is no subdirectory
 @('\"subdir\"') of the current directory.  Thanks to Jared Davis for pointing
 out that some Lisps (in particular, CCL) would create a missing directory in
 such a case, while others (in particular, SBCL) would not.</p>

 <p>Slightly improved the printing of terms (the so-called ``@(see
 untranslate)'' utility) to avoid producing terms of the form @('(not (not
 u))') in some cases.  Thanks to Eric Smith for feedback leading to this
 change.</p>

 <p>The function being defined (or functions, plural, if using @(tsee
 mutual-recursion)) may now be among the declared @(see ruler-extenders).
 Thanks to Alessandro Coglio for an email that led us to make this change.</p>

 <p>The utility @(':')@(tsee pso), along with other proof-replay utilities
 including @(tsee psof) and @(tsee psog), now works with @(tsee defthmd) and
 @(tsee defund).  More generally, saved proofs are only wiped out by newer
 proofs, not by other @(see events) such as @(tsee in-theory) events.</p>

 <p>The @(':exec') code in calls of @(tsee mbe) no longer affects termination
 proofs or induction schemes produced for function definitions.  This had
 formerly only been the case for certain ``top-level'' calls in the
 if-then-else structure of the definition's body.</p>

 <p>The macro @('logicalp') is now deprecated, replaced by the function symbol
 @('logicp').  (For efficiency, @('logicp') is inlined in raw Lisp;
 @('logicalp') is for now simply a macro abbreviating @('logicp').)  Moreover,
 these utilities no longer call the function @('symbol-class').  (See @(see
 system-utilities) for discussion of such utilities.)  The latter change, which
 avoids consideration of the <tt>'theorem</tt> property of a symbol, can be
 helpful in proofs; indeed, this change simplifies reasoning about the new
 function @('logic-fnsp') (see the ``Bug Fixes'' section below).</p>

 <p>Several improvements have been made for utilities that show guard proof
 obligations.</p>

 <ul>

 <li>The low-level system utility @(tsee guard-obligation) no longer returns
 @(tsee state).  Thanks to Alessandro Coglio for requesting this
 enhancement.</li>

 <li>The utilities @(tsee verify-guards-formula) and @(tsee guard-obligation)
 take a new argument, @('rrp') (``return redundant p'').  When this argument
 is ('nil'), which is the default for @('verify-guards-formula'), these
 utilities will avoid returning the symbol @(''redundant') even in the case
 that the given function symbol is already guard-verified.  Thanks to Eric
 Smith for requesting this enhancement.</li>

 <li>Documentation has been improved for utilities that show guard proof
 obligations, in particular with the addition of a new topic, @(see
 guard-formula-utilities), which explains their differences.</li>

 <li>The utilities @(tsee guard-theorem) and @(tsee gthm) now do some
 simplification of the guard theorem by default.  See @(see guard-theorem) and
 @(see gthm).  Thanks to Alessandro Coglio and Eric Smith for useful
 discussions.</li>

 <li>The utility @(tsee gthm) has two improvements: it takes a second optional
 argument, @('guard-debug'); and it returns a single value (an untranslated
 @(see term)), rather than an @(see error-triple) whose value component is that
 untranslated term.  The function @(tsee guard-theorem) has been changed to
 support the new optional argument.</li>

 </ul>

 <p>Some recursive, @(see logic)-mode built-in functions did not have proper
 @(see measure)s stored in the ACL2 logical @(see world): specifically, those
 whose suitability for logic mode is established in the community book
 @('books/system/top.lisp') and the books included under that book.  This has
 been fixed for all such functions except for the two
 (@('merge-sort-term-order') and @('merge-term-order')) whose measures use
 functions defined only in books, not in ACL2.  Thanks to Eric Smith for a
 request leading to this enhancement.  (If you are interested in
 implementation-level information about the mechanism tying books to
 verification of termination and guards for built-in functions, see comments in
 source-code constant @('*system-verify-guards-alist*'), source file
 @('boot-strap-pass-2.lisp').)</p>

 <p>The utilities @(tsee print-gv) and @(tsee set-print-gv-defaults) now accept
 a natural number for the keyword argument, @(':substitute'), so that only
 certain large repeated terms cause the result to use @(tsee flet).  See @(see
 print-gv).  Thanks to Eric Smith for suggesting such a change and helping to
 design it.</p>

 <p>ACL2 formerly caused a raw Lisp error when attempting to define a function
 that was already defined in raw Lisp but not in ACL2.  Now an ordinary ACL2
 error occurs instead.  Thanks to Eric Smith for a question leading to this
 change.</p>

 <p>Functions @('all-ffn-symbs') and @('all-ffn-symbs-lst') are now in @(see
 guard)-verified @(':')@(tsee logic) mode.  Thanks to Eric Smith for a helpful
 relevant conversation.  Several other functions are now in guard-verified
 @(':logic') mode, thanks to discussions with Eric and also Alessandro Coglio,
 including @('formalized-varlistp'), @('latest-body'), @('logical-namep'),
 @('macro-args'), @('stobjs-out'), @('termify-clause-set'),
 @('throw-nonexec-error-p'), and @('throw-nonexec-error-p1').  For a complete
 list, compare the old and new values of constant
 @('*system-verify-guards-alist*') in source file
 @('boot-strap-pass-2.lisp').</p>

 <p>It had been necessary to evaluate @('(set-state-ok t)') in order to call
 @(tsee verify-termination) on a @(':')@(tsee program) mode function that takes
 @(tsee state) as a formal parameter but does not declare @('state') explicitly
 as a @(see stobj).  Thanks to Eric Smith for pointing out this issue.  Here is
 an example that had failed but now succeeds.</p>

 @({
 (set-state-ok t)
 (defun foo (state) (declare (xargs :mode :program)) state)
 (set-state-ok nil)
 (verify-termination foo) ; formerly failed
 })

 <p>To evaluate a form @('(set-iprint t :hard-bound N)'), ACL2 will first
 replace @('t') by @(':reset-enable').  This behavior has been expanded to
 apply to @('(set-iprint nil :hard-bound N)') and @('(set-iprint :same
 :hard-bound N)') as well: the first argument will be converted to @(':reset')
 or @(':reset-enable').  See @(see set-iprint).  This change fixes a bug in the
 interaction between hard-bounds and rollovers.  For an example that formerly
 exhibited this bug, see a comment about ``hard-bounds and rollovers'' in
 @('(defxdoc note-7-3 ...)') in community book
 @('books/system/doc/acl2-doc.lisp').</p>

 <p>The following improvements have been made to @(tsee defun-sk).  See @(see
 defun-sk) for detailed documentation.</p>

 <ul>

 <li>@('Defun-sk') now modifies the @(see pe-table), with the effect that if
 you introduce a function @('NAME') with @('defun-sk'), then subsequent
 evaluation of @(':pe NAME') will show the @('defun-sk') form rather than the
 underlying @('defun') form.  As usual, you can invoke @(':')@(tsee pe!)
 instead, in order to see that @('defun') form.</li>

 <li>When @('defun-sk') was supplied with keyword argument @(':strengthen t'),
 the name of the generated theorem was always in the @('\"ACL2\"') package.
 Now it is in the same package as the function symbol being defined.  Thanks to
 Alessandro Coglio for suggesting this change.</li>

 <li>@('Defun-sk') now accepts @(tsee declare) forms immediately after the
 formal parameters, as is the case for @(tsee defun).  Thanks to Eric Smith for
 suggesting this enhancement.  The @(':witness-dcls') keyword is still
 supported as well, but may become deprecated in the future.</li>

 <li>An issue involving @(see guard) verification for @('defun-sk') forms has
 been addressed.  Thanks to Alessandro Coglio for suggesting this
 improvement.</li>

 <li>Syntax checking now produces improved error messages for
 @('defun-sk').</li>

 </ul>

 <p>The error message for a call of a undefined symbol now mentions defined
 symbols in other packages with the same name, in case that is what the user
 intended.  The message also points to a new documentation topic, @(see
 near-misses), which provides a way (using certain books) to find approximate
 matches that are defined.  Thanks to Jared Davis for suggesting such a
 change.</p>

 <p>ACL2 now accepts @('#\\Return') as legal notation for the character with
 @(tsee char-code) 13, and it prints that character as @('#\\Return') rather
 than moving the cursor (e.g., to the beginning of the line).  Thanks to
 Alessandro Coglio, Eric McCarthy, and Eric Smith for requesting this change,
 to help with the printing of failed subgoals that mention this character.</p>

 <p>The macro @(tsee good-bye) no longer requires its argument to be a
 (natural) number.  Any argument is now valid, and as before, is evaluated; if
 that argument is not an integer, it is treated as 0.  The same change applies
 to the aliases for @(tsee good-bye), namely @(tsee exit) and @(tsee quit).
 Thanks to Eric Smith for suggesting this change.</p>

 <p>When some subgoal in a set of key checkpoints is @('NIL'), then such a
 subgoal will be printed first in the corresponding list, provided of course
 that the list isn't entirely ignored because of a checkpoint-summary-limit of
 0.  See @(see nil-goal), which has been updated.  Thanks to Eric Smith for
 suggesting that @('NIL') subgoals should be seen in the checkpoints in spite
 of the <see topic='@(url
 set-checkpoint-summary-limit)'>checkpoint-summary-limit</see>.</p>

 <p>A new keyword argument, @(':ctx'), is available for @('value-triple').  See
 @(see value-triple).</p>

 <p>@(csee Definition) rules with non-@('nil') values of
 @(':install-body') (the default) are now permitted to have equivalence
 relations other than @(tsee equal).</p>

 <p>For macros such as @(tsee prog2$) that invoke @(tsee return-last), an
 argument to be evaluated with attachments (see @(see defattach)) was failing
 to use attachments in some cases involving non-guard-verified functions.  This
 has been fixed.  For an example, see the relevant comment in the form
 @('(defxdoc note-7-3 ...)') in community book
 @('books/system/doc/acl2-doc.lisp').</p>

 <p>The @(':')@(tsee termination-theorem) @(see lemma-instance) has been
 improved so that old function symbols may be replaced with corresponding new
 function symbols, either automatically or explicitly by the user.  See @(see
 lemma-instance) and see @(see termination-theorem-example).  Thanks for
 Alessandro Coglio and Eric Smith for helpful discussions, including pointing
 out the previous deficiency.</p>

 <p>A new key, @(':user'), is now legal for the @(tsee acl2-defaults-table).
 Its value must be an association list.  The key is reserved for users, who may
 assume that the ACL2 system does not give it any special handling; see @(see
 acl2-defaults-table).  Thanks to Eric Smith for a helpful discussion leading
 to this change.</p>

 <p>A new macro, @('(with-guard-checking-event x form)'), is now legal for
 event contexts; see @(see embedded-event-form).  Thanks to Eric Smith for
 helpful discussions leading to this change.</p>

 <p>For many years, it has been the case that when a @(see constraint) is
 proved that arises from a @(':functional-instance') lemma instance (see
 [lemma-instance]), that information is stored so that the same constraint is
 not re-proved on behalf of a later such lemma instance.  However, this had not
 been the case when the original lemma instance was inside an @(tsee
 encapsulate) event.  Now, that information is stored provided the
 @('encapsulate') event has an empty @(see signature) list and is not ``empty''
 (that is, stores at least one event).  Thanks to Eric Smith for sending us an
 example to point out this problem.</p>

 <p>The @(see proof-builder)'s @('bash') and @('reduce') commands no longer
 fail when the @(':hints') for @('\"Goal\"') include @(':do-not-induct t').
 Thus, it is no longer necessary to edit out such @(':do-not-induct') @(see
 hints) when editing a proof-builder command by copying hints from an event
 being developed.</p>

 <p>By default, the @(see proof-builder) command @(':s') now uses contextual
 information when doing linear arithmetic.  The new keyword argument
 @(':linear') can be set to @('nil') to get the previous behavior.  See @(see
 acl2-pc::s).  Thanks to Eric Smith for requests that led us to make this
 change.</p>

 <p>Warning and error messages produced upon @(tsee theory-invariant)
 violations now include additional explanation.  Thanks to David Hardin and
 Grant Passmore for helpful remarks leading us to make this change.  Those
 messages also now show where the theory invariant was defined: a book
 pathname, or ``top-level'' if directly in the loop.</p>

 <p>The summary of ``Key checkpoint'' goals, at the end of a failed proof
 attempt, has been improved.  It now indicates, inside the ``***'' banners,
 every case in which proof has been aborted due to a @(':DO-NOT-INDUCT') hint
 or generation of a goal of @('NIL').</p>

 <p>The @(see proof-builder) command, @('noise'), no longer prints @(see
 proof-tree) information, which can be obtained with the new command,
 @('noise!').  The @('quiet') command is unchanged, but a @('quiet!') command
 turns off the printing of goal identifiers (as with @(tsee
 set-print-clause-ids)).</p>

 <p>When @(tsee defund) and @(tsee defthmd) @(see events) fail, their output no
 longer concludes with distracting output that mentions @(tsee
 with-output).</p>

 <h3>New Features</h3>

 <p>New optional arguments allow the @(tsee pso) utility to restrict output to
 a single goal or a segment of the output (say, between two specified goals);
 similarly for related utilities @(tsee pso!), @(tsee psof), and @(tsee psog).
 Thanks to David Rager for a recent query leading to this enhancement.</p>

 <p>The function @(tsee cons-with-hint) provides an alternative to @(see cons)
 that can sometimes avoid consing.  Thanks to Jared Davis and Sol Swords for
 suggesting this function and providing an implementation and
 documentation.  A few ACL2 source functions now call @('cons-with-hint').</p>

 <p>Function @(tsee file-length$) computes efficiently the number of bytes in a
 specified file.</p>

 <p>Function @(tsee delete-file$) deletes a given file.  Thanks to Eric Smith
 for requesting this utility.</p>

 <p>New macros @(tsee active-or-non-runep) and @(tsee incompatible!) are
 similar to @(tsee active-runep) and @(tsee incompatible) (respectively),
 except that the new macros essentially consider non-@(see rune)s to be
 enabled.  Thanks to Eric Smith for feedback leading to these additions.</p>

 <p>It is now possible to @(tsee declare) formal parameters of @(tsee defun)
 events to be irrelevant.  See @(see irrelevant-formals).  Thanks to Eric Smith
 for requesting this feature.</p>

 <p>The @(tsee deftheory) event now accepts a new keyword, @(':redundant-okp'),
 to allow a limited form of redundancy (see @(see redundant-events)).  Thanks
 to Eric Smith for requesting such support.  A new macro, @(tsee defthy),
 abbreviates @('deftheory') calls by adding @(':redundant-okp t').</p>

 <p>The @(tsee fmt) family of functions has a new tilde directive, @('~S'),
 which behaves like @('~s') except that margins are ignored.  Thanks to Jared
 Davis for requesting this feature.</p>

 <p>The iprinting utility has a new keyword option, @(':share'), which causes
 iprint indices to be re-used (using so-called ``iprint sharing'' and ``iprint
 eager sharing'').  See @(see set-iprint).  Thanks to David Rager for
 suggesting a notion of iprint sharing.</p>

 <p>A new function, @(tsee set-serialize-character-system), can be used to turn
 off (or on) the @(see serialize-write) capability, which is on by default, for
 writing certain files during book certification, including @(see certificate)
 files.  This capability has been useful for working around issues with 32-bit
 CCL; thanks to Waqar Ahmed for working through that issue with us.</p>

 <p>ACL2 now supports the reading of rational numbers expressed in
 floating-point (scientific notation) syntax, using prefixes @('\"#f\"') and
 @('\"#fx\"') for base 10 and base 16, respectively.  See @(see
 sharp-f-reader).  Thanks to Dmitry Nadezhin for suggesting this
 enhancement.</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>The raw-Lisp definition of @(tsee defpkg) has been modified in a way that
 may improve performance for some host Lisps.  Thanks to Bob Boyer for emails
 pointing to the (surprising) use of compilation by @(tsee include-book) in
 CCL, which is eliminated (at least in some cases) by this change.</p>

 <p>@(csee Type-set) reasoning has been improved in several basic ways.</p>

 <ul>

 <li>The first, for which we thank Jared Davis and Sol Swords for providing an
 example, is illustrated in a comment in the form @('(defxdoc note-7-3 ...)')
 in Community Books file @('system/doc/acl2-doc.lisp'))</li>

 <li>When @(see definition) bodies and @(see guard)s are simplified, as they are
 by default &mdash; see the new documentation for @(see normalize) &mdash;
 @(see type-set) reasoning is now subjected to a @(see backchain-limit) of 1
 (unless it is already 0 globally).  Thanks to Jared Davis for sending an
 example, for which @(tsee include-book) time has been cut to less than 10% of
 what it had been, without changing the results of @(see normalization).  (That
 said, regression timings suggest that this change will not be noticed for most
 books.)</li>

 <li>The collection of primitive @(see type-set)s supported by ACL2 has been
 changed, by splitting the type of positive integers into two sets: the set
 consisting solely of the number 1, and the set of integers greater than 1.
 Thanks to Jared Davis for suggesting this change, and to him and Sol Swords
 for pointing out deficiencies in our initial implementation.  For a discussion
 of changes made to community books to accommodate this change, see the comment
 immediately above the form @('(defxdoc note-7-3 ...)') in community book
 @('books/system/doc/acl2-doc.lisp').  Note that ACL2 has a newly-added
 function, @(tsee bitp), whose built-in @(see compound-recognizer) rule
 specifies that the value recognized by @('bitp') is either @('0') or @('1'),
 that is, a member of the union of the primitive types @('{0}') and @('{1}').

 @(def bitp-compound-recognizer)

 ACL2 can reason a bit more powerfully about existing functions in some cases.
 For example, it now proves the following theorem without including any books,
 which was not the case previously.

 @({
 (thm (implies (and (rationalp x) (not (integerp x)))
               (< 1 (denominator x))))
 })

 You may need to change some of your books, however.  For example, if you
 want to @(see disable) a function that always returns 1, then as was
 previously the case for such functions that always return 0 instead (or t, or
 nil), you'll want to disable the @(see type-prescription) rule for that
 function, too.</li>

 <li>When a term of the form @('(integerp (+ k term))') is assumed true or
 false, for an integer constant @('k'), ACL2 now essentially attempts to add
 suitable type information for @('term') rather than for @('(+ k term)').
 (Source function @('strengthen-recog-call') shows precisely what is done.)  We
 also made analogous improvements for terms of the form @('(rationalp (+ k
 term))') and @('(rationalp (* k term))').  Example theorem now provable that
 was not provable previously:

 @({
 (thm (implies (and (zp k) ; either k <= 0 or k is not an integer
                    (integerp (+ 1 k))
                    (< 0 (+ 1 k))
                    (acl2-numberp k))
               (equal 2 (+ 2 (* 2 k)))))
 })</li>

 </ul>

 <p>We eliminated a rather technical check during book certification.
 (A bit of technical detail: we check for hidden packages in @(tsee make-event)
 expansions, and an optimization eliminated that check for events in the book
 occurring before the first such event that introduced a new package, if any.
 But if no events in the book introduced a new package, then we were checking
 all such expansions; now, we check none of them.)</p>

 <p>Calls of the utility @(tsee clear-memoize-table) formerly discarded
 relevant hash tables, building new ones when necessary.  Now, the hash tables
 are typically retained but cleared (using Common Lisp function @('clrhash')),
 although heuristics may determine that tables are ``too large'', in which case
 the former discarding behavior applies.  Thanks to Jared Davis and Sol Swords
 for contributing this change, which they found to speed up certain
 computations significantly.  We expect that it will likely not slow others
 down significantly.  Note that (as they have pointed out) the behavior of
 related utility @(tsee clear-memoize-tables) remains unchanged; it continues
 to discard relevant hash tables.</p>

 <p>The generation of raw Lisp definitions of @(see stobj) creator functions
 have been made potentially more efficient for stobjs with many fields.  Thanks
 to Sol Swords and Jared Davis for reporting this issue and suggesting a fix,
 we we adopted (in source function @('defstobj-raw-init')) with some small
 changes.</p>

 <p>We now avoid certain inefficiencies with @(tsee mbe).  The definition of
 @('f8') below has taken 83.63 seconds in Version 7.2 built on CCL as the host
 Lisp, but with that same machine and host Lisp the time was merely 0.11 second
 after this change.  (Technical note: the explosion was in the time required to
 compile the so-called ``*1* function''.)</p>

 @({
 (defmacro id (x) `(mbe :logic (identity ,x) :exec (identity ,x)))
 (defun f8 (x) (id (id (id (id (id (id (id (id x)))))))))
 })

 <p>The heuristics for the ``eliminate-irrelevance'' clause processor (see
 @(see hints)) no longer drop applications of zero-ary functions or their
 negations, e.g., @('(P)') or @('(NOT P)').  Thanks to Marijn Heule for
 feedback that led us towards modifying our initial change (twice!).</p>

 <p>Several low-level efficiency improvements, which can speed up @(see
 read-object), may also speed up some other operations.</p>

 <ul>

 <li>Finding a package from a string can be faster (low-level raw Lisp function
 @('find-package-fast')).</li>

 <li>The implementation of low-level raw Lisp function @('bad-lisp-objectp')
 was tweaked to use type recognizers, which are faster in some Lisps than
 corresponding recognizer predicates; for example, the test @('(consp x)') has
 been replaced by the test @('(typep x 'cons)').</li>

 <li>New raw Lisp function @('bad-lisp-consp') processes conses on behalf of
 @('bad-lisp-objectp'), and now @('bad-lisp-consp') is memoized at startup
 instead of @('bad-lisp-objectp').  Note that we continue to use memoization
 option @(':forget t'), which throws away memoization information when exiting
 the top-level call of the function.  With this change, we avoid the overhead
 of memoization when checking non-cons values, which was perhaps of limited
 value anyhow.  There could be slowdown when large EQ strings occur repeatedly
 inside a cons pair, but we expect such slowdown to be at most negligible in
 practice.</li>

 <li>New utility @(tsee set-bad-lisp-consp-memoize) can turn off memoization of
 the new raw Lisp function @('bad-lisp-consp').</li>

 </ul>

 <h3>Bug Fixes</h3>

 <p>A soundness bug exploited the possibility that pathnames contain illegal
 ACL2 characters.  Consider the following bash shell commands, which create a
 file whose name is the euro sign and create a soft link, @('\"foo\"'), to that
 file.  Thanks to Eric McCarthy for helpful discussions showing us how to
 create such a file, which ultimately led us to discover this bug.</p>

 @({
 mkdir $'\\xe2\\x82\\xac'
 ln -s $'\\xe2\\x82\\xac' foo
 })

 <p>Then the following book certified on a Mac, but now one gets an error
 message complaining about a character with code 8364.</p>

 @({
 (in-package \"ACL2\")
 (make-event
  `(defconst *c* ,(char (canonical-pathname \"foo\" t state) 44)))
 (defthm bad
   nil
   :rule-classes nil
   :hints ((\"Goal\"
            :in-theory (theory 'minimal-theory)
            :use ((:instance char-code-linear (x *c*))))))
 })

 <p>The utility @(tsee getenv$) now causes an error if the value it would
 otherwise return is not an ACL2 string, for example because it contains a
 character whose @(tsee char-code) exceeds 255.  Many other changes, less
 visible to the user, have been made in how ACL2 deals with strings that come
 from outside ACL2, in particular, file names (see the related item just
 above).</p>

 <p>The handling of @(see meta)functions allowed an invariant to be violated,
 that conjectures in the prover are always 100% @(see logic) mode.  An example
 is in a comment in the ACL2 source code under @('(deflabel note-7-3 ...)').
 We have not exploited this bug to show that it leads to unsoundness, but that
 seems possible.  Our fix is to extend the checks that all applications of
 metafunctions and @(see clause-processor)s produce @(see term)s, to check
 additionally that those terms are all in logic mode.  An analogous change
 applies to @(see well-formedness-guarantee)s, using new functions @(tsee
 logic-termp), @(tsee logic-term-listp), and @(tsee logic-term-list-listp),
 where @('logic-termp') checks not only @(tsee termp) but also the new
 predicate @('logic-fnsp'), and similarly for the others (@('logic-term-listp')
 calls @('logic-fns-listp') and @('logic-term-list-listp') calls
 @('logic-fns-list-listp')).</p>

 <p>A bug has been fixed that could cause hard Lisp error when using the @(see
 iprint) utility.  Specifically, calling @(tsee set-iprint) with a small
 @(':hard-bound') could cause a hard Lisp error during ``rollover'', as with
 the following example.</p>

 @({
 (set-iprint :reset-enable :hard-bound 200)
 (set-iprint t :hard-bound 1000)
 (f-get-global 'iprint-ar state)
 (set-evisc-tuple (evisc-tuple 3 4 nil nil) :iprint t :sites :all)
 (thm (equal (append (append x y) x y x y x y x y)
             (append x y x y x y x y x y)))
 (pso)
 (pso)
 (pso)
 })

 <p>Thanks to David Rager for bringing this bug to our attention and for
 describing how it occurred in his environment.  The fix is to convert the
 argument @('t') of @(tsee set-iprint) to @(':reset-enable') when keyword
 argument @(':hard-bound') is supplied.</p>

 <p>The keyword @(':computed-hints-replacement') appeared in the source code a
 few times where @(':computed-hint-replacement') was intended.  This has been
 fixed.  We are not aware of any examples in practice where this makes a
 noticeable difference; in particular, no @(see community-books) were modified
 to accommodate this fix.</p>

 <p>Redefinition can support certain uses of @(tsee make-event) within @(tsee
 encapsulate) forms, where formerly an error occurred.  (Technical note: Small
 examples appear as comments in source function @('chk-embedded-event-form');
 search there for ``redefinition''.)  Thanks to Jared Davis for sending us an
 example that exhibited this problem.  Strictly speaking, we don't really view
 this as a bug; we have clarified in the documentation for @(see
 ld-redefinition-action) that redefinition may behave in unexpected ways.</p>

 <p>We now avoid creating directories when reading rather than writing:</p>

 <ul>

 <li>It is no longer the case that @(tsee include-book) creates a directory
 when attempting to include a book in a non-existent directory.  Thanks to
 Jared Davis for bringing this bug to our attention.</li>

 <li>In Version  7.2, we arranged that @('open-output-channel') and
 @('open-output-channel!') attempt to create directories as needed.
 Unfortunately, that change also caused this behavior for
 @('open-input-channel').  That has been fixed.  Thanks to Sol Swords for
 pointing out that certifying books in CCL using @('cert.pl') could cause
 creation of directories when including books; with this fix, that is no longer
 the case.</li>

 </ul>

 <p>When submitting a call of @(tsee define-trusted-clause-processor) with an
 unsuitable signature, the resulting error message was causing a raw Lisp
 error.  This has been fixed.  Thanks to Eric Smith for reporting this bug.</p>

 <p>Contrary to its documentation, a @(tsee define-trusted-clause-processor)
 event was never redundant in the case that the values for keyword arguments
 @(':label') and @(':partial-theory') were both @('nil') (or omitted).  Thanks
 to Eric Smith for pointing out this bug.  Now, redundancy of the resulting
 @(tsee encapsulate) event succeeds because a subsidiary @(tsee deflabel) event
 is generated by default.  (The previous behavior can be obtained by explicitly
 supplying the keyword argument @(':label nil').)  Also, the obsolete keyword
 argument, @(':doc'), has been deleted for
 @('define-trusted-clause-processor').</p>

 <p>It had been possible to get a @(see slow-array-warning) from computed hints
 (see @(see computed-hints)) that directly modify so-called enabled structures.
 This has been fixed by providing a suitable way for users to call system
 function @('load-hint-settings-into-rcnst'), as is done in the @(see
 community-books) utility @(see easy-simplify-term), which calls a function
 @('easy-simplify-term1-fn') that updates an enabled structure.  Thanks to
 Jared Davis for sending an example that exhibited this problem through the
 computed hint @(tsee logbitp-reasoning).  Also thanks to Sol Swords for a
 helpful discussion that brought our attention to the community book mentioned
 above.</p>

 <p>Avoided an assertion @('(ASSERT$ ACTUAL-ELEMENT ...)') that could occur
 when including uncertified books, in particular when an included sub-book was
 originally certified in a different directory from where it now resides.
 Thanks to Eric Smith for reporting this bug and sending a helpful example.</p>

 <p>Fixed function @('get-skipped-proofs-p') so that it returns @('nil') on
 built-in functions.  Thanks to Eric Smith for bringing up this issue, for
 example by pointing out that @('(get-skipped-proofs-p 'len (w state))')
 evaluated to @('t'); now, it evaluates to @('nil').</p>

 <p>The utility @(tsee unmonitor) was failing to carry out its task when
 applied to a @(see rune).  This was due to a bug in ACL2 source function
 @('delete-assoc-equal-lst'), which has been fixed.</p>

 <p>The utility @(':')@(tsee psof) now prints the @('Rules'), @('Hint-events'),
 and @('Splitter rules') fields to the specified file instead of the terminal.
 It also prints the interactive @(see proof-builder) prompt to that file
 instead of the terminal.</p>

 <p>On rare occasions it seems that after book certification, the compiled file
 was older than the corresponding @('.cert') file, which prevented subsequent
 @(tsee include-book) forms from loading that compiled file.  (Technical note:
 The problem was that we erroneously relied on Lisp function @('rename-file')
 to preserve write-dates.)  This has been fixed.  Thanks to Gary Byers for
 confirming that Lisp does not guarantee that @('rename-file') preserves
 write-dates, and to Camm Maguire for reporting a related failure.</p>

 <p>We fixed the @(':')@(tsee puff) command so that it will no longer fail on
 @(tsee include-book) commands followed by later @('include-book') events.
 Thanks to Eric Smith for reporting the problem via a helpful example.</p>

 <p>Some symbols were printed in a way that could not be read back in, but are
 now printed with surrounding @('|...|').  Thanks to Sol Swords for reporting
 this problem for symbols with the Tab character.  Now that we are more careful
 to print symbols readably in every host Lisp, but in a consistent manner for
 all host Lisps, you may find more symbols printed with surrounding @('|...|')
 than is necessary for your host Lisp.</p>

 <p>It was possible to corrupt the system by evaluating ill-@(see guard)ed
 arguments on @(see program)-mode functions with raw Lisp code when
 guard-checking is off.  For example, after evaluating the forms
 @('(set-guard-checking nil)') and @('(verbose-pstack 23)'), the form @('(thm
 (equal x x))') caused a raw Lisp error.  Now, the ill-guarded call above of
 @(tsee verbose-pstack) causes a guard violation, even with guard-checking
 off.</p>

 <p>In host Lisps that do not compile on-the fly &mdash; that is, in host Lisps
 other than CCL and SBCL &mdash; an error occurred when trying to evaluate
 certain calls of @(tsee comp), including @('(comp t)') during @(tsee
 make-event) expansion.  This has been fixed; here is an example that can be
 evaluated successfully now but not formerly.</p>

 @({
 (make-event (er-progn (comp t)
                       (value '(value-triple nil))))
 })

 <p>ACL2 now avoids some needless escaping of symbol names with vertical bars,
 as in the case of @('car') in base 16, among others supplied by Eric Smith,
 whom we thank for the bug report:</p>

 @({
 ACL2 !>(set-print-base-radix 16 state)
 <state>
 ACL2 !>'car
 |CAR|
 ACL2 !>
 })

 <p>Vertical bars are used for symbols whose names are so-called ``potential
 numbers'', which Common Lisp defines using several criteria.  Consecutive
 letters disqualify a token from being a potential number, and ACL2's mistake
 was in failing to treat characters @('#\\A') through @('#\\F') as letters.</p>

 <p>We fixed a bug in the interaction between iprinting and brr.  For an
 example, see the comment about ``interaction between iprinting and brr'' in
 the form @('(defxdoc note-7-3 ...)') in community book
 @('books/system/doc/acl2-doc.lisp').  Thanks to Shilpi Goel for pointing out a
 somewhat related problem introduced by a change originally made after
 Version_7.2, which also has been fixed.</p>

 <p>The documentation for @(tsee ld) specified that ``If @(tsee standard-co)
 and @(tsee proofs-co) are equal strings, only one channel to that file is
 opened and is used for both.''  This was only the case when @('proofs-co') was
 a canonical absolute (full) pathname.  This has been fixed; now, the criterion
 is that @('standard-co') and @('proofs-co') are strings that represent the
 same file.</p>

 <p>It is no longer illegal for @(tsee defstub) to use an old style output
 signature with variables that are not among the formals.  For example, the
 following is now legal (note that @('u') is not among the list @('(x y)') of
 formal parameters): @('(defstub foo (x y) (mv u x))').  Thanks to Eric Smith
 for pointing out that this behavior is allowed by the documentation
 (specifically, see the discussion of ``Old Style'' in the documentation for
 @(see signature)).</p>

 <p>We fixed a bug in the implementation of @(tsee defattach), which could
 cause the wrong constraints to be generated in the case of more than one
 function argument.</p>

 <p>For a proposed @(see definition) rule with a missing (or empty)
 @(':CLIQUE') but a non-empty @(':CONTROLLER-ALIST'), the error message was
 ill-formed.  This has been fixed.</p>

 <p>Calls of the macro @(tsee add-custom-keyword-hint) are no longer illegal
 @(see events) in the context of @(tsee local).</p>

 <p>Tweaked @(tsee break-on-error) to avoid rare error involving
 @('STATE').</p>

 <h3>Changes at the System Level</h3>

 <p>It was possible for a backtrace to be printed to the terminal by SBCL and
 CMUCL, even when output is redirected to a file.  This has been fixed.
 Moreover, we now print, just above a backtrace (with ACL2 function
 @('print-call-history')), the full pathname of the book under certification,
 in case this problem arises again.  Also, limited the number of frames in
 CMUCL to the default in SBCL, namely, 1000.</p>

 <p>When building the executable with `@('make')', ACL2 now prints a message of
 the form ``@('Successfully built <ACL2_executable_pathname>')'' as the last
 line of the log.  Thanks to Eric Smith for suggesting this change.  Note that
 the exit status continues to be 0 upon success and non-zero upon failure.</p>

 <p>An error now occurs when attempting to build ACL2 or certify the @(see
 community-books) (in the usual way, using @('make')) in a directory whose name
 contains at least one space.  Thanks to Eric Smith for discussion leading to
 this change.  Although the issue may only be with the infrastructure for
 certifying community books, we cause an error for the ACL2 build as well, to
 make installers aware of the problem with spaces as soon as possible; thus, we
 added this check in both the top-level @('GNUmakefile') and in
 @('books/GNUmakefile').  Note that the installation instructions (file
 @('installation/installation.html')) already said to install ACL2 ``in a
 directory whose pathname does not contain whitespace''; now, this requirement
 is enforced.  (If some in the community would like to update the
 infrastructure for certifying books to support spaces in the build directory,
 they are welcome to do so and then remove the check for spaces in
 @('books/GNUmakefile'), at which time we would be happy to remove
 corresponding code in the top-level @('GNUmakefile') as well.)</p>

 <p>The @('rdtsc') feature is now used in function @(see memoization) not only
 for host Lisp CCL but also for SBCL.  Thanks to Bob Boyer for suggesting this
 change and providing helpful code.</p>

 <p>With a trust tag, it is now possible to apply @(tsee verify-termination) to
 functions with under-the-hood raw Lisp code.  See @(see
 verify-termination-on-raw-program-okp).</p>

 <p>An argument has been added to the built-in function, @('recursivep').  The
 old call @('(recursivep fn wrld)') has been replaced by the equivalent new
 call @('(recursivep fn t wrld)') in some community books.  See @(see
 system-utilities) for a discussion of @('recursivep').  Thanks to Alessandro
 Coglio for suggesting this change.</p>

 <p>There is now some documentation on ACL2 system development; see @(see
 system-development) and its subtopics.  These replace the pages under web
 directory @('http://www.cs.utexas.edu/users/moore/acl2/open-architecture/').
 Thanks to Eric Smith for encouraging us to move that documentation to
 XDOC.</p>

 <p>The Common Lisp variable @('*debug-io*') is now used in printing
 backtraces, but also is bound to @('*standard-output*') when entering the ACL2
 read-eval-print loop, which is done at start-up (see @(see lp)).  These
 changes avoid unfortunate printing of backtraces when certifying certain books
 that mess with @('*debug-io*') using <see topic='@(url defttag)'>trust
 tags</see>, such as <see topic='@(url community-books)'>community book</see>.
 @('books/centaur/vl2014/server/server.lisp').  Thanks to Jared Davis for a tip
 that helped us to debug that issue (ACL2 GitHub Issue #634).</p>

 <p>We improved ACL2's implementation of the @('#.') read macro so that it no
 longer prints additional errors after the first.  Also, the error message now
 mentions :DOC @(see sharp-dot-reader), pointing in particular to a relevant
 remark when the failure occurs during book certification.</p>

 <p>(SBCL only) Increased the value of @('--dynamic-space-size') written to the
 executable scripts to 24000, from 16000, in support of building the manual.</p>

 <h3>EMACS Support</h3>

 <p>The text-based display of @(see documentation) has been improved, that is,
 for output from @(':')@(tsee doc) at the terminal and also for the @(tsee
 acl2-doc) Emacs browser.</p>

 <ul>

 <li>Links are inserted much more reliably.  That is, the surrounding of text
 by square brackets for text-based display now virtually always creates links
 that can be followed to topics in the @(see acl2-doc) browser.  In particular,
 that browser now handles names properly that contain the @(':')
 character.</li>

 <li>Text in square brackets, for example [1], is no longer recognized as a
 link (though Emacs still highlights it).  Thanks to Mihir Mehta for pointing
 out this issue.</li>

 <li>Automatic insertion of links for expressions <tt>@@('(name ...)')</tt>, as
 <tt>@@('([name] ...)')</tt>, should not happen for text-based display.  This
 was however done when generating short strings for subtopics in @(see
 acl2-doc); that no longer happens.</li>

 <li>The @('see?') directive (see @(see xdoc::preprocessor)) now inserts links;
 it did not do so before (for text-based display).</li>

 <li>Certain ``raw'' topics, such as DEFXDOC-RAW, are now included that
 formerly were only included in the web-based manual.</li>

 <li>Text within ``@('<stv> ... </stv>')'' is now replaced by the text
 ``@('{STV display}')''.  A general mechanism is in place for extending this
 behavior to other tags (see @('xdoc-tag-elide-alist') in @(see
 community-books) file 'books/xdoc/display.lisp').</li>

 <li>In the @(see acl2-doc) browser, when the ``i'' (@('acl2-doc-index'))
 command is invoked without a prefix argument, the mode line shows the number
 of matches.  (The remaining matches continue to be accessible using the ``,''
 @('(acl2-doc-index-next)') command.)</li>

 </ul>

 <p>Incorporated changes to @('emacs/emacs-acl2.el') put forward by Keshav
 Kini (thanks!), as follows.</p>

 <ul>

 <li>Now, @('meta-x new-shell') avoids buffer names that already exist.</li>

 <li>An error occurs when attempting to switch to a non-existent ACL2 shell
 buffer, rather than creating such a buffer with no process.</li>

 <li>For a new shell, call @('shell') instead of @('make-comint').</li>

 <li>Did a bit of refactoring and improved some error messages.</li>

 </ul>

 <h3>Experimental Versions</h3>

 <p>As before, @(see brr) does not work in ACL2(p) with @(see
 waterfall-parallelism) enabled; see @(see
 unsupported-waterfall-parallelism-features).  But now it is an error to try to
 enable both brr and waterfall-parallelism.  Thanks to David Rager for helpful
 discussions pertaining to this change.</p>

 ")

(defxdoc note-7-4

; Total number of release note items: 22.

; Eliminate extra code for backward compatibility, now obsolete, in functions
; book-hash and cert-hash.

; Improved error messages from exceeding the call depth limit, in response to
; helpful feedback from Eric Smith.

; Here is a brief explanation of the soundness bug in functional instantiation,
; and its fix.  There was a "draconian" restriction until late 2006, which made
; it illegal for free variables in a functional substitution to occur either in
; (a) the functionally-instantiated theorem or (b) the relevant
; functionally-instantiated constraints.  That restriction was eliminated in
; Version 3.0.2 (released December 2006); this was completely appropriate for,
; and motivated by, the desire to avoid the restriction for (a).  However, it
; was unsound to do this for (b): one is really functionally instantiating the
; universal closure of the constraints, so for example if function f is
; replaced by (lambda (u) (g u y)) in a constraint formula, say for example (p
; (f x) y), then logically we are substituting into the constraint (forall (x
; y) (p (f x) y)) to get the formula (forall (x y) (p (g x y) y)), which sadly
; is not a functional instance of the original constraint.  The new
; implementation automatically performs alpha renaming of the constraint to
; avoid such capture: in our example, it functionally instantiates the renamed
; constraint (forall (x y-renamed0) (p (f x) y-renamed0)) to obtain a suitable
; proof obligation of (p (g x y) y-renamed0).  A "[Capture]" warning is printed
; when this happens.

; Disabled executable-counterpart of function print-call-history; so now we
; don't get distracting output, for example from
; (thm (equal (print-call-history) 3)).

; Added a long comment, "Essay on Admitting a Model for Apply$ and the
; Functions that Use It", near the end of ACL2 source file apply-raw.lisp.
; This Essay is a step towards incorporating apply$, which supports a weak form
; of second-order programming and reasoning, into part of ACL2.  As mentioned
; there, [new] community books directory books/projects/apply-model/ contains
; examples that illustrate the Essay.

  :parents (release-notes)
  :short "ACL2 Version  7.4 (March, 2017) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes to ACL2 since Version 7.3 into the
 following categories of changes: existing features, new features, heuristic
 and efficiency improvements, bug fixes, changes at the system level, Emacs
 support, and experimental versions.  Each change is described in just one
 category, though of course many changes could be placed in more than one
 category.</p>

 <p>Note that only ACL2 system changes are listed below.  Changes to the @(see
 books) can be found by browsing the <a
 href='https://github.com/acl2/acl2/'>ACL2+Books GitHub repository</a>, in
 particular, the raw <a
 href='https://github.com/acl2/acl2/commits/master'>commit log</a>.  Also note
 that with each release, some built-in functions that were formerly in
 @(':')@(tsee program) mode are now @(see guard)-verified @(':')@(tsee logic)
 mode functions.</p>

 <h3>Changes to Existing Features</h3>

 <p>The utility @(tsee read-file-into-string) is now a macro, not a function.
 It no longer takes @('state') as an argument (though its expansion reads the
 state), and it has new keyword arguments that allow one to read successive
 segments of the file.  See @(see read-file-into-string).</p>

 <p>The test has been slightly relaxed for determining whether any supporting
 events are missing for @(tsee defabsstobj).  Thanks to Sol Swords for sending
 an example to illustrate the issue, together with analysis of the problem.</p>

 <h3>New Features</h3>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>We now avoid the @(see invariant-risk) slowdown in the case of a
 @(':')@(tsee logic) mode function with guard @('t').  For relevant examples
 see @(see program-wrapper).</p>

 <p>A technical change in the handling of @(see type-set) computations can, in
 rare cases, result in better built-in @(see type-prescription) rules for
 functions.</p>

 <h3>Bug Fixes</h3>

 <p>Fixed a soundness bug, introduced about 10 years ago, that could occur with
 @(':use') or @(':by') @(see lemma-instance)s when a variable occurs free in a
 lambda of a functional substitution.  For an explanation see a comment in
 @('(defxdoc note-7-4 ...)') in community book
 @('books/system/doc/acl2-doc.lisp'); also, a proof of @('nil') (in Version
 7.3) that exploits this bug can be found in a comment in the definition of
 function @('remove-capture-in-constraint-lst') in the ACL2 source code.  This
 may be the first time that a proved ``theorem'' in the @(see community-books)
 has been discovered to be a non-theorem (@('tr-to-array-of-array-to-tr') in
 @('books/projects/legacy-defrstobj/typed-records.lisp')).  Thanks to Sol
 Swords for pointing out that this directory of books isn't used elsewhere; we
 temporarily excluded it from the regression by adding a @('cert_pl_exclude')
 file, until Sol Swords repaired the proof a couple of days later.  Also thanks
 to Ruben Gamboa for fixing proofs in the @('nonstd/') books that failed after
 the bug fix.</p>

 <p>Fixed a bug in @(see proof-builder) commands @('x') and @('expand'), which
 usually gave a misleading error message when attempting to expand a
 constrained function.</p>

 <p>Fixed bugs in the tracking and disabling of @(see compound-recognizer)
 rules.  Thanks to Dmitry Nadezhin for pointing out this bug, indeed, sending
 an example and analyzing it to point to system function
 @('term-and-typ-to-lookup'), which was indeed the one that had the bug.</p>

 <p>Avoided a rare error in @(tsee hons-wash) that has happened when there is a
 second garbage collection after @('hons-wash') has commenced.  Thanks to
 Keshav Kini for telling us about the problem and providing a patch, which we
 used almost verbatim.</p>

 <h3>Changes at the System Level</h3>

 <p>An ACL2 customization file is no longer loaded by default (when it exists)
 when invoking `@('make')' from the top-level ACL2 directory.  This change is
 not necessary for `@('make regression')' because the build system for the
 books already takes care of it.  However we need this change for `@('make
 DOC')', at the least; thanks to Eric Smith for bringing our attention to a
 failure of `@('make DOC')'.</p>

 <p>(Really a books change, but affects building the manual:) By default, it is
 now an error if when saving the ACL2+books or ACL2-only manuals (web-based or
 text-based), a syntax error (marked by ``xdoc error'') is encountered.  See
 @(tsee xdoc::save) and @(tsee xdoc::save-rendered): both now have an error
 argument with default @('nil') so that by default, those new errors are not
 signaled; but in accordance with the change above, that new error argument is
 @('t') for the standard ways of building the ACL2+books and ACL2-only manuals.
 Also, two arguments have been eliminated for @('xdoc::save-rendered').</p>

 <p>An invocation of `@('make update')' to build an ACL2 executable initiates a
 build only when necessary (that is, when at least one source file or
 supporting file, like @('GNUmakefile'), has changed).  Thanks to Eric Smith
 for the suggestion.  Removed the following `@('make')' targets, which were
 suspect after this change (the first definitely no longer worked) and are
 unnecessary: @('saved_acl2'), @('saved_acl2p'), @('saved_acl2r'), and
 @('saved_acl2pr').  WARNING: @('make update') should be used with care, since
 it does not rebuild the desired executable when it already exists and is more
 recent than the sources.  For example, if you change Lisp implementations
 without changing the @('PREFIX') variable &mdash; perhaps even only changing
 the version of your Lisp &mdash; then use @('make') or @('make large'), not
 @('make update').</p>

 <p>New `@('make')' target @('clean-all') removes all generated files in the
 main ACL2 directory and its @('doc/') subdirectory, while existing target
 @('clean'), which has been renamed @('clean-lite'), cleans all of those except
 files @('*saved_acl2*') (and @('doc.lisp.backup')), essentially as before.
 Thanks to Eric Smith for suggestions leading to this change, and to Keshav
 Kini for suggesting consideration of target @('distclean') as an alias for
 @('clean-all'), which it now is.  The target @('clean') is deprecated but,
 consistent with prior usage, acts as @('clean-lite') for now.</p>

 <p>A successful build using `@('make')' shows only four lines for @(''fgrep -i
 compiler make.log')' instead of five.</p>

 <p>(GCL only) Installed a patch from Camm Maguire (GCL maintainer) to fix a
 GCL compiler bug.  Also turned off SGC to avoid an ``mprotect failure'' error
 (community book @('books/centaur/fty/tests/deftagsum-scale.lisp')).</p>

 <p>Fixed a bug that was causing an assertion failure, instead of a clean
 error, when attempting to apply @(':')@(tsee monitor) to undefined primitives,
 e.g., @(':monitor cons t').  Thanks to Keshav Kini for reporting this bug and
 sending us an initial fix.</p>

 <p>Fixed a bug in the @(see break-rewrite) commands @(':go!') and @(':go$'),
 which was causing an error message to be printed.</p>

 <h3>EMACS Support</h3>

 <p>Made minor @(see acl2-doc) improvements: fixed a bug in `@('u')' command's
 error message when already at the top topic; fixed a bug that was displaying
 the \"Parent list:\" field in reverse order; and eliminated the warning when
 loading a large manual (combined manual is at about 70M bytes now; new
 threshold is 80M bytes).</p>

 <p>Improved @(see acl2-doc) to work with other manuals; see @(see acl2-doc),
 specifically Section ``Selecting a Manual''.  Note that the command for
 initially bringing up the ACL2 User's Manual, instead of the ACL2+Books
 manual, has changed from @('(defvar *acl2-doc-top-default* 'TOP)') to
 @('(defvar *acl2-doc-manual-name* 'acl2-only)').</p>

 <p>Added new @(see acl2-doc) commands, `@('/')' and `@('W')', to go to an ACL2
 definition.  By default the search is through both the ACL2 sources and books.
 The search can be continued even outside acl2-doc by using a numeric prefix
 argument with @('control-t /'), which is just the `@('/')' command made
 available outside acl2-doc.  These two commands differ only in the defaults
 presented in the minibuffer.  The default for `@('/')' is based on the text at
 the cursor.  (This is much like the similar built-in Emacs command,
 @('meta-.'); indeed, `@('/')' is next to `@('.')' on standard keyboards.)  For
 `@('W')', the default is based on the page's topic name (as shown by the
 `@('w')' command).  See @(see acl2-doc) for details.</p>

 <p>Installed a patch for @('control-t control-e') from Keshav Kini, so that
 when there are more than two windows and one has the ACL2 shell buffer
 showing, then that one receives the form.  Consider for example windows A, B,
 and C, where the cursor is showing in A and the shell buffer is showing in C.
 Previously, the shell buffer could be placed in B to receive the form.  Now,
 the form will go into C.</p>

 <p>The @(':evisc-tuple') keyword for @(tsee trace$) was being ignored when
 @(':native t') was also supplied.  Since the use of @(':native t') sends the
 tracing command to raw Lisp, this wasn't really a bug, since no raw Lisp we
 know of supports the @(':evisc-tuple') keyword.  However, we have improved our
 custom modifications of the native @('trace') for host Lisps CCL and Allegro
 CL so that @(':evisc-tuple') is no longer ignored for these Lisps.</p>

 <h3>Experimental Versions</h3>

 <p>A new rewrite rule for ACL2(r), @('realp-implies-acl2-numberp'), is
 analogous to the existing rule @('rationalp-implies-acl2-numberp').  Thanks to
 Dmitry Nadezhin for suggesting the addition of this rule, which he observed is
 necessary for some ACL2(r) proofs.</p>

 ")

(defxdoc note-8-0

; Total number of release note items: 80.

; The following comments include changes not covered in the release notes
; items-- for example, because they are about changes in error messages.

; Improved an error message when stobj-let references a stobj not declared by
; :stobjs, thanks to a bug report and example from Sol Swords.

; Improved guard violation messages for primitives to avoid mentioning safe
; mode when not appropriate.

; Fixed print-idate to avoid being vulnerable to escaping certain symbols,
; specifically, printing |,| and |:| as |,| and |:| rather than as , and : --
; as we have seen in a development version of a Lisp implementation.

; Changed an error message when attempting to call a constrained or
; non-executable function, from "ACL2 cannot ev the call of undefined function"
; to "ACL2 cannot ev the call of non-executable function".  Thanks to Eric
; Smith for pointing out that functions defined with defun-nx are not really
; undefined, so the old wording was misleading.

; Changed an include-book warning for certifying a subbook, so that instead of
; saying "After including the book", it says "After processing the events in
; the book".  Thanks to Eric Smith for pointing out that the old wording could
; be confusing, since the include-book is still actually under way.

; Improved an error message when attempting to provide an elim rule for a
; function symbol that already has an elim rule.  Thanks to Keshav Kini for
; noticing this issue and providing a fix.

; Added guards, as per Sol Swords, to functions obviously-equal-lambda-args,
; obviously-equiv-terms, and obviously-equiv-terms-lst (and also
; obviously-iff-equiv-terms).

; State global variable prompt-memo is now untouchable.  To see why, try
; evaluating (assign prompt-memo 3) in a previous ACL2 version and you'll see a
; raw Lisp error.

; Added source function standard-string-p, which avoids building a list with
; coerce, and modified some guards to use it.

; Tweaked source function match-tests-and-bindings to avoid ill-guarded call.

; Fixed many typos.

; Improved a couple of errors pertaining to "function applications" to instead
; say the more general "function (and macro) applications".  Thanks to Eric
; Smith for suggestion that such a message be tweaked.

; Simplified the definition of formals, following a suggestion of Alessandro
; Coglio.

; While making the changes for theory functions, we added an extra argument to
; each of the functions union-current-theory-fn,
; set-difference-current-theory-fn, and set-difference-theories-fn, and two
; extra arguments for intersection-theories-fn, and also we now support a value
; of 'both for union-theories-fn.  These changes may slightly improve
; efficiency.  We do not advertise these changes in the release notes because
; they are unadvertised ACL2 system functions.  Some of these are nonetheless
; used in the community books, which have been modified accordingly.

; Improved the discussion of :do-not-induct in :doc hints.  Also cleaned up
; some error messages related to :do-not-induct.  Thanks to a query from Eric
; Smith that led to these changes.

; Cleaned up handling of raw-guard-warningp, including: now a state global
; instead of a Lisp special, modified warning message, added :doc
; guard-checking-inhibited, and cleared raw-guard-warningp in a simple way for
; each top level form (in ld-read-eval-print).

; The problem with ev-fncall-w (not a function) was really a problem with
; raw-ev-fncall, which has been fixed.

; Removed let-beta-reduce from *initial-untouchable-fns* (it occurs nowhere
; else in the sources).

; An error message for certain ``program-only'' functions was confusing.  It
; has been shortened considerably, with a pointer to a new :doc topic,
; program-only.

; Fixed the build check, check-none-ideal, to check for ideal functions defined
; under mutual-recursion.  (That check was previously missing.)

; Improved system-verify-guards to handle mutual-recursion with arbitrary
; measures.

; One example sent by Keshav Kini for identifying the problem with type-set
; reasoning for COMPLEX was (thm (implies (zerop (conjugate x)) (zerop x))).
; However, due to changes in the definition of conjugate, that is no longer a
; theorem (consider x = t, for example).

; Regarding books/system/check-system-guards.lisp, mentioned in the release
; note below: that also caught a bug in the guard of source function
; warning-off-p1.

; Made the warning banner for development snapshots less scary.

; (GCL only) Changed si::*code-block-reserve* as per suggestion from Camm
; Maguire.

  :parents (release-notes)
  :short "ACL2 Version  8.0 (December, 2017) Notes"
  :long "<p>NOTE!  New users can ignore these release notes, because the @(see
 documentation) has been updated to reflect all changes that are recorded
 here.</p>

 <p>Below we roughly organize the changes to ACL2 since Version 7.4 into the
 following categories of changes: existing features, new features, heuristic
 and efficiency improvements, bug fixes, changes at the system level, Emacs
 support, and experimental versions.  Each change is described in just one
 category, though of course many changes could be placed in more than one
 category.</p>

 <p>Note that only ACL2 system changes are listed below.  See also @(see
 note-8-0-books) for a summary of changes made to the ACL2 Community Books
 since ACL2 7.4, including the build system.  Also note that with each release,
 some built-in functions that were formerly in @(':')@(tsee program) mode are
 now @('see guard')-verified @(':')@(tsee logic) mode functions.</p>

 <h3>Changes to Existing Features</h3>

 <p>The macro, @(tsee case-match), now treats keywords as constants when they
 occur in patterns.  For example, the following form evaluates to 3 where
 formerly an error occurred:</p>

 @({
 (let ((x '(:foo 3)))
   (case-match x
     ((:foo y) y)
     (& 17)))
 })

 <p>Thanks to Keshav Kini for suggesting this improvement.</p>

 <p>Several changes have been made to @(tsee sys-call) and @(tsee sys-call+),
 and a new utility, @(tsee sys-call*), has been added.  These stem from
 feedback from an observation by Eric Smith: @('sys-call') could invoke the
 operating system when simplifying terms (see @(see sys-call) for an example).
 We thank Eric for helpful discussions.  Changes include:</p>

 <ul>

 <li>When @(tsee sys-call) is invoked during a proof (from a prover call or
 invocation of the @(see proof-builder), it no longer can make a (potentially
 dangerous) call to the operating system.  If such an invocation occurs during
 evaluation of a clause-processor or metafunction, an error will be
 signaled.</li>

 <li>@(tsee Sys-call+) continues to call the OS during proofs, but now it only
 does so when applied to the actual ``live'' ACL2 @(see state).</li>

 <li>A new utility, @(tsee sys-call*), combines some features of @(tsee
 sys-call) and @(tsee sys-call+); it takes @('state') and takes effect even
 during proofs like @('sys-call+'), but like @('sys-call') it does not capture
 output.  Thus, it can be a good choice in place of @('sys-call') for
 clause-processors and metafunctions, now that @('sys-call') would cause an
 error.</li>

 <li>The guards are no longer @('t').  Now, the guard for all three functions
 specifies the application of a string (the command) to a true list of
 strings (the arguments).</li>

 <li>The @(see executable-counterpart) of @(tsee sys-call) is disabled by
 default.</li>

 </ul>

 <p>Several symbols have been added to the list @(tsee *acl2-exports*),
 including @('LET') (thanks to Eric Smith for that suggestion).</p>

 <p>When a single-threaded object is being used where an ordinary object is
 expected, the error message has been improved to show the enclosing form.
 Moreover, such an error message can now appear when congruent stobjs are
 involved, where formerly the error was blamed on the shape of the result.
 Thanks to Sol Swords for bringing the latter problem to our attention with a
 helpful example.  (See a comment in ACL2 source function @('translate11-call')
 for a simplified version of that example.)</p>

 <p>The banner printed when there is a raw Lisp error now points to a new @(see
 documentation) topic, @(see raw-lisp-error).  Thanks to Keshav Kini for most
 recently pointing out that @(tsee fmt) can cause a raw Lisp error.</p>

 <p>When suppressing output of all types other than @('error') &mdash; see
 @(see set-inhibit-output-lst) &mdash; then errors may be reported with
 considerably less noise than before, because of the following changes.  Thanks
 to Eric Smith, Alessandro Coglio, and Stephen Westfold for helpful
 discussions and feedback.</p>

 <ul>

 <li>When all output is inhibited except error output, the generic failure
 message for events is suppressed for @(tsee encapsulate), @(tsee progn),
 @(tsee progn!), and @(tsee make-event).</li>

 <li>When a call of @(tsee make-event) specifies keyword @(':on-behalf-of')
 with value @(':quiet') or @(':quiet!'), an error for @('make-event') expansion
 is generally suppressed; see @(see make-event-details).</li>

 <li>A failed call of @(tsee progn) no longer prints @('\"PROGN failed!\"');
 similarly for @(tsee progn!).</li>

 </ul>

 <p>Some warnings have been made more compact for including uncertified books.
 Thanks to Eric Smith for suggesting such an improvement.</p>

 <p>The (minimal) support for infix printing has been removed.  (See the Essay
 on infix printing in ACL2 source file @('axioms.lisp') for more information.)
 However, as a result it is now possible to call certain functions during
 evaluation of @(tsee defconst) forms, and during macroexpansion &mdash; in
 general, during any evaluation when so-called ``safe mode'' is active and a
 function with raw Lisp code is encountered.  For example, the following form
 was formerly rejected but is now accepted.</p>

 @({(defconst *c* (fms-to-string \"abc~x0\" (list (cons #\0 (expt 2 4)))))})

 <p>Thanks to Eric Smith for suggesting such a change.</p>

 <p>The role of @(see ruler-extenders) for redundancy of @(tsee defun) forms
 has been simplified; see @(see redundant-events).  Thanks to Alessandro Coglio
 for contributing a patch for this change.  Moreover, there was a bug: the
 redundancy check for definitions could allow the new definition to be
 redundant even when it specified more than one value for
 @(':ruler-extenders'), which is illegal.  This has been fixed.  Thanks to
 Alessandro Coglio for bringing this issue to our attention.</p>

 <p>Modified the built-in rule @('complex-0') to one that is simpler but
 equivalent, and modified the definition of @(tsee conjugate) so that it always
 returns a number (essentially by ``fixing'' its argument).  We thank Keshav
 Kini for suggesting such changes, and for helpful discussions we also thank
 Alessandro Coglio and Sol Swords, who suggested the definition of
 @('conjugate') that we ultimately installed.</p>

 <p>The system-level utility, @('trans-eval'), now prints a warning by default
 when its call modifies a user-defined @(tsee stobj).  This feature can be
 defeated but it may be best to allow the warning to be printed.  See @(see
 trans-eval) and, especially, see @(see user-stobjs-modified-warnings).  A
 related change is that in order to call @(tsee ld) in the body of a
 definition, a new keyword argument, @(':ld-user-stobjs-modified-warning'),
 must be supplied.  See @(see ld).  (Note: This issue was raised some time ago
 by Sol Swords.)</p>

 <p>Substantially improved error messages for illegal applications of <see
 topic='@(url theory-functions)'>theory functions</see> @(tsee enable), @(tsee
 disable), @(tsee set-difference-theories), @(tsee union-theories), and @(tsee
 intersection-theories).</p>

 <p>Theory warnings have been enhanced to report enabling or disabling of the
 definition @(see rune) for an undefined @(see primitive) like @(see cons).
 Thanks to Eric Smith for pointing out that ACL2 quietly lets one enable or
 disable undefined primitives to no effect, and also for feedback leading to
 improvements on the initial implementation of this change.  For details, see
 @(see theories-and-primitives), specifically the last section, which pertains
 to primitives.</p>

 <p>Removed the symbol @('let-beta-reduce') from the list
 @('*initial-untouchable-fns*') because @('let-beta-reduce') is not a known
 function symbol.</p>

 <p>The @(':do-not-induct') hint no longer accepts keyword arguments other than
 @(':otf-flg-override') and @(':otf'), which would produce illegal theorem
 names in the report of skipped goals.  Thanks to Eric Smith for a query that
 led us to clean this up.</p>

 <p>Duplicate hypotheses have been eliminated for events generated by @(tsee
 defabsstobj).  Thanks to David Rager for bringing this issue to our attention
 and for helpful conversations.</p>

 <p>It is now legal for the bindings of a @(tsee stobj-let) form to call
 accessors of a stobj, @('st1'), on a stobj @('st2') that is congruent to
 @('st1').  See @(see nested-stobjs).  Thanks to Sol Swords for requesting and
 explaining this feature, implementing it, and providing tests.  To see tests,
 search for ``how congruent stobjs may be used in stobj-let'' in @(see
 community-book) @('books/system/tests/nested-stobj-tests.lisp').</p>

 <p>A low-level error starting with ``HARD ACL2 ERROR in
 FIND-MAPPING-PAIRS-TAIL'' has been eliminated.  This error could formerly
 occur when using redefinition; see comments in ACL2 source function
 @('find-mapping-pairs-tail1') for two simple examples.  We thank Yan Peng for
 bringing this issue to our attention.  Note that although we make some effort
 to support redefinition, we do not guarantee that it always works well; for a
 relevant warning, see @(see ld-redefinition-action).</p>

 <p>Several related changes have been made in ``second-order''
 capabilities.</p>

 <ul>

 <li>The function @(tsee magic-ev-fncall) could invoke functions that should
 not be invoked because they require a trust tag (see @(see defttag)) or they
 are untouchable (see @(see push-untouchable)).  A check is now in place to
 prevent this; see @(see magic-ev-fncall).  For example, evaluation of the form
 @('(magic-ev-fncall 'sys-call '(\"pwd\" nil) state t nil)') no longer prints
 the current directory; instead it results in an error.</li>

 <li>It was possible for system function @('ev-fncall-w') to subvert such a
 check by placing it under a @(see program-wrapper); so @('ev-fncall-w') is now
 untouchable.</li>

 <li>A new function, @('ev-fncall-w!'), always performs the check, and may be
 used in place of @('ev-fncall-w').  But consider instead using the documented
 @(see logic)-mode function @(tsee magic-ev-fncall).</li>

 <li>The first argument of @('magic-ev-fncall') no longer needs to be in @(see
 logic) mode.</li>

 <li>@('Magic-ev-fncall') can execute considerably more quickly than before;
 thanks to Eric Smith for sending an example that helped us to implement this
 improvement.</li>

 <li>Both @('oracle-apply') and @('oracle-funcall') have been eliminated.  Use
 @(tsee magic-ev-fncall) where you would otherwise use one of those.</li>

 </ul>

 <p>Expressions in @(see table) @(see events) may now use not only the
 variable, @('WORLD'), but also the variable, @('ENS').  See @(see table).</p>

 <h3>New Features</h3>

 <p>A new utility, @(tsee apply$), provides a weak version of the Common Lisp
 second-order utility, @('apply').  Using this new primitive the user can
 define functions like @('map'), which can apply certain function symbols and
 lambda expressions.</p>

 <p>Added utility @(tsee checkpoint-summary-limit).  Thanks to Mihir Mehta for
 an email leading to this addition.</p>

 <p>A new utility, @(tsee set-register-invariant-risk), provides a way to avoid
 inclusion of the @(see invariant-risk) check in code generated by ACL2 for
 executable-counterpart functions (see @(see evaluation)).  The effect of
 @('set-register-invariant-risk') is limited to the enclosing book or @(tsee
 encapsulate) event.  Thanks to Eric Smith for a discussion leading to this
 feature.</p>

 <p>The new functions @('read-object-with-case') and
 @('print-object$-preserving-case') is are variants of @('read-object') and
 @('print-object$'), respectively.  The function @('read-object-with-case')
 lets you specify that case is preserved, inverted, or converted to lower case
 or (as with @('read-object')) to upper case.  The function
 @('print-object$-preserving-case) prints symbols without escaping them for
 case; for example, the symbol in the current package with name @('\"abc\"') is
 printed as @('abc'), not as @('|abc|') as would be printed by
 @('print-object$').  See @(see io).</p>

 <p>New macro @('with-output!') is the same as @(tsee with-output) except for
 two differences: @('with-output!') can be called in code, but it does not
 generate an event form.</p>

 <p>Now @('complex-definition') is a disabled rewrite rule (formerly @(see
 rule-classes) @('nil')).  Also added (enabled) rules @('default-pkg-imports'),
 @('default-code-char'), and @('default-intern-in-package-of-symbol').  All of
 these may be found in ACL2 source file @('axioms.lisp').  Thanks to Keshav
 Kini for email that led us to add these rules.</p>

 <p>New function @(tsee get-enforce-redundancy) queries the @(see world) on
 whether redundancy is being enforced.  Thanks to Eric Smith for requesting
 this feature.</p>

 <p>It is now possible to obtain output that is less likely to depend on the
 directory where it was created, by evaluating the form @('(assign script-mode
 t)').  (This capability supports the new tool, @(tsee run-script).)</p>

 <p>We added support for more detailed reports on the progress of
 forward-chaining.  However these reports are only available on an experimental
 basis by redefining the system function @('forward-chain1') as directed by a
 comment at the top of that @('defun').  Users who find this level of reporting
 useful are encouraged to tell us as we could incorporate it into the
 documentation topic, @(see forward-chaining-reports).</p>

 <p>Normally, hard error messages (see @(see er)) are not inhibited.  A new
 @(see state) global, @('INHIBIT-ER-HARD'), inhibits hard error messages when
 @('ERROR') output is inhibited; see @(see set-inhibit-output-lst).</p>

 <h3>Heuristic and Efficiency Improvements</h3>

 <p>The checking done for @(see invariant-risk) has been relaxed, so that it no
 longer causes any slowdown in calls of @(':')@(tsee logic)-mode functions.</p>

 <p>A low-level system function, @('cross-prod') (which is used by @(see
 tau-system)), now uses tail-recursion, which may avoid some stack
 overflows.</p>

 <p>@(csee Forward-chaining) was improved so that if a @(':forward-chaining')
 rule produces a conclusion that is a disjunction, the system watches for later
 @(see type-set) information about the disjuncts.  E.g., if we forward-chain to
 @('(OR p q)') and later in the same forward-chaining process @('q') becomes
 false, then @('p') is made true.  We thank Dave Greve for providing an example
 requiring this.</p>

 <p>An optimization for removing @(see stobj) recognizers, long applied to
 bodies of executable definitions, is now also applied to @(see guard)s.
 Thanks to Sol Swords for suggesting this change and its implementation.</p>

 <p>The function @(tsee resize-list) is now defined using @(tsee mbe) so that
 its execution is tail-recursive.  Thanks to Martin Simmons of LispWorks
 Technical Support for diagnosing a stall in the certification of community
 book @('books/centaur/truth/perm4.lisp') as being due to a stack overflow
 caused by an invocation of @('resize-list').  Based on his advice we no longer
 automatically grow the stack in LispWorks; this will ease debugging when
 compilation is done with safety 3.  The maximum stack size is 399998, at least
 in our 64-bit LispWorks build.</p>

 <h3>Bug Fixes</h3>

 <p>Soundness bugs have been fixed in the handling of @(tsee stobj-let), due to
 aliasing that could take place by binding two different but congruent stobjs
 to the same stobj.  To see examples, search for ``soundness'' in @(see
 community-book) @('books/system/tests/nested-stobj-tests.lisp').  We are very
 grateful to Sol Swords not only for bringing this to our attention, but
 especially for his contributions to a fix through helpful conversations and by
 providing code and examples.</p>

 <p>A bug in the @(see proof-builder)'s command, @('rewrite') (or equivalently,
 @('r'); see @(see acl2-pc::rewrite), avoided creating necessary subgoals,
 which can presumably be unsound.  That bad behavior could occur when the
 third (and optional) argument of that command was a non-@('nil') value other
 than @('t').</p>

 <p>The built-in evaluator functions for ACL2 relied on a system function,
 @('ev-fncall-w'), that was not a function!  We do not see how to exploit this
 oddity to prove @('nil'), since @('ev-fncall-w') is guaranteed never to be in
 @(see logic) mode.  However, it is clearly undesirable.  In the following
 example, the two @('ev-fncall-w') calls gave different answers on the same
 inputs &mdash; @('(mv nil 7)') and @('(mv nil 12)') &mdash; but now the second
 call results in an error.</p>

 @({
 (defun foo (x y) (+ x y))
 (assign old-w (w state))
 (ev-fncall-w 'foo '(3 4) (@ old-w) nil nil nil t nil)
 (u)
 (defun foo (x y) (* x y))
 (ev-fncall-w 'foo '(3 4) (@ old-w) nil nil nil t nil)
 })

 <p>The check for the requisite theorems supporting a @(tsee defabsstobj) event
 included a case where the check was too weak, and it also could cause an
 unexpected assertion.  The first of these could probably cause unsoundness.
 Thanks to Sol Swords for finding these issues and providing fixes.</p>

 <p>A small change in @(tsee defstobj) can lead to improved automation for some
 @(tsee guard) proofs involving @(tsee stobj-let).  Thanks to Sol Swords for
 sending an example, which guided us to add a test (as suggested by Eric
 Smith) in community book @('system/tests/nested-stobj-formals.lisp').</p>

 <p>Formatted printing (with @(tsee fmt), @(tsee cw), etc.) failed to respect
 newlines encountered while processing @('~s') and @('~S') directives.  This
 has been fixed; see @('books/system/tests/fmt-to-string.lisp') for examples
 that behave well now but formerly did not.  Thanks to Eric Smith for pointing
 out this problem and sending, in essence, the following example.</p>

 @({
 (cw \"~s0\"
     (string-append-lst
      (make-list 100
                 :initial-element
                 (coerce '(#\A #\B #\C #\D #\E #\F #\G #\H #\I #\J #\Newline)
                         'string))))
 })

 <p>A bug that was in the @(see tau-system) is illustrated by the following
 example sent by Grant Passmore, in which tau discovers that the function being
 defined always returns @('nil'), hence implies everything.  Tau no longer
 causes an error in this situation.</p>

 @({
 (defun f (x) (> x 0))
 (defun g (x) (< x 0))
 (defun h (x) (and (f x) (g x)))
 })

 <p>Moreover, tau ``knows'' that the function @('h') above is contradictory, as
 evidenced by the successful proof of the @('thm') below.</p>

 @({
 (thm
  (implies (h x) (consp x))
  :hints ((\"Goal\" :in-theory '((:e tau-system)))))
 })

 <p>Fixed a bug in @(':')@(tsee pe!) that could result in an error in @(':pe!
 :here') when the most recent command is an @(tsee encapsulate) event.</p>

 <p>It was possible to be in raw-mode, when including an uncertified book with
 a call of @(tsee progn!) that first sets raw-mode @(tsee set-raw-mode) and
 then causes a raw Lisp error.  This has been fixed.</p>

 <p>It is now possible to invoke @(tsee verify-termination) without an error
 occurring due to the presence of untouchable variables or functions in the
 definition (which hadn't prevented earlier admission in @(see program) mode).
 Thanks To Eric Smith for bringing this issue to our attention.</p>

 <p>ACL2 has supported, and continues to support, @(tsee defun) forms that
 include the ACL2 @(see state) as an argument without declaring @('state')
 explicitly to be a @(see stobj).  This is done by first evaluating
 @('(set-state-ok t)').  But in that case, the guard for such a function
 erroneously failed to include @('(state-p state)'), which can have unfortunate
 consequences; see @('books/system/tests/state-p-in-guard.lisp') in the @(see
 community-books).  This has been fixed.  Thanks to Alessandro Coglio for
 contributing a fix and for helpful conversations.</p>

 <p>Fixed bugs in reporting of errors and warnings by @(tsee defchoose) when
 pertaining to ignored variables.  Thanks to Eric Smith for bringing one of
 these to our attention.</p>

 <p>Fixed a bug in the @(see proof-builder): @(see hints) on the @('prove')
 command were not being passed down to induction.  Thanks to Mihir Mehta for
 bringing this bug to our attention with a reproducible example.</p>

 <p>Fixed a low-level bug (in source functions @('note-relieve-hyp-failure')),
 discovered by using the new community book
 @('books/system/check-system-guards.lisp').  That book, which is useful for
 system development, checks all top-level calls of built-in functions that are
 in @(see logic) mode, @(see guard)-verified.</p>

 <h3>Changes at the System Level</h3>

 <p>When building the combined manual, an error occurs if there is more than
 the single expected broken link.  Thanks to Alessandro Coglio for helpful
 discussions.  <i>Notes.</i> (1) This uses a new keyword argument available in
 @(tsee xdoc::save), @(':broken-links-limit').  (2) There is no such limit for
 saving the text-based manual.</p>

 <p>As usual, several @(see documentation) improvements have been
 made, for example, clarification made in the topic @(see
 local-incompatibility) thanks to Keshav Kini and Yan Peng.  A new
 documentation topic, @(see evaluation), is probably long overdue: it
 explains ACL2 evaluation with a focus on the notions of the
 ``executable-counterpart function'' (sometimes called the ``*1*
 function'') and the ``submitted function'' (sometimes called the
 ``raw-Lisp function'').</p>

 <p>Environment variable @('SBCL_USER_ARGS') allows one to pass runtime-options
 to calls of ACL2 built on SBCL, without having to call @(tsee save-exec).
 Thanks to Sol Swords for requesting this capability.  Example:</p>

 @({
 (export SBCL_USER_ARGS=\"--lose-on-corruption\" ; ./sbcl-saved_acl2)
 })

 <p>There is a new documentation topic, @(see talks), which has a link from the
 ACL2 home page (with Applications, Tours, and Tutorials/Demos).  Additional
 contributions to this topic are welcomed!</p>

 <p>For SBCL, the runtime option @('--disable-ldb') is now supplied by the
 @('saved_acl2') script, which avoids passing control to the
 lowest-level (@('ldb')) debugger (from which recovery is probably impossible).
 Without this option, a parallel run of @('cert.pl') (see @(see
 build::cert.pl)) can stall out when a single failure passes control to the
 @('ldb') debugger.</p>

 <p>Some infinite loops are now avoided in the debugger for SBCL (and perhaps
 some other Lisp implementations).  Thanks to Keshav Kini for sending an
 example and suggesting a fix, which we incorporated, as well as for helpful
 conversations.  Implementation note: the definition of constant
 @('*our-standard-io*') in ACL2 source file @('interface-raw.lisp') explains
 the issue.</p>

 <p>Warnings were being produced by @(tsee include-book) in CCL, and perhaps
 some other Lisps, when including a book that redefines a function as a macro
 or vice-versa.  We have eliminated those raw Lisp warnings.</p>

 <p>It is now checked that the @('books/') directory exists before attempting
 any operations using @(''make'') on that directory.  Thanks to Keshav Kini for
 suggesting this check, since there are source-only distributions, without the
 books.</p>

 <p>(SBCL only) The setting of environment variable @('SBCL_HOME') has been
 tweaked to be more robust.  In particular, we expect it to be unnecessary, and
 even inadvisable, to set @('SBCL_HOME') manually.  Thanks to Keshav Kini for
 contributing this change.</p>

 <p>(CMUCL only) ACL2 Version  8.0 cannot be reliably run on CMUCL, so we have
 disabled building ACL2 on CMUCL.  The CMUCL implementor is aware of the
 problem, and we are hoping for a fix before the next ACL2 release</p>

 <p>The @(see state) global variables, @('serialize-character-system') and
 @('serialize-character'), are now preserved after @(tsee make-event)
 expansion.  This change for @('serialize-character-system') allows the use of
 @('make-event') to avoid a stack overflow when writing out a @(see
 certificate) file; see @(see set-serialize-character-system).</p>

 <h3>EMACS Support</h3>

 <p>Now, tags table @('TAGS-acl2-doc') is automatically built when building the
 manual unless environment variable @('TAGS_ACL2_DOC') has value @('SKIP').  It
 can also be built by using the new event @(tsee xdoc::save-rendered-event).
 See @(see acl2-doc) and see @(see xdoc::save-rendered-event).  Thanks to Eric
 Smith and David Rager for discussions leading to this enhancement.  That tags
 table can also be built when building ACL2; see @(see acl2-doc).</p>

 <p>Made miscellaneous fixes for @(see acl2-doc): added @('Shift-<tab>')
 (more precisely, @('<backtab>') to do the same thing as
 @('Control-<tab>') (thanks to Eric McCarthy for the suggestion), avoided the
 use of @('setf') (not always defined without requiring the @('cl') package),
 avoided a potential error (when variable @('large-file-warning-threshold') is
 @('nil')), and avoided an infinite loop on some platforms when quitting
 acl2-doc.</p>

 <p>Defined `@('meta-,')' in @('emacs/emacs-acl2.el') to be Emacs function
 @('tags-loop-continue'), which is how it has traditionally been defined by
 Emacs but might be defined differently in some versions of Emacs 25 (and
 perhaps later).  <b>NOTE</b>: Put @('(setq *preserve-tags-loop-continue* t)')
 in your @('.emacs') file before loading ACL2 file @('emacs/emacs-acl2.el'), if
 you want to avoid redefining `@('meta-,')'.  Thanks to Keshav Kini and Mihir
 Mehta for helpful discussions.</p>

 <p>Removed both non-ascii characters from @('emacs/emacs-acl2.el').  Thanks to
 Keshav Kini for the suggestion.</p>

 <p>For documentation printed at the terminal with @(':')@(tsee doc), links
 (enclosed in in square brackets, ``[..]'') continue to be printed with respect
 to the @('\"ACL2\"') package (that is, as though the current package were
 @('\"ACL2\"')).  Now, however, where a link formerly might be printed as
 ``[acl2::foo]'', it is now printed as ``[foo]''; that is, a package prefix of
 @('\"ACL2\"') (regardless of case) is not printed.</p>

 <h3>Experimental Versions</h3>

 <p>Improved @(see type-set) reasoning for the function, @(tsee imagpart).
 Thanks to Keshav Kini for identifying the problem and suggesting a code
 change, and for sending an example of a theorem that formerly failed to be
 proved in ACL2(r).</p>

 <p>Improved @(see type-set) reasoning for the function, @(tsee complex).
 Thanks to Keshav Kini for identifying the problem and sending a patch, which
 we installed, together with examples of theorems that formerly failed to be
 proved in ACL2(r) but now prove, in particular:</p>

 @({
 (thm (implies (and (real/rationalp a)
                    (not (rationalp a)))
               (not (complex-rationalp (complex a b)))))
 })

 <p>Since @(tsee wormhole) uses a lock (and has for some time), we modified
 @(tsee observation-cw) so that it uses the same wormhole printing in ACL2(p)
 (instead of using @(tsee cw)) that is used in regular ACL2.  Thanks to David
 Rager for a helpful discussion.  If you see an increase in hangs while using
 ACL2(p), please contact the implementors.</p>

 <p>Fixed an infinite loop that could be caused with parallelism enabled when
 there is an error, when Lisp variable @('*hard-error-is-error*') has been set
 to a non-@('nil') value in raw Lisp (see @(see hard-error)).</p>

 ")

(defpointer note1 note-1-1)
(defpointer note2 note-1-2)
(defpointer note3 note-1-3)
(defpointer note4 note-1-4)
(defpointer note5 note-1-5)
(defpointer note6 note-1-6)
(defpointer note7 note-1-7)
(defpointer note8 note-1-8)
(defpointer note8-update note-1-8-update)
(defpointer note9 note-1-9)

(defxdoc nqthm-to-acl2
  :parents (acl2-tutorial)
  :short "ACL2 analogues of Nqthm functions and commands"
  :long "@({
  Example Forms:
  :nqthm-to-acl2 prove-lemma   ; Display ACL2 topic(s) and/or print
                               ; information corresponding to Nqthm
                               ; PROVE-LEMMA command.
  (nqthm-to-acl2 'prove-lemma) ; Same as above.

  General Form:
  (nqthm-to-acl2 name)
 })

 <p>where @('name') is a notion documented for Nqthm: either a function in the
 Nqthm logic, or a command.  If there is corresponding information available
 for ACL2, it will be printed in response to this command.  This information is
 not intended to be completely precise, but rather, is intended to help those
 familiar with Nqthm to make the transition to ACL2.</p>

 <p>We close with two tables that contain all the information used by this
 @('nqthm-to-acl2') command.  The first shows the correspondence between
 functions in the Nqthm logic and corresponding ACL2 functions (when possible);
 the second is similar, but for commands rather than functions.</p>

 @({
  Nqthm functions  -->     ACL2
  ----------------------------------------
  ADD1          -->  1+
  ADD-TO-SET    -->  ADD-TO-SET-EQUAL and ADD-TO-SET-EQ
  AND           -->  AND
  APPEND        -->  APPEND and BINARY-APPEND
  APPLY-SUBR    -->  No correspondent, but see the documentation for
                     DEFEVALUATOR and META.
  APPLY$        -->  No correspondent, but see the documentation for
                     DEFEVALUATOR and META.
  ASSOC         -->  ASSOC-EQUAL, ASSOC and ASSOC-EQ
  BODY          -->  No correspondent, but see the documentation for
                     DEFEVALUATOR and META.
  CAR           -->  CAR
  CDR           -->  CDR
  CONS          -->  CONS
  COUNT         -->  ACL2-COUNT
  DIFFERENCE    -->  -
  EQUAL         -->  EQUAL, EQ, EQL and =
  EVAL$         -->  No correspondent, but see the documentation for
                     DEFEVALUATOR and META.
  FALSE         -->  Nqthm's F corresponds to the ACL2 symbol NIL.
  FALSEP        -->  NOT and NULL
  FORMALS       -->  No correspondent, but see the documentation for
                     DEFEVALUATOR and META.
  GEQ           -->  >=
  GREATERP      -->  >
  IDENTITY      -->  IDENTITY
  IF            -->  IF
  IFF           -->  IFF
  IMPLIES       -->  IMPLIES
  LEQ           -->  <=
  LESSP         -->  <
  LISTP         -->  CONSP
  LITATOM       -->  SYMBOLP
  MAX           -->  MAX
  MEMBER        -->  MEMBER-EQUAL, MEMBER and MEMBER-EQ
  MINUS         -->  - and UNARY--
  NEGATIVEP     -->  MINUSP
  NEGATIVE-GUTS -->  ABS
  NLISTP        -->  ATOM
  NOT           -->  NOT
  NUMBERP       -->  ACL2-NUMBERP, INTEGERP and RATIONALP
  OR            -->  OR
  ORDINALP      -->  O-P
  ORD-LESSP     -->  O<
  PACK          -->  See intern and coerce.
  PAIRLIST      -->  PAIRLIS$
  PLUS          -->  + and BINARY-+
  QUOTIENT      -->  /
  REMAINDER     -->  REM and MOD
  STRIP-CARS    -->  STRIP-CARS
  SUB1          -->  1-
  TIMES         -->  * and BINARY-*
  TRUE          -->  The symbol T.
  UNION         -->  UNION-EQUAL and UNION-EQ
  UNPACK        -->  See symbol-name and coerce.
  V&C$          -->  No correspondent, but see the documentation for
                     DEFEVALUATOR and META.
  V&C-APPLY$    -->  No correspondent, but see the documentation for
                     DEFEVALUATOR and META.
  ZERO          -->  The number 0.
  ZEROP         -->  ZP



  Nqthm commands   -->     ACL2
  ----------------------------------------
  ACCUMULATED-PERSISTENCE
                -->  ACCUMULATED-PERSISTENCE
  ADD-AXIOM     -->  DEFAXIOM
  ADD-SHELL     -->  There is no shell principle in ACL2.
  AXIOM         -->  DEFAXIOM
  BACKQUOTE-SETTING
                -->  Backquote is supported in ACL2, but not
                     currently documented.
  BOOT-STRAP    -->  GROUND-ZERO
  BREAK-LEMMA   -->  MONITOR
  BREAK-REWRITE -->  BREAK-REWRITE
  CH            -->  PBT
                     See also :DOC history.
  CHRONOLOGY    -->  PBT
                     See also :DOC history.
  COMMENT       -->  DEFLABEL
  COMPILE-UNCOMPILED-DEFNS
                -->  COMP
  CONSTRAIN     -->  See :DOC encapsulate and :DOC local.
  DATA-BASE     -->  Perhaps the closest ACL2 analogue of DATA-BASE
                     is PROPS.  But see :DOC history for a collection
                     of commands for querying the ACL2 database
                     (``world'').  Note that the notions of
                     supporters and dependents are not supported in
                     ACL2.
  DCL           -->  DEFSTUB
  DEFN          -->  DEFUN and DEFMACRO
  DEFTHEORY     -->  DEFTHEORY
  DISABLE       -->  DISABLE
  DISABLE-THEORY
                -->  See :DOC theories.  The Nqthm command
                     (DISABLE-THEORY FOO) corresponds roughly to the
                     ACL2 command
                     (in-theory (set-difference-theories
                                  (current-theory :here)
                                  (theory 'foo))).
  DO-EVENTS     -->  LD
  DO-FILE       -->  LD
  ELIM          -->  ELIM
  ENABLE        -->  ENABLE
  ENABLE-THEORY -->  See :DOC theories.  The Nqthm command
                     (ENABLE-THEORY FOO) corresponds roughly to the
                     ACL2 command
                     (in-theory (union-theories
                                  (theory 'foo)
                                  (current-theory :here))).
  EVENTS-SINCE  -->  PBT
  FUNCTIONALLY-INSTANTIATE
                -->  ACL2 provides a form of the :USE hint that
                     corresponds roughly to the
                     FUNCTIONALLY-INSTANTIATE event of Nqthm. See
                     :DOC lemma-instance.
  GENERALIZE    -->  GENERALIZE
  HINTS         -->  HINTS
  LEMMA         -->  DEFTHM
  MAINTAIN-REWRITE-PATH
                -->  BRR
  MAKE-LIB      -->  There is no direct analogue of Nqthm's notion of
                     ``library.''  See :DOC books for a description
                     of ACL2's mechanism for creating and saving
                     collections of events.
  META          -->  META
  NAMES         -->  NAME
  NOTE-LIB      -->  INCLUDE-BOOK
  PPE           -->  PE
  PROVE         -->  THM
  PROVEALL      -->  See :DOC ld and :DOC certify-book.  The latter
                     corresponds to Nqthm's PROVE-FILE,which may be
                     what you're interested in,really.
  PROVE-FILE    -->  CERTIFY-BOOK
  PROVE-FILE-OUT
                -->  CERTIFY-BOOK
  PROVE-LEMMA   -->  DEFTHM
                     See also :DOC hints.
  R-LOOP        -->  The top-level ACL2 loop is an evaluation loop as
                     well, so no analogue of R-LOOP is necessary.
  REWRITE       -->  REWRITE
  RULE-CLASSES  -->  RULE-CLASSES
  SET-STATUS    -->  IN-THEORY
  SKIM-FILE     -->  LD-SKIP-PROOFSP
  TOGGLE        -->  IN-THEORY
  TOGGLE-DEFINED-FUNCTIONS
                -->  EXECUTABLE-COUNTERPART-THEORY
  TRANSLATE     -->  TRANS and TRANS1
  UBT           -->  UBT and U
  UNBREAK-LEMMA -->  UNMONITOR
  UNDO-BACK-THROUGH
                -->  UBT
  UNDO-NAME     -->  See :DOC ubt.  There is no way to undo names in
                     ACL2 without undoing back through such names.
                     However, see :DOC ld-skip-proofsp for
                     information about how to quickly recover the
                     state.
 })")

(defxdoc nth
  :parents (lists acl2-built-ins)
  :short "The nth element (zero-based) of a list"
  :long "<p>@('(Nth n l)') is the @('n')th element of @('l'), zero-based.  If
 @('n') is greater than or equal to the length of @('l'), then @('nth') returns
 @('nil').</p>

 <p>@('(Nth n l)') has a @(see guard) that @('n') is a non-negative integer and
 @('l') is a @(tsee true-listp).</p>

 <p>@('Nth') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def nth)")

(defxdoc nth-aliases-table
  :parents (stobj nth update-nth)
  :short "A @(see table) used to associate names for nth/update-nth printing"
  :long "@({
  Example:
  (table nth-aliases-table 'st0 'st)
 })

 <p>This example associates the symbol @('st0') with the symbol @('st').  As a
 result, when the theorem prover prints terms of the form @('(nth n st0)') or
 @('(update-nth n val st0)'), where @('st') is a @(see stobj) whose @('n')th
 accessor function is @('f-n'), then it will print @('n') as @('*f-n*').</p>

 @({
  General Form:
  (table nth-aliases-table 'alias-name 'name)
 })

 <p>This event causes @('alias-name') to be treated like @('name') for purposes
 of the printing of terms that are calls of @('nth') and @('update-nth').
 (Note however that @('name') is not recursively looked up in this table.)
 Both must be symbols other than @(tsee state).  See @(see term), in particular
 the discussion there of untranslated terms.</p>

 <p>For a convenient way to add entries to this @(see table), see @(see
 add-nth-alias).  To remove entries from the @(see table) with ease, see @(see
 remove-nth-alias).</p>")

(defxdoc nthcdr
  :parents (lists acl2-built-ins)
  :short "Final segment of a list"
  :long "<p>@('(Nthcdr n l)') removes the first @('n') elements from the list
 @('l').</p>

 <p>The following is a theorem.</p>

 @({
  (implies (and (integerp n)
                (<= 0 n)
                (true-listp l))
           (equal (length (nthcdr n l))
                  (if (<= n (length l))
                      (- (length l) n)
                    0)))
 })

 <p>For related functions, see @(see take) and see @(see butlast).</p>

 <p>The @(see guard) of @('(nthcdr n l)') requires that @('n') is a nonnegative
 integer and @('l') is a true list.</p>

 <p>@('Nthcdr') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def nthcdr)")

(defxdoc null
  :parents (basics acl2-built-ins)
  :short "Recognizer for the empty list"
  :long "<p>@('Null') is the function that checks whether its argument is
 @('nil').  For recursive definitions it is often preferable to test for the
 end of a list using @(tsee endp) instead of @('null'); see @(see endp).</p>

 <p>@('Null') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def null)")

(defxdoc number-subtrees
  :parents (hons-and-memoization acl2-built-ins)
  :short "@('(number-subtrees x)') returns the number of distinct subtrees of
X, in the sense of @(tsee equal)"
  :long "<p>In the logic, @('number-subtrees') is defined as the length of
 @(tsee cons-subtrees).</p>

 <p>Under the hood, we first @(tsee hons-copy) X to obtain a normed version,
 then count the number of unique conses in X using an EQ hash table.</p>

 @(def number-subtrees)")

(defxdoc numbers
  :parents (programming)
  :short "Numbers in ACL2 and operations on them"
  :long "<p>See @(see numbers-introduction) for introductory background.  See @(see
arithmetic) for libraries of @(see books) for arithmetic reasoning.</p>")

(defxdoc numerator
  :parents (numbers acl2-built-ins)
  :short "Dividend of a ratio in lowest terms"
  :long "<p>Completion Axiom (@('completion-of-numerator')):</p>

 @({
  (equal (numerator x)
         (if (rationalp x)
             (numerator x)
           0))
 })

 <p>@(see Guard) for @('(numerator x)'):</p>

 @({
  (rationalp x)
 })")

(defxdoc |Name the Formula Above|
  :parents (|Pages Written Especially for the Tours|)
  :short "Name the Formula Above"
  :long "<p>When the theorem prover explicitly assigns a name, like @('*1'), to
 a formula, it has decided to prove the formula by induction.</p>")

(defxdoc |Nontautological Subgoals|
  :parents (|Pages Written Especially for the Tours|)
  :short "Prover output omits some details"
  :long "<p>The theorem prover's proof output is intended to suggest an outline
 of the reasoning process employed by its proof engine, which is virtually
 always more than is necessary for the ACL2 user.  In particular, the output
 often omits subgoals that are sufficiently trivial, including
 tautologies.</p>")

(defconst *xdoc-long-numbers-introduction*

; Warning: Do not add references requiring a tiny warning sign, because this
; :long string is used not only in The Tours, but also in regular ACL2
; documentation.

  "<p>ACL2 numbers are precisely represented and unbounded.  They can be
 partitioned into the following subtypes:</p>

 @({
  ACL2 Numbers
   |
   |- Rationals
   |  |
   |  |- Integers
   |  |  |- Positive integers                 3
   |  |  |- Zero                              0
   |  |  |- Negative Integers                 -3
   |  |
   |  |- Non-Integral Rationals
   |  |  |
   |  |  |- Positive Non-Integral Rationals   19/3
   |  |  |- Negative Non-Integral Rationals   -22/7
   |
   |- Complex Rational Numbers                 #c(3 5/2) ; i.e., 3 + (5/2)i
 })

 <p>Signed integer constants are usually written (as illustrated above) as
 sequences of decimal digits, possibly preceded by @('+') or @('-').  Decimal
 points are not allowed.  Integers may be written in binary, as in @('#b1011')
 (= 23) and @('#b-111') (= -7).  Octal may also be used, @('#o-777') = -511.
 Non-integral rationals are written as a signed decimal integer and an unsigned
 decimal integer, separated by a slash.  Complex rationals are written as
 #c(rpart ipart) where rpart and ipart are rationals.</p>

 <p>Of course, 4/2 = 2/1 = 2 (i.e., not every rational written with a slash is
 a non-integer).  Similarly, #c(4/2 0) = #c(2 0) = 2.</p>

 <p>The common arithmetic functions and relations are denoted by @('+'),
 @('-'), @('*'), @('/'), @('='), @('<'), @('<='), @('>') and @('>=').  However
 there are many others, e.g., @('floor'), @('ceiling'), and @('lognot').  See
 any Common Lisp language documentation.</p>

 <p>The primitive predicates for recognizing numbers are illustrated below.
 The following ACL2 function will classify an object, x, according to its
 numeric subtype, or else return 'NaN (not a number).  We show it this way just
 to illustrate programming in ACL2.</p>

 @({
  (defun classify-number (x)
    (cond ((rationalp x)
           (cond ((integerp x)
                  (cond ((< 0 x) 'positive-integer)
                        ((= 0 x) 'zero)
                        (t 'negative-integer)))
                 ((< 0 x) 'positive-non-integral-rational)
                 (t 'negative-non-integral-rational)))
          ((complex-rationalp x) 'complex-rational)
          (t 'NaN)))
 })")

(defxdoc |Numbers in ACL2|

; This topic is essentially the same as numbers-introduction, but it has a name
; that shows up more nicely when taking the walking tour of ACL2.

  :parents (|Pages Written Especially for the Tours|)
  :short "Numbers in ACL2"
  :long *xdoc-long-numbers-introduction*)

(defxdoc numbers-introduction

; This topic is essentially the same as |Numbers in ACL2|, which is a topic for
; the walking tour, but here the name provides a nicer link when browsing the
; ACL2 documentation, especially if using the Emacs-based ACL2-Doc browser.

  :parents (numbers)
  :short "Numbers in ACL2"
  :long *xdoc-long-numbers-introduction*)

(defxdoc o-finp
  :parents (ordinals acl2-built-ins)
  :short "Recognizes if an ordinal is finite"
  :long "<p>We introduce the function @('o-finp') which returns @('t') for any
 ordinal that is finite, else @('nil').  This function is equivalent to the
 function @(tsee atom), and is introduced so that we can @(tsee disable) its
 definition when dealing with ordinals (also see @(see make-ord)).</p>

 @(def o-finp)")

(defxdoc o-first-coeff
  :parents (ordinals acl2-built-ins)
  :short "Returns the first coefficient of an ordinal"
  :long "<p>An ACL2 ordinal is either a natural number or, for an infinite
 ordinal, a list whose elements are exponent-coefficient pairs (see @(see
 o-p)).  In the latter case, this function returns the @(tsee cdr) of the first
 pair in the list.  In the case of a natural number, this function returns the
 ordinal itself (since a natural number, n, can be thought of as (w^0)n).</p>

 <p>For the corresponding exponent, see @(see o-first-expt).</p>

 @(def o-first-coeff)")

(defxdoc o-first-expt
  :parents (ordinals acl2-built-ins)
  :short "The first exponent of an ordinal"
  :long "<p>An ACL2 ordinal is either a natural number or, for an infinite
 ordinal, a list whose elements are exponent-coefficient pairs (see @(see
 o-p)).  In the latter case, this function returns the @(tsee car) of the first
 pair in the list.  In the case of a natural number, the value returned is
 0 (since a natural number, @('n'), can be thought of as (w^0)n).</p>

 <p>For the corresponding coefficient, see @(see o-first-coeff).</p>

 @(def o-first-expt)")

(defxdoc o-infp
  :parents (ordinals acl2-built-ins)
  :short "Recognizes if an ordinal is infinite"
  :long "<p>@('O-infp') is a macro.  @('(O-infp x)') opens up to
  @('(not (o-finp x))').</p>")

(defxdoc o-p
  :parents (ordinals acl2-built-ins)
  :short "A recognizer for the ordinals up to epsilon-0"
  :long "<p>Using the nonnegative integers and lists we can represent the
 ordinals up to @('epsilon-0'). The ordinal representation used in ACL2 has
 changed as of Version_2.8 from that of Nqthm-1992, courtesy of Pete Manolios
 and Daron Vroon; additional discussion may be found in ``Ordinal Arithmetic in
 ACL2'', <a
 href='http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/'>proceedings of
 ACL2 Workshop 2003</a>.  Previously, ACL2's notion of ordinal was very similar
 to the development given in ``New Version of the Consistency Proof for
 Elementary Number Theory'' in The Collected Papers of Gerhard Gentzen,
 ed. M.E. Szabo, North-Holland Publishing Company, Amsterdam, 1969, pp
 132-213.</p>

 <p>The following essay is intended to provide intuition about ordinals.  The
 truth, of course, lies simply in the ACL2 definitions of @('o-p') and @(tsee
 o<).</p>

 <p>Very intuitively, think of each non-zero natural number as by being denoted
 by a series of the appropriate number of strokes, i.e.,</p>

 @({
  0             0
  1             |
  2             ||
  3             |||
  4             ||||
  ...           ...
 })

 <p>Then ``@('omega'),'' here written as @('w'), is the ordinal that might be
 written as</p>

 @({
  w             |||||...,
 })

 <p>i.e., an infinite number of strokes.  Addition here is just concatenation.
 Observe that adding one to the front of @('w') in the picture above produces
 @('w') again, which gives rise to a standard definition of @('w'): @('w') is
 the least ordinal such that adding another stroke at the beginning does not
 change the ordinal.</p>

 <p>We denote by @('w+w') or @('w*2') the ``@('doubly infinite')'' sequence
 that we might write as follows.</p>

 @({
  w*2           |||||... |||||...
 })

 <p>One way to think of @('w*2') is that it is obtained by replacing each
 stroke in @('2') @('(||)') by @('w').  Thus, one can imagine @('w*3'),
 @('w*4'), etc., which leads ultimately to the idea of ``@('w*w'),'' the
 ordinal obtained by replacing each stroke in @('w') by @('w').  This is also
 written as ``@('omega') squared'' or @('w^2'), or:</p>

 @({
   2
  w             |||||... |||||... |||||... |||||... |||||... ...
 })

 <p>We can analogously construct @('w^3') by replacing each stroke in @('w') by
 @('w^2') (which, it turns out, is the same as replacing each stroke in
 @('w^2') by @('w')).  That is, we can construct @('w^3') as @('w') copies of
 @('w^2'),</p>

 @({
   3              2       2       2       2
  w              w  ...  w  ...  w  ...  w ... ...
 })

 <p>Then we can construct @('w^4') as @('w') copies of @('w^3'), @('w^5') as
 @('w') copies of @('w^4'), etc., ultimately suggesting @('w^w').  We can then
 stack @('omega')s, i.e., @('(w^w)^w') etc.  Consider the ``limit'' of all of
 those stacks, which we might display as follows.</p>

 @({
         .
        .
       .
      w
     w
    w
   w
  w
 })

 <p>That is epsilon-0.</p>

 <p>Below we begin listing some ordinals up to @('epsilon-0'); the reader can
 fill in the gaps at his or her leisure.  We show in the left column the
 conventional notation, using @('w') as ``@('omega'),'' and in the right column
 the ACL2 object representing the corresponding ordinal.</p>

 @({
    ordinal            ACL2 representation

    0                  0
    1                  1
    2                  2
    3                  3
    ...                ...
    w                 '((1 . 1) . 0)
    w+1               '((1 . 1) . 1)
    w+2               '((1 . 1) . 2)
    ...                ...
    w*2               '((1 . 2) . 0)
    (w*2)+1           '((1 . 2) . 1)
    ...                ...
    w*3               '((1 . 3) . 0)
    (w*3)+1           '((1 . 3) . 1)
    ...                ...

     2
    w                 '((2 . 1) . 0)
    ...                ...

     2
    w +w*4+3          '((2 . 1) (1 . 4) . 3)
    ...                ...

     3
    w                 '((3 . 1) . 0)
    ...                ...

     w
    w                 '((((1 . 1) . 0) . 1) . 0)
    ...                ...

     w  99
    w +w  +w4+3       '((((1 . 1) . 0) . 1) (99 . 1) (1 . 4) . 3)
    ...                ...

      2
     w
    w                 '((((2 . 1) . 0) . 1) . 0)

    ...                ...

      w
     w
    w                 '((((((1 . 1) . 0) . 1) . 0) . 1) . 0)
    ...               ...
 })

 <p>Observe that the sequence of @('o-p')s starts with the natural numbers
 (which are recognized by @(tsee natp)). This is convenient because it means
 that if a term, such as a measure expression for justifying a recursive
 function (see @(see o<)) must produce an @('o-p'), it suffices for it to
 produce a natural number.</p>

 <p>The ordinals listed above are listed in ascending order.  This is the
 ordering tested by @(tsee o<).</p>

 <p>The ``@('epsilon-0') ordinals'' of ACL2 are recognized by the recursively
 defined function @('o-p').  The base case of the recursion tells us that
 natural numbers are @('epsilon-0') ordinals.  Otherwise, an @('epsilon-0')
 ordinal is a list of @(tsee cons) pairs whose final @(tsee cdr) is a natural
 number, @('((a1 . x1) (a2 . x2) ... (an . xn) . p)').  This corresponds to the
 ordinal @('(w^a1)x1 + (w^a2)x2 + ... + (w^an)xn + p').  Each @('ai') is an
 ordinal in the ACL2 representation that is not equal to 0.  The sequence of
 the @('ai')'s is strictly decreasing (as defined by @(tsee o<)). Each @('xi')
 is a positive integer (as recognized by @(tsee posp)).</p>

 <p>Note that infinite ordinals should generally be created using the ordinal
 constructor, @(tsee make-ord), rather than @(tsee cons). The functions @(tsee
 o-first-expt), @(tsee o-first-coeff), and @(tsee o-rst) are ordinals
 destructors.  Finally, the function @(tsee o-finp) and the macro @(tsee
 o-infp) tell whether an ordinal is finite or infinite, respectively.</p>

 <p>The function @(tsee o<) compares two @('epsilon-0') ordinals, @('x') and
 @('y').  If both are integers, @('(o< x y)') is just @('x<y').  If one is an
 integer and the other is a @(tsee cons), the integer is the smaller.
 Otherwise, @(tsee o<) recursively compares the @(tsee o-first-expt)s of the
 ordinals to determine which is smaller.  If they are the same, the @(tsee
 o-first-coeff)s of the ordinals are compared.  If they are equal, the @(tsee
 o-rst)s of the ordinals are recursively compared.</p>

 <p>Fundamental to ACL2 is the fact that @(tsee o<) is well-founded on
 @('epsilon-0') ordinals.  That is, there is no ``infinitely descending chain''
 of such ordinals.  See @(see proof-of-well-foundedness).</p>

 @(def o-p)")

(defxdoc o-rst
  :parents (ordinals acl2-built-ins)
  :short "Returns the rest of an infinite ordinal"
  :long "<p>An ACL2 infinite ordinal is a list whose elements are
 exponent-coefficient pairs (see @(see o-p) and see @(see o-infp)).  The first
 exponent and first coefficient of an ordinal can be obtained by using @(tsee
 o-first-expt) and @(tsee o-first-coeff) respectively.  To obtain the rest of
 the ordinal (for recursive analysis), use the @('o-rst') function. It returns
 the rest of the ordinal after the first exponent and coefficient are
 removed.</p>

 @(def o-rst)")

(defxdoc o<
  :parents (ordinals acl2-built-ins)
  :short "The well-founded less-than relation on ordinals up to @('epsilon-0')"
  :long "<p>If @('x') and @('y') are both @('o-p')s (see @(see o-p)) then
 @('(o< x y)') is true iff @('x') is strictly less than @('y').  @('o<') is
 well-founded on the @(tsee o-p)s.  When @('x') and @('y') are both nonnegative
 integers, @('o<') is just the familiar ``less than'' relation (@(tsee <)).</p>

 <p>@('o<') plays a key role in the formal underpinnings of the ACL2 logic.  In
 order for a recursive definition to be admissible it must be proved to
 ``terminate.''  By terminate we mean that the arguments to the function ``get
 smaller'' as the function recurs and this sense of size comparison must be
 such that there is no ``infinitely descending'' sequence of ever smaller
 arguments.  That is, the relation used to compare successive arguments must be
 well-founded on the domain being measured.</p>

 <p>The most basic way ACL2 provides to prove termination requires the user to
 supply (perhaps implicitly) a mapping of the argument tuples into the ordinals
 with some ``measure'' expression in such a way that the measures of the
 successive argument tuples produced by recursion decrease according to the
 relation @('o<').  The validity of this method rests on the well-foundedness
 of @('o<') on the @(tsee o-p)s.</p>

 <p>Without loss of generality, suppose the definition in question introduces
 the function @('f'), with one formal parameter @('x') (which might be a list
 of objects).  Then we require that there exist a measure expression, @('(m
 x)'), that always produces an @(tsee o-p).  Furthermore, consider any
 recursive call, @('(f (d x))'), in the body of the definition.  Let @('hyps')
 be the conjunction of terms, each of which is either the test of an @(tsee if)
 in the body or else the negation of such a test, describing the path through
 the body to the recursive call in question.  Then it must be a theorem
 that</p>

 @({
    (IMPLIES hyps (O< (m (d x)) (m x))).
 })

 <p>When we say @('o<') is ``well-founded'' on the @(tsee o-p)s we mean that
 there is no infinite sequence of @(tsee o-p)s such that each is smaller than
 its predecessor in the sequence.  Thus, the theorems that must be proved about
 @('f') when it is introduced establish that it cannot recur forever because
 each time a recursive call is taken @('(m x)') gets smaller.  From this, and
 the syntactic restrictions on definitions, it can be shown (as on page 44 in
 ``A Computational Logic'', Boyer and Moore, Academic Press, 1979) that there
 exists a function satisfying the definition; intuitively, the value assigned
 to any given @('x') by the alleged function is that computed by a sufficiently
 large machine.  Hence, the logic is consistent if the axiom defining @('f') is
 added.</p>

 <p>See @(see o-p) for a discussion of the ordinals and how to compare two
 ordinals.</p>

 <p>The definitional principle permits the use of relations other than @('o<')
 but they must first be proved to be well-founded on some domain.  See @(see
 well-founded-relation-rule).  Roughly put, alternative relations are shown
 well-founded by providing an order-preserving mapping from their domain into
 the ordinals.  See @(see defun) for details on how to specify which
 well-founded relation is to be used.</p>

 @(def o<)")

(defxdoc o<=
  :parents (ordinals acl2-built-ins)
  :short "The less-than-or-equal relation for the ordinals"
  :long "<p>@('o<=') is a macro and @('(o<= x y)') expands to @('(not (o< y
 x))').  See @(see o<).</p>")

(defxdoc o>
  :parents (ordinals acl2-built-ins)
  :short "The greater-than relation for the ordinals"
  :long "<p>@('O>') is a macro and @('(o> x y)') expands to @('(o< y x)').  See
 @(see o<).</p>")

(defxdoc o>=
  :parents (ordinals acl2-built-ins)
  :short "The greater-than-or-equal relation for the ordinals"
  :long "<p>@('O>=') is a macro and @('(o>= x y)') expands to @('(not (o< x
 y))').  See @(see o<).</p>")

(defxdoc obdd
  :parents (bdd)
  :short "Ordered binary decision diagrams with rewriting"
  :long "<p>See @(see bdd) for information on this topic.</p>")

(defxdoc observation
  :parents (io acl2-built-ins)
  :short "Print an observation"
  :long "<p>Here is a typical application of @('observation').</p>

 @({
  ACL2 !>(let ((ctx 'top-level)
               (name 'foo))
           (observation ctx
                        \"Skipping processing of name ~x0.\"
                        name))

  ACL2 Observation in TOP-LEVEL:  Skipping processing of name FOO.
  <state>
  ACL2 !>
 })

 <p>@('Observation') prints an initial ``@('ACL2 Observation...: ')'', and then
 prints the indicated message using formatted printing (see @(see fmt)).
 Notice in the example above that evaluation of a call of @('observation')
 returns @(tsee state).  Indeed, @('observation') is actually a macro whose
 expansion takes and returns the ACL2 @(tsee state).  A similar utility,
 @('observation-cw'), is available that does not take or return @('state');
 rather, it returns @('nil') as the suffix ``@('cw')'' suggests that a
 ``comment window'' is the target of this printing, rather than the state.  For
 example:</p>

 @({
  ACL2 !>(let ((ctx 'top-level)
               (name 'foo))
           (observation-cw ctx
                           \"Skipping processing of name ~x0.\"
                           name))

  ACL2 Observation in TOP-LEVEL:  Skipping processing of name FOO.
  NIL
  ACL2 !>
 })

 <p>@('Observation-cw') takes exactly the same arguments as @('observation'),
 but @('observation-cw') does its printing in a so-called ``wormhole''; see
 @(see wormhole).</p>

 @({
  General Forms:
  (observation    ctx fmt-string fmt-arg1 fmt-arg2 ... fmt-argk)
  (observation-cw ctx fmt-string fmt-arg1 fmt-arg2 ... fmt-argk)
 })

 <p>where @('ctx') generally evaluates to a symbol (but see below), and
 @('fmt-string') together with the @('fmt-argi') are suitable for passing to
 @(tsee fmt).  Output begins and ends with a newline.</p>

 <p>Recall from the example above that the output from a call of
 @('observation') (or @('observation-cw')) begins with ``@('ACL2
 Observation')'' and additional characters ending in ``@(': ')'', for example
 ``@(' in TOP-LEVEL: ')'', followed by formatted output produced from
 @('fmt-string') with the given @('fmt-argi').  The characters printed
 immediately following the string ``@('ACL2 Observation')'' depend on the value
 of @('ctx').  If @('ctx') is @('nil'), nothing is printed.  If @('ctx') is a
 non-@('nil') symbol, it is printed using @(tsee fmt) directive @('~x').  If
 @('ctx') is a @(tsee cons) pair whose @(tsee car) is a symbol, formatted
 printing is applied to the string \"(~x0 ~x1 ...)\", where @('#\\0') and
 @('#\\1') are bound respectively to that car and cdr.  Otherwise, @('ctx') is
 printed using @(tsee fmt) directive @('~@').</p>

 <p>We next discuss situations in which printing is inhibited for
 @('observation') and @('observation-cw').  No printing is done when
 @('observation') is among the inhibited output types; see @(see
 set-inhibit-output-lst).  Moreover, no printing is done by @('observation')
 during @(tsee include-book).  If you want to avoid printing from
 @('observation-cw') during @(tsee include-book), then you need to manage that
 yourself.</p>")

(defxdoc oddp
  :parents (numbers acl2-built-ins)
  :short "Test whether an integer is odd"
  :long "<p>@('(oddp x)') is true if and only if @('x') is odd, i.e., not even
 in the sense of @(tsee evenp).</p>

 <p>The @(see guard) for @('oddp') requires its argument to be an integer.</p>

 <p>@('Oddp') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def oddp)")

(defxdoc ok-if
  :parents (break-rewrite)
  :short "Conditional exit from @('break-rewrite')"
  :long "@({
  Example Form:
  :ok-if (null (brr@ :wonp))

  General Form:
  :ok-if expr
 })

 <p>where @('expr') is a term involving no free variables other than @('state')
 and returning one non-@('state') result which is treated as Boolean.  This
 form is intended to be executed from within @('break-rewrite') (see @(see
 break-rewrite)).</p>

 <p>Consider first the simple situation that the @('(ok-if term)') is a command
 read by @('break-rewrite').  Then, if the term is non-@('nil'),
 @('break-rewrite') exits and otherwise it does not.</p>

 <p>More generally, @('ok-if') returns an ACL2 error triple @('(mv erp val
 state)').  (See @(see ld) or see @(see programming-with-state) for more on
 error triples.)  If any form being evaluated as a command by
 @('break-rewrite') returns the triple returned by @('(ok-if term)') then the
 effect of that form is to exit @(see break-rewrite) if term is non-@('nil').
 Thus, one might define a function or macro that returns the value of
 @('ok-if') expressions on all outputs and thus create a convenient new way to
 exit @('break-rewrite').</p>

 <p>The exit test, @('term'), generally uses @('brr@') to access context
 sensitive information about the attempted rule application.  See @(see brr@).
 @('Ok-if') is useful inside of command sequences produced by break conditions.
 See @(see monitor).  @(':ok-if') is most useful after an @(':eval') command
 has caused @('break-rewrite') to try to apply the rule because in the
 resulting break environment @('expr') can access such things as whether the
 rule succeeded, if so, what term it produced, and if not, why.  There is no
 need to use @(':ok-if') before @(':eval')ing the rule since the same effects
 could be achieved with the break condition on the rule itself.  Perhaps we
 should replace this concept with @(':eval-and-break-if')?  Time will
 tell.</p>")

(defxdoc oops
  :parents (history)
  :short "Undo a @(':u') or @(':')@(tsee ubt)"
  :long "<p>The keyword @(see command) @(':oops') will undo the most recent
 @(':')@(tsee ubt) (or @(':u'), which we here consider just another
 @(':')@(tsee ubt)).  A second @(':oops') will undo the next most recent
 @(':')@(tsee ubt), a third will undo the @(':')@(tsee ubt) before that one,
 and a fourth @(':oops') will return the logical @(see world) to its
 configuration before the first @(':oops').</p>

 <p>Consider the logical world (see @(see world)) that represents the current
 extension of the logic and ACL2's rules for dealing with it.  The @(':')@(tsee
 ubt) and @(':u') @(see command)s ``roll back'' to some previous @(see world)
 (see @(see ubt)).  Sometimes these @(see command)s are used to inadvertently
 undo useful work and user's wish they could ``undo the last undo.''  That is
 the function provided by @(':oops').</p>

 <p>@(':Oops') is best described in terms of an implementation.  Imagine a ring
 of four @(see world)s and a marker (@('*')) indicating the current ACL2 @(see
 world):</p>

 @({
               *
             w0
           /    \\
         w3      w1
           \\    /
             w2
 })

 <p>This is called the ``kill ring'' and it is maintained as follows.  When you
 execute an event the current @(see world) is extended and the kill ring is not
 otherwise affected.  When you execute @(':')@(tsee ubt) or @(':u'), the
 current @(see world) marker is moved one step counterclockwise and that @(see
 world) in the ring is replaced by the result, say @('w0''), of the
 @(':')@(tsee ubt) or @(':u').</p>

 @({
             w0
           /    \\
        *w0'     w1
           \\    /
             w2
 })

 <p>If you were to execute @(see events) at this point, @('w0'') would be
 extended and no other changes would occur in the kill ring.</p>

 <p>When you execute @(':oops'), the marker is moved one step clockwise.  Thus
 the kill ring becomes</p>

 @({
               *
             w0
           /    \\
         w0'     w1
           \\    /
             w2
 })

 <p>and the current ACL2 @(see world) is @('w0') once again.  That is,
 @(':oops') ``undoes'' the @(':')@(tsee ubt) that produced @('w0'') from
 @('w0').  Similarly, a second @(':oops') will move the marker to @('w1'),
 undoing the undo that produced @('w0') from @('w1').  A third @(':oops') makes
 @('w2') the current @(see world).  Note however that a fourth @(':oops')
 restores us to the configuration previously displayed above in which @('w0'')
 has the marker.</p>

 <p>In general, the kill ring contains the current @(see world) and the three
 most recent @(see world)s in which a @(':')@(tsee ubt) or @(':u') were
 done.</p>

 <p>While @(':')@(tsee ubt) may appear to discard the information in the @(see
 events) undone, we can see that the @(see world) in which the @(':')@(tsee
 ubt) occurred is still available.  No information has been lost about that
 @(see world).  But @(':')@(tsee ubt) does discard information!  @(':')@(tsee
 Ubt) discards the information necessary to recover from the third most recent
 @(tsee ubt)!  An @(':oops'), on the other hand, discards no information, it
 just selects the next available @(see world) on the kill ring and doing enough
 @(':oops')es will return you to your starting point.</p>

 <p>We can put this another way.  You can freely type @(':oops') and inspect
 the @(see world) that you thus obtain with @(':')@(tsee pe), @(':')@(tsee pc),
 and other @(see history) @(see command)s.  You can repeat this as often as you
 wish without risking the permanent loss of any information.  But you must be
 more careful typing @(':')@(tsee ubt) or @(':u').  While @(':oops') makes
 @(':')@(tsee ubt) seem ``safe'' because the most recent @(':')@(tsee ubt) can
 always be undone, information is lost when you execute @(':')@(tsee ubt).</p>

 <p>We note that @(':ubt') and @(':u') may remove compiled definitions (but
 note that in some Lisps, including CCL (OpenMCL) and SBCL, functions are
 always compiled).  When the original world is restored using @(':oops'),
 restored functions will not generally be compiled (except for Lisps as above),
 though the user can remedy this situation; see @(see comp).</p>

 <p>Finally, we note that our implementation of @('oops') can use a significant
 amount of memory, because of the saving of old logical @(see world)s.  Most
 users are unlikely to experience a memory problem, but if you do, then you may
 want to disable @('oops') by evaluating @('(reset-kill-ring 0 state)'); see
 @(see reset-kill-ring).</p>")

(defxdoc open-output-channel!
  :parents (io acl2-built-ins)
  :short "When trust tags are needed to open output channels"
  :long "<p>Use this function in place of @('open-output-channel') if you want
 to open a channel for output at times this would otherwise be prohibited, for
 example during @(tsee make-event) expansion and @(tsee clause-processor) @(see
 hints).  If this functionality doesn't quite seem like what you need, take a
 look at the definition of @('open-output-channel!') in axioms.lisp,
 specifically the binding of @(tsee state) global variable @('writes-okp').
 The following example, taken from (no longer available) community book
 @('books/hons-archive/hons-archive.lisp'), illustrates the latter
 approach.</p>

 @({
  (defmacro har-zip! (x filename &key sortp)
    \"See :doc hons-archive\"
    `(mv-let (erp val state)
             (progn!
              :state-global-bindings
              ((temp-touchable-vars t set-temp-touchable-vars))
              (state-global-let*
               ((writes-okp t))
               (let ((state (har-zip-fn ,x ,filename ,sortp state)))
                 (mv nil nil state))))
             (declare (ignore erp val))
             state))
 })

 <p>The book below illustrates the soundness loophole plugged in ACL2
 Version_3.2 related to file writes during book certification.</p>

 @({
  ; The following example is adapted (with only very slight changes)
  ; from one written by Peter Dillinger.  It illustrates the prohibition
  ; against writing files enforced by with-output-channel during book
  ; certification (more specifically, during make-event expansion).

  ; This book certifies in ACL2 Version_3.1 before the fix discussed in the
  ; paragraph about it being ``possible to write files during book
  ; certification'' in :DOC NOTE-3-2.  The fix was actually made to ACL2
  ; function open-output-channel.

  ; After the fix, in order for certification to succeed one needs to do
  ; two things.  First, in raw lisp:
  ;   (push :after-writes-okp-fix *features*)
  ; Second, certify with this command:
  ;   (certify-book \"writes-okp\" 0 nil :ttags (:writes-okp))

  (in-package \"ACL2\")

  (local
   (defun write-objects-to-channel (obj-lst chan state)
     (declare (xargs :mode :program
                     :stobjs state
                     :guard (true-listp obj-lst)))
     (if (consp obj-lst)
         (pprogn (print-object$ (car obj-lst) chan state)
                 (write-objects-to-channel (cdr obj-lst) chan state)
                 state)
       state)))

  #+after-writes-okp-fix
  (defttag :writes-okp)

  (local
   (defun write-objects-to-file (obj-lst filename state)
     (declare (xargs :mode :program
                     :stobjs state
                     :guard (and (stringp filename)
                                 (true-listp obj-lst))))
     (mv-let (chan state)
             #-after-writes-okp-fix
             (open-output-channel filename :object state)
             #+after-writes-okp-fix
             (open-output-channel! filename :object state)
             (if chan
                 (pprogn (write-objects-to-channel obj-lst chan state)
                         (close-output-channel chan state)
                         (value :done))
               (er soft 'write-object-to-file
                   \"Could not open for writing: ~x0\"
                   filename)))))

  (local
   (defconst *nil.lisp*
     '((in-package \"ACL2\")
       (defthm bad nil :rule-classes nil))))

  (local
   (defconst *nil.cert*
     '((IN-PACKAGE \"ACL2\")
       \"ACL2 Version 3.1\"
       :BEGIN-PORTCULLIS-CMDS
       :END-PORTCULLIS-CMDS
       NIL
       ((\"/home/peterd/test/nil.lisp\" \"nil\" \"nil\"
         ((:SKIPPED-PROOFSP) (:AXIOMSP) (:TTAGS)) . 134094174))
       62589544
       )))

  (local
   (make-event (er-progn
                (write-objects-to-file *nil.lisp* \"nil.lisp\" state)
                (write-objects-to-file *nil.cert* \"nil.cert\" state)
                (value '(value-triple :invisible)))))

  (local (include-book
          \"nil\" :load-compiled-file nil))

  (defthm bad nil :rule-classes nil)
 })")

(defxdoc open-trace-file
  :parents (trace)
  :short "Redirect trace output to a file"
  :long "@({
  Example:
  (open-trace-file \"foo\") ; trace output will go to file foo

  General Form:
  (open-trace-file filename) ; trace output will go to file filename
 })

 <p>Output from @(tsee trace$) normally goes to the screen, i.e., @(tsee
 standard-co).  But it can be redirected to a file as shown above.  See @(see
 close-trace-file) for how to send trace output back to the screen.</p>")

(defxdoc or
  :parents (basics acl2-built-ins)
  :short "Disjunction"
  :long "<p>@('Or') is the macro for disjunctions.  @('Or') takes any number of
 arguments and returns the first that is non-@('nil'), or @('nil') if there is
 no non-@('nil') element.</p>

 <p>(Note: If you are seeking documentation for the @(':or') hint, see @(see
 hints).)</p>

 <p>In the ACL2 logic, the macroexpansion of @('(or x y)') is an @('IF') term
 that appears to cause @('x') to be evaluated twice:</p>

 @({
  ACL2 !>:trans (or x y)

  (IF X X Y)

  => *

  ACL2 !>
 })

 <p>If @('x') were replaced by an expression whose evaluation takes a long
 time, then such an expansion would be inefficient.  However, don't be fooled:
 you can expect Common Lisp implementations to avoid this problem, say by
 generating a new variable, for example:</p>

 @({
  ACL2 !>:q ; Exit the ACL2 loop and go into raw Common Lisp

  Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
  ACL2>(macroexpand '(or x y))

  (LET ((#:G5374 X)) (IF #:G5374 #:G5374 Y))
  T

  ACL2>
 })

 <p>@('Or') is a Common Lisp macro.  See any Common Lisp documentation for more
 information.</p>

 @(def or)
 @(def or-macro)")

(defxdoc ordinals
  :parents (miscellaneous)
  :short "Ordinals in ACL2"
  :long "<p>Ordinals are used in ACL2 for proving termination in the admission
 of recursive function definitions.  For a proof that the ACL2 ordinals are
 well-founded, see @(see proof-of-well-foundedness).</p>

 <p>The representation of ordinals changed in ACL2 Version_2.8, and is due to
 Pete Manolios and Daron Vroon.  They have also defined algorithms for ordinal
 arithmetic, created a library of theorems to reason about ordinal arithmetic,
 and written the rest of this documentation in order to explain this change.
 We thank them for their efforts.  Although they have provided the
 implementation and even modified the community books as needed, we have looked
 over their work and are maintaining it (and this documentation); if there are
 any bugs, they should be considered ours (Matt Kaufmann and J Moore).</p>

 <p>A book is included for compatibility with the representation before
 Version_2.8.  For books that contain events relying on the previous ordinal
 implementation, insert the following lines before the first such event:</p>

 @({
  (include-book \"ordinals/e0-ordinal\" :dir :system)
  (set-well-founded-relation e0-ord-<)
 })

 <p>The new ordinal representation is based on a slightly different version of
 Cantor Normal Form than that used by the old ordinals.  An advantage of the
 new representation is that it is exponentially more succinct than the old
 representation.</p>

 <p>While pre-Version_2.8 ACL2 versions provided built-in functions for
 checking if an object is an ordinal and for comparing two ordinals, they did
 not provide support for reasoning about and constructing ordinals.  The
 community books directory @('books/ordinals') provides such support.  First,
 it provides efficient algorithms for ordinal arithmetic (including addition,
 subtraction, multiplication, and exponentiation).  The algorithms and their
 complexity are described in the following paper.</p>

 @({
  Manolios, Panagiotis & Vroon, Daron.
  Algorithms for ordinal arithmetic.
  Baader, Franz (ed),
  19th International Conference on Automated Deduction--CADE-19.
  Pages 243-257 of LNAI, vol. 2741.  Springer-Verlag.
 })

 <p>Second, the algorithms are mechanically verified and libraries of theorems
 which can be used to automate reasoning involving the ordinals are provided.
 For details, see the following paper.</p>

 <code>
 Manolios, Panagiotis &amp; Vroon, Daron.
 Ordinal arithmetic in ACL2.
 Kaufmann, Matt, &amp; Moore, J Strother (eds).
 Fourth International Workshop on the ACL2 Theorem
 Prover and Its Applications (ACL2-2003),
 July, 2003.
 See <a href='http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/'>http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/</a>.
 </code>

 <p>We now describe aspects of the above mentioned books in more detail.</p>

 <p>The new ordering function is @(tsee o<) and the new ordinal recognizer is
 @(tsee o-p).  See also @(tsee natp), @(tsee posp), @(tsee o<=), @(tsee o>),
 @(tsee o>=), @(tsee o-first-expt), @(tsee o-first-coeff), @(tsee o-rst),
 @(tsee make-ord), @(tsee o-finp), and @(tsee o-infp).</p>

 <p>The old ordinals were based on the following formulation of Cantor Normal
 Form:</p>

 <p>For any ordinal, @('a < epsilon-0'), there exist natural numbers @('p') and
 @('n'), and ordinals @('a1 >= a2 >= ... >= an > 0') such that @('a > a1') and
 @('a = w^(a1) + w^(a2) + ... + w^(an) + p').</p>

 <p>Thus, a predicate recognizing ACL2's old ordinals is given by the following
 definition.</p>

 @({
  (defun e0-ordinalp (x)
    (if (consp x)
        (and (e0-ordinalp (car x))
             (not (equal (car x) 0))
             (e0-ordinalp (cdr x))
             (or (atom (cdr x))
                 (not (e0-ord-< (car x) (cadr x)))))
      (and (integerp x)
           (>= x 0))))
 })

 <p>The new representation is based on a corollary to the above theorem, which
 we get by the left distributive property of ordinal multiplication over
 ordinal addition. Thus, @('w^a + w^a = (w^a)2'), @('w^a + w^a + w^a = (w^a)3')
 and so forth. The corollary is as follows:</p>

 <p>For any ordinal, @('a < epsilon-0'), there exist natural numbers @('p') and
 @('n'), positive integers @('x1, x2, ..., xn') and ordinals @('a1 > a2 > ... >
 an > 0') such that @('a > a1') and @('a = w^(a1)x1 + w^(a2)x2 + ... + w^(an)xn
 + p').</p>

 <p>Instead of representing an ordinal as a list of non-increasing ordinals, we
 represent it as a list of exponent-coefficient pairs, such that the exponents
 are strictly decreasing (see @(see o-p)).  Note that this representation is
 exponentially more efficient than the old representation.</p>

 <p>The ordinal arithmetic functions: @('o+'), @('o-'), @('o*'), and @('o^')
 are defined in the ordinals library (in the community books directory
 @('books/ordinals')). To use them, include the book
 @('ordinals-without-arithmetic') or @('ordinals'), depending on whether you
 want the arithmetic books included or not (@('ordinals') includes community
 book @('books/arithmetic/top-with-meta')). To use the old ordinals, include
 the book @('e0-ordinal') and run the command @('(set-well-founded-relation
 e0-ord-<)')</p>

 <p>The community book @(see arithmetic/natp-posp) is a book for reasoning
 about @('posp') and @('natp').  We recommend using this book if you have to
 reason about @('posp') and @('natp').  It is included in community book
 @('books/arithmetic/top'), which is included in community book
 @('books/arithmetic/top-with-meta'), which is included in community book
 @('books/ordinals/ordinals').</p>

 <p>If you have a good reason to use the old definitions of the ordinals (e.g.,
 because of legacy code and theorems), then we provide a convenient way to do
 this.  The book @('ordinal-isomorphism') proves that the new ordinals are
 order-isomorphic to the old ordinals and thus theorems proved in one context
 can be directly transferred to the other.  For an example of how to do this,
 look at the book @('defmul') in the community books directory
 @('books/workshops/2000/ruiz/multiset').</p>

 <p>The ordinals books have been used to prove non-trivial theorems.  For a
 good example, see the books in the community books directory
 @('books/workshops/2003/sustik/support'), where Matyas Sustik proves Dickson's
 lemma.</p>

 <p>Finally, many termination proofs can be carried out with weaker orderings
 than the ordinals up to @('epsilon-0').  For example, many inductive theorem
 provers only know that the lexicographic ordering on natural numbers is
 well-founded.  The book @('lexicographic-ordering') contains a definition of
 such an ordering @('l<') whose arguments are either a list of natural numbers,
 or a natural number.  In the book we prove that @('l<') is well-founded (that
 is, we prove a @(':well-founded-relation') @(tsee defthm) and provide a macro
 @('llist') to simplify the generation of measure functions.  We also show how
 to use @('l<') to prove that the famous Ackermann function terminates.
 Finally, since @('l<') does something reasonable with natural numbers, it gets
 along with @(tsee acl2-count), the default measure chosen by ACL2.</p>")

(defxdoc otf-flg
  :parents (defthm thm xargs)
  :short "Allow more than one initial subgoal to be pushed for induction"
  :long "<p>The value of this flag is normally @('nil').  If you want to
 prevent the theorem prover from abandoning its initial work upon pushing the
 second subgoal, set @(':otf-flg') to @('t').</p>

 <p>Suppose you submit a conjecture to the theorem prover and the system splits
 it up into many subgoals.  Any subgoal not proved by other methods is
 eventually set aside for an attempted induction proof.  But upon setting aside
 the second such subgoal, the system chickens out and decides that rather than
 prove n&gt;1 subgoals inductively, it will abandon its initial work and
 attempt induction on the originally submitted conjecture.  The @(':otf-flg')
 (Onward Thru the Fog) allows you to override this chickening out. When
 @(':otf-flg') is @('t'), the system will push all the initial subgoals and
 proceed to try to prove each, independently, by induction.</p>

 <p>Even when you don't expect induction to be used or to succeed, setting the
 @(':otf-flg') is a good way to force the system to generate and display all
 the initial subgoals.</p>

 <p>For @(tsee defthm) and @(tsee thm), @(':otf-flg') is a keyword argument
 that is a peer to @(':')@(tsee rule-classes) and @(':')@(tsee hints).  It may
 be supplied as in the following examples; also see @(see defthm).</p>

 @({
  (thm (my-predicate x y) :rule-classes nil :otf-flg t)

  (defthm append-assoc
    (equal (append (append x y) z)
           (append x (append y z)))
    :hints ((\"Goal\" :induct t))
    :otf-flg t)
 })

 <p>The @(':otf-flg') may be supplied to @(tsee defun) via the @(tsee xargs)
 declare option.  When you supply an @(':otf-flg') hint to @('defun'), the flag
 is effective for the termination proofs and the guard proofs, if any.</p>")

(defxdoc output-to-file
  :parents (io)
  :short "Redirecting output to a file"
  :long "<p>For a general discussion of ACL2 input/output and of the ACL2
 read-eval-print loop, see @(see io) and see @(see ld) (respectively).  Here we
 use an example to illustrate how to use some of the options provided by
 @('ld') to redirect ACL2 output to a file, other than the printing of the
 prompt (which continues to go to the terminal).</p>

 <p>There are two @('ld') specials that control output from the @('ld')
 command: @(tsee proofs-co) for proof output and @(tsee standard-co) for other
 output.  The following example shows how to use these to redirect output to a
 file @('\"tmp.out\"').  The following command opens a character output channel
 to the file @('\"tmp.out\"') and redirects proof output to that channel, i.e.,
 to file @('\"tmp.out\"').</p>

 @({
  (mv-let (chan state)
          (open-output-channel \"tmp.out\" :character state)
          (set-proofs-co chan state))
 })

 <p>Next, we redirect standard output to that same channel.</p>

 @({
  (set-standard-co (proofs-co state) state)
 })

 <p>Now we can load an input file, in this case file @('\"tmp.lisp\"'), and
 output will be redirected to file @('\"tmp.out\"').  (The use of
 @(':ld-pre-eval-print t') is optional; see @(see ld).)</p>

 @({
  (ld \"tmp.lisp\" :ld-pre-eval-print t)
 })

 <p>Having completed our load operation, we restore both proof output and
 standard output to the terminal, as follows.</p>

 @({
  (set-standard-co *standard-co* state)
  (close-output-channel (proofs-co state) state)
  (set-proofs-co *standard-co* state)
 })

 <p>The following variant of the above example shows how to redirect output as
 above except without changing the global settings of the two @(tsee ld)
 specials, @(tsee proofs-co) and @(tsee standard-co).  This approach uses a
 notion of ``global variables'' stored in the ACL2 @(see state); see @(see
 assign) and see @(see @).</p>

 @({
  (mv-let (chan state)
          (open-output-channel \"tmp.out\" :character state)
          (assign tmp-channel chan))
  (ld \"tmp.lisp\" :ld-pre-eval-print t
                 :proofs-co (@ tmp-channel)
                 :standard-co (@ tmp-channel))
  (close-output-channel (@ tmp-channel) state)
 })")

(defxdoc override-hints
  :parents (hints)
  :short "A list of hints given priority in every proof attempt"
  :long "<p>This is an advanced feature, originally implemented to help system
 designers to create ``modes'' that control the way hints are supplied to the
 theorem prover.  Please see @(see default-hints) for the much more usual way
 to install hints that may be applied by default.</p>

 @({
  Examples:
  ACL2 !>(override-hints (w state))
  ((computed-hint-1 clause keyword-alist processor)
   (computed-hint-2 clause keyword-alist stable-under-simplificationp))
 })

 <p>@('Override-hints') returns a list of computed hints (see @(see
 computed-hints)) which, unlike other computed hints, may mention the variable
 @('KEYWORD-ALIST').</p>

 <p>Before reading further, please see @(see hints-and-the-waterfall) to review
 the basics of how @(see hints) are applied during a proof.  In particular, we
 assume familiarity with the notion of selecting a hint to be applied to the
 current goal.  If there are override-hints, that hint selection is tentative,
 because if it reduced to @('nil') after the application of override-hints,
 then that hint will be skipped and the attempt will continue for selecting an
 applicable hint.  (Craft your override-hints so that @(':no-op t') is returned
 in such cases instead of @('nil'), if you don't want the hint to be skipped.)
 But we must explain what is meant by ``the application of override-hints'',
 and we do that now.</p>

 <p>Suppose that there are override-hints when a hint is selected for the
 current goal.  That selected hint is a keyword-alist, which is an alternating
 list of hint keywords and their values, whose source is either an explicit
 hint @('(goal-name :key1 val1 ... :keyn valn)') where the @(':keyi') are
 allowed to be custom hint keywords (which are expanded away; see @(see
 custom-keyword-hints)), or else is the non-@('nil') keyword-alist produced by
 evaluating a computed hint.  Then the override-hints are applied to that
 keyword-alist as follows, one at a time, in order of their occurrence in the
 list of override-hints (as determined by the use of @(tsee set-override-hints)
 and @(tsee add-override-hints)).  The first override-hint is evaluated, in the
 usual manner of evaluating computed hints but with the variable
 @('KEYWORD-ALIST') bound to the above keyword-alist.  That evaluation produces
 a result that should also be a keyword-alist, or else an error occurs.  Any
 custom keyword hints are then eliminated from that keyword-alist.  The
 resulting keyword-alist must not contain the @(':ERROR') hint keyword and must
 not start with the @(':COMPUTED-HINT-REPLACEMENT') keyword; otherwise an error
 occurs.  With @('KEYWORD-ALIST') bound to this result, the second
 override-hint is similarly evaluated.  This process continues, and the
 keyword-alist returned by the final override-hint is the one used when
 processing the goal at hand.  Except: If that keyword-alist is @('nil'), then
 the next hint among the pending hints is tentatively selected and the process
 repeats, applying each override hint to that new tentative selection.  Of
 course we might obtain @('nil') again, in which case we tentatively select the
 next pending hint; and so on.</p>

 <p>If finally no hint is selected for the current goal, then
 @('KEYWORD-ALIST') is bound to @('nil') and the override-hints are applied as
 described above.  But note that this final step is skipped if hint selection
 is being performed because @('stable-under-simplificationp') has just become
 true, rather than at the top of the waterfall.  (Otherwise the override-hints
 could easily keep firing uselessly yet putting us back at the top of the
 waterfall, with no change to the given goal, resulting in an infinite
 loop.)</p>

 <p>As mentioned above, the @(':COMPUTED-HINT-REPLACEMENT') keyword is illegal
 for the value of an override-hint.  But a selected hint may be a computed hint
 that evaluates to a keyword-alist beginning with prefix
 @(':COMPUTED-HINT-REPLACEMENT val').  What value does ACL2 return for such a
 computed hint in the presence of override-hints?  First, this prefix is
 stripped off before passing the resulting keyword-alist to the override-hints
 as described above.  If the result of applying override-hints to that
 keyword-alist is not @('nil'), then the prefix is put back on the front of
 that resulting keyword-alist after doing internal processing of the hint,
 including expansion of any custom keyword hints.  Otherwise, the application
 of override-hints to the computed hint is @('nil'), so this hint is not
 selected after all.</p>

 <p><b>WARNING</b>: Unlike ordinary computed hints, a value of @('nil') for an
 override-hint is not ignored.  That is: When an ordinary computed hint
 evaluates to @('nil'), it is deemed not to apply, and the next available hint
 is consulted.  But when an override-hint is evaluated, the result is always
 supplied for the next binding of the variable @('KEYWORD-ALIST'), even if that
 result is @('nil').  If you want an override-hint to be a no-op, return as the
 expression the variable @('KEYWORD-ALIST') rather than an expression that
 evaluates to @('nil').</p>

 <p>This feature can be used in order to implement a form of additive hints.
 Suppose for example that you want a hint that turns off generalization.  A
 simple but inadequate solution is:</p>

 @({
  (add-default-hints '((quote (:do-not '(generalize)))))
 })

 <p>The problem is that if there is any explicit hint supplied for a given
 goal, then it will be the one selected, and the above will be ignored.  But
 suppose that the explicit hint supplied is of the form @('(\"Subgoal x.y\"
 :do-not '(fertilize))').  What we would really want in this case is to
 generate the hint for the indicated subgoal that binds @(':do-not') to a list
 indicating that both fertilization _and_ generalization are disabled for that
 goal.  A solution is to merge, for example as follows.  (The use of @(tsee
 prog2$) and @(tsee cw) is of course optional, included here to provide debug
 printing.)</p>

 @({
  (add-override-hints
   '((let* ((tmp (assoc-keyword :do-not KEYWORD-ALIST))
            (new-keyword-alist
             (cond (tmp (list* :do-not
                               `(cons 'generalize ,(cadr tmp))
                               (remove-keyword :do-not KEYWORD-ALIST)))
                   (t (list* :do-not ''(generalize) KEYWORD-ALIST)))))
       (prog2$ (cw \"New: ~x0~|\" new-keyword-alist)
               new-keyword-alist))))
 })

 <p>REMARKS</p>

 <p>(1) The utilities @(tsee add-override-hints), @(tsee add-override-hints!),
 @(tsee set-override-hints), @(tsee set-override-hints!), @(tsee
 remove-override-hints), and @(tsee remove-override-hints!) are also available,
 in complete analogy to their default-hints versions.</p>

 <p>(2) The community book @('hints/basic-tests.lisp') illustrates the use of
 override-hints and illuminates a number of corner cases; search in that file
 for ``Test override-hints.''</p>

 <p>(3) The community book @('hints/merge-hint.lisp') provides support for
 merging hints that might be useful for writers of override-hint expressions
 (see the examples at the end of that file).</p>

 <p>(4) Override-hints are used in the processing of @(':BACKTRACK') hints (see
 @(see hints)).</p>")

(defxdoc |On the Naming of Subgoals|
  :parents (|Pages Written Especially for the Tours|)
  :short "On the Naming of Subgoals"
  :long "<p>@('Subgoal *1/2') is the <b>induction step</b> from the scheme,
 obtained by instantiating the scheme with our conjecture.</p>

 <p>We number the cases ``backward'', so this is case ``2'' of the proof of
 ``*1''.  We number them backward so you can look at a subgoal number and get
 an estimate for how close you are to the end.</p>")

(defxdoc |Other Requirements|
  :parents (|Pages Written Especially for the Tours|)
  :short "Other Requirements"
  :long "<p><see topic='@(url |The End of the Flying Tour|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>ACL2 is distributed on the Web without fee.</p>

 <p>There is a <b>license</b> agreement based on the 3-clause BSD license.  See
 the file LICENSE in the ACL2 distribution.</p>

 <p>ACL2 currently runs on <b>Unix</b>, <b>Linux</b>, <b>Windows</b>, and
 <b>Macintosh OS X</b> operating systems.</p>

 <p>It can generally be built in any of the following Common Lisps:</p>

 <code>
   * <b>Allegro Common Lisp</b>,
   * <b>CCL</b> (formerly OpenMCL)
   * <b>CMU Common Lisp</b>,
   * <b>GCL</b> (Gnu Common Lisp),
   * <b>LispWorks</b>, and
   * <b>SBCL</b> (Steel Bank Common Lisp)
 </code>

 <p><see topic='@(url |The End of the Flying Tour|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |Overview of the Expansion of ENDP in the Base Case|
  :parents (|Pages Written Especially for the Tours|)
  :short "Overview of the Expansion of ENDP in the Base Case"
  :long "<p>@('Subgoal *1/1') is the <b>Base Case</b> of our induction.  It
 simplifies to @('Subgoal *1/1'') by expanding the <b>ENDP</b> term in the
 hypothesis, just as we saw in the earlier proof of @('Subgoal *1/2').</p>")

(defxdoc |Overview of the Expansion of ENDP in the Induction Step|
  :parents (|Pages Written Especially for the Tours|)
  :short "Overview of the Expansion of ENDP in the Induction Step"
  :long "<p>In this message the system is saying that @('Subgoal *1/2') has
 been rewritten to the @('Subgoal *1/2''), by expanding the definition of
 <b>endp</b>.  This is an example of <b>simplification</b>, one of the main
 proof techniques used by the theorem prover.</p>

 <p>Click <see topic='@(url
 |The Expansion of ENDP in the Induction Step (Step 0)|)'>here</see> if you
 would like to step through the simplification of @('Subgoal *1/2').</p>")

(defxdoc |Overview of the Final Simplification in the Base Case|
  :parents (|Pages Written Especially for the Tours|)
  :short "Overview of the Final Simplification in the Base Case"
  :long "<p>The <b>But</b> is our signal that the goal is proved.</p>

 <p>Click <see topic='@(url
 |The Final Simplification in the Base Case (Step 0)|)'>here</see> to step
 through the proof.  It is very simple.</p>")

(defxdoc |Overview of the Proof of a Trivial Consequence|
  :parents (|Pages Written Especially for the Tours|)
  :short "Overview of the Proof of a Trivial Consequence"
  :long "<p><see topic='@(url |The End of the Walking Tour|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p><img src='res/tours/green-line.gif'></img></p>

 <code>
 ACL2 !&gt;<b>(defthm trivial-consequence</b>
          <b>(equal (app (app (app (app x1 x2) (app x3 x4)) (app x5 x6)) x7)</b>
                 <b>(app x1 (app (app x2 x3) (app (app x4 x5) (app x6 x7))))))</b>

 <see topic='@(url |The WARNING about the Trivial Consequence|)'>ACL2 Warning</see> [Subsume] in ( DEFTHM TRIVIAL-CONSEQUENCE ...):  The previously
 added rule ASSOCIATIVITY-OF-APP subsumes the newly proposed :REWRITE
 rule TRIVIAL-CONSEQUENCE, in the sense that the old rule rewrites a
 more general target.  Because the new rule will be tried first, it
 may nonetheless find application.

 By the simple :rewrite rule <see topic='@(url |The First Application of the Associativity Rule|)'>ASSOCIATIVITY-OF-APP</see> we reduce the conjecture
 to

 Goal'
 (EQUAL (APP X1
             (APP X2
                  (APP X3 (APP X4 (APP X5 (APP X6 X7))))))
        (APP X1
             (APP X2
                  (APP X3 (APP X4 (APP X5 (APP X6 X7))))))).

 But we reduce the conjecture to T, by primitive type reasoning.

 Q.E.D.

 Summary
 Form:  ( DEFTHM TRIVIAL-CONSEQUENCE ...)
 Rules: ((:REWRITE ASSOCIATIVITY-OF-APP)
         (:FAKE-RUNE-FOR-TYPE-SET NIL))
 Warnings:  <see topic='@(url |The Summary of the Proof of the Trivial Consequence|)'>Subsume</see>
 Time:  0.20 seconds (prove: 0.02, print: 0.00, other: 0.18)
  TRIVIAL-CONSEQUENCE
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>You might explore the links before moving on.</p>

 <p><see topic='@(url |The End of the Walking Tour|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |Overview of the Simplification of the Base Case to T|
  :parents (|Pages Written Especially for the Tours|)
  :short "Overview of the Simplification of the Base Case to T"
  :long "<p><see topic='@(url
 |The End of the Proof of the Associativity of App|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <code>
 <see topic='@(url |Overview of the Expansion of ENDP in the Base Case|)'>Subgoal *1/1</see>
 (IMPLIES (ENDP A)
          (EQUAL (APP (APP A B) C)
                 (APP A (APP B C)))).

 By the simple :definition ENDP we reduce the conjecture to

 Subgoal *1/1'
 (IMPLIES (NOT (CONSP A))
          (EQUAL (APP (APP A B) C)
                 (APP A (APP B C)))).

 <see topic='@(url |Overview of the Final Simplification in the Base Case|)'>But</see> simplification reduces this to T, using the :definition APP and
 primitive type reasoning.

 </code>

 <p><see topic='@(url |The End of the Proof of the Associativity of App|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |Overview of the Simplification of the Induction Conclusion|
  :parents (|Pages Written Especially for the Tours|)
  :short "Overview of the Simplification of the Induction Conclusion"
  :long "<p>In this message the system is saying that @('Subgoal *1/2'') has
 been rewritten to T using the rules noted.  The word ``<b>But</b>'' at the
 beginning of the sentence is a signal that the goal has been proved.</p>

 <p>Click <see topic='@(url
 |The Simplification of the Induction Conclusion (Step 0)|)'>here</see> to step
 through the proof of @('Subgoal *1/2'').</p>")

(defxdoc |Overview of the Simplification of the Induction Step to T|
  :parents (|Pages Written Especially for the Tours|)
  :short "Overview of the Simplification of the Induction Step to T"
  :long "<p><see topic='@(url
 |Overview of the Simplification of the Base Case to T|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <code>
 <see topic='@(url |On the Naming of Subgoals|)'>Subgoal *1/2</see>
 (IMPLIES (AND (NOT (ENDP A))
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (APP (APP A B) C)
                 (APP A (APP B C)))).

 By the simple :definition <see topic='@(url |Overview of the Expansion of ENDP in the Induction Step|)'>ENDP</see> we reduce the conjecture to

 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (APP (APP A B) C)
                 (APP A (APP B C)))).

 <see topic='@(url |Overview of the Simplification of the Induction Conclusion|)'>But</see> simplification reduces this to T, using the :definition APP, the
 :rewrite rules CDR-CONS and CAR-CONS and primitive type reasoning.
 </code>

 <p><see topic='@(url
 |Overview of the Simplification of the Base Case to T|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc p!
  :parents (ld)
  :short "To pop up (at least) one level of ACL2's command loop"
  :long "<p>Logically speaking, @('(p!) = nil').  If you are already at the top
 level of the ACL2 command loop, rather than being in a subsidiary call of
 @(tsee ld), then the keyword then a call of @('(p!)') returns @('nil') and has
 no other effect.</p>

 <p>Otherwise, @('(p!)') is evaluated inside a call of @(tsee ld) that was made
 inside ACL2's command loop.  In that case, the current computation is aborted
 and treating as causing an error, and control returns to the superior call of
 @('ld').</p>

 <p>Here is a more detailed description of the effect of @('(p!)') when not at
 the top level of the ACL2 command loop.  The current call of @('LD') is
 treated as though @('ld-error-action') is @(':RETURN!') (the default; here we
 ignore the case @('(:exit N)')) and hence immediately returns control to the
 superior call of @(tsee ld).  If all calls of @(tsee ld) were made with the
 default @('ld-error-action') of @(':RETURN!'), then all superior calls of
 @('ld') will then complete until you are back at top level of the ACL2 loop.
 For more information, see @(see ld-error-action).</p>

 <p>If you are at an ACL2 prompt (as opposed to a raw Lisp break), then you may
 type @(':p!') in place of @('(p!)'); see @(see keyword-commands).</p>")

(defxdoc package-reincarnation-import-restrictions
  :parents (packages)
  :short "Re-defining undone @(tsee defpkg)s"
  :long "<p>Suppose @('(defpkg \"pkg\" imports)') is the most recently executed
 successful definition of @('\"pkg\"') in this ACL2 session and that it has
 since been undone, as by @(':')@(tsee ubt).  Any future attempt in this
 session to define @('\"pkg\"') as a package must specify an identical imports
 list.</p>

 <p>The restriction stems from the need to implement the reinstallation of
 saved logical @(see world)s as in error recovery and the @(':')@(tsee oops)
 @(see command).  Suppose that the new @(tsee defpkg) attempts to import some
 symbol, @('a::sym'), not imported by the previous definition of @('\"pkg\"').
 Because it was not imported in the original package, the symbol @('pkg::sym'),
 different from @('a::sym'), may well have been created and may well be used in
 some saved @(see world)s.  Those saved @(see world)s are Common Lisp objects
 being held for you ``behind the scenes.''  In order to import @('a::sym') into
 @('\"pkg\"') now we would have to unintern @('pkg::sym'), rendering those
 saved @(see world)s ill-formed.  It is because of saved @(see world)s that we
 do not actually clear out a package when it is undone.</p>

 <p>At one point we thought it was sound to allow the new @(tsee defpkg) to
 import a subset of the old.  But that is incorrect.  Suppose the old
 definition of @('\"pkg\"') imported @('a::sym') but the new one does not.
 Suppose we allowed that and implemented it simply by setting the imports of
 @('\"pkg\"') to the new subset.  Then consider the conjecture @('(eq a::sym
 pkg::sym)').  This ought not be a theorem because we did not import
 @('a::sym') into @('\"pkg\"').  But in fact in AKCL it is a theorem because
 @('pkg::sym') is read as @('a::sym') because of the old imports.</p>")

(defxdoc packages
  :parents (programming)
  :short "Collections of symbols that act as namespaces."

  :long "Packages are collections of symbols.  They can be used to avoid name
 conflicts when working on large ACL2 projects.

  See @(see working-with-packages) for the best practices in setting up and
  using packages.")

(defxdoc pairlis
  :parents (lists alists)
  :short "See @(see pairlis$)"
  :long "<p>The Common Lisp language allows its @('pairlis') function to
 construct an alist in any order!  So we have to define our own version: See
 @(see pairlis$).</p>")

(defxdoc pairlis$
  :parents (lists alists acl2-built-ins)
  :short "Zipper together two lists"
  :long "<p>The Common Lisp language allows its @(tsee pairlis) function to
 construct an alist in any order!  So we have to define our own version,
 @('pairlis$').  It returns the list of pairs obtained by @(tsee cons)ing
 together successive respective members of the given lists until the first list
 runs out.  (Hence in particular, if the second argument is @('nil') then each
 element of the first argument is paired with @('nil').)</p>

 <p>The @(see guard) for @('pairlis$') requires that its arguments are true
 lists.</p>

 @(def pairlis$)")

(defxdoc pand
  :parents (parallel-programming acl2-built-ins)
  :short "Parallel, Boolean version of @(tsee and)"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism), and see @(see parallel-programming), which has a disclaimer.</p>

 @({
  Example Forms:
  (pand (subsetp-equal x y)
        (subsetp-equal y x))

  (pand (declare
         (granularity
          (and (> (length x) 500)
               (> (length y) 500))))
         (subsetp-equal x y)
         (subsetp-equal y x))
 })

 @({
  General Form:
  (pand (declare (granularity expr)) ; optional granularity declaration
        arg1 ... argN)
 })

 <p>where @('N >= 0') and each @('argi') and @('expr') are arbitrary terms.</p>

 <p>@('Pand') evaluates its arguments in parallel.  It returns a Boolean
 result: @('nil') if any argument evaluates to @('nil'), else @('t').  Note
 that @('pand') always returns a Boolean result, even though @('and') can
 return a non-@('nil') value other than @('t'), namely the value of its last
 argument.  (A moment's reflection will make it clear that in order for @(tsee
 por) to parallelize efficiently, it needs to return a Boolean value; so
 @('pand') returns a Boolean value for consistency with @(tsee por).)</p>

 <p>Another difference between @('pand') and @(tsee and) is that for a call of
 @('pand'), even if an argument evaluates to @('nil'), a subsequent argument
 may be evaluated.  Consider the following example (where @('cw') prints a
 string; see @(see cw)).</p>

 @({
  (defun bar ()
    (pand (equal (make-list 100000) nil) ; evaluates to nil
          (cw \"hello world~%\")))
 })

 <p>When @('(bar)') is evaluated, the above arguments of @('pand') can execute
 in parallel, causing ``@('hello world')'' to be printed to the terminal.  If
 we had used @('and') rather than @('pand'), then since @('(equal (make-list
 100000) nil)') evaluates to @('nil'), the above call of @(tsee cw) would be
 avoided and no such printing would take place.  Even with @('pand'), such
 printing <i>might</i> not take place, depending on resources, timing of thread
 creation, and whether or not parallel execution is enabled (see @(see
 set-parallel-execution)).</p>

 <p>Note that unlike the case for @(tsee and), the definition of @('pand') does
 not provide @('(consp x)') as a @(see guard) to @('(car x)') in the call of
 @('pand') below:</p>

 @({
  (defun h (x)
    (declare (xargs :guard t))
    (pand (consp x) (equal (car x) 'foo)))
 })

 <p>As a result, @(see guard) verification will fail for the above definition.
 If @('pand') were replaced by @('and'), then @(see guard) verification would
 succeed.</p>

 <p>See @(see parallelism-tutorial) for another example.  Also see @(see
 parallelism-at-the-top-level) for restrictions on evaluating parallelism
 primitives from within the ACL2 top-level loop.  Finally see @(see
 early-termination) to read how @('pand') can offer more efficiency than @(tsee
 and) by avoiding evaluation of some of its arguments.</p>")

(defxdoc parallel
  :parents (parallelism)
  :short "Evaluating forms in parallel"
  :long "<p>See @(see parallelism).</p>")

(defxdoc parallel-execution
  :parents (parallel-programming)
  :short "For ACL2(p): configure parallel execution"
  :long "<p>See @(see set-parallel-execution) for how to configure parallel
 execution for calls of @(tsee plet), @(tsee pargs), @(tsee pand), @(tsee
 por) (but not @(tsee spec-mv-let)).</p>")

(defxdoc parallel-programming

; The Disclaimer below may seem a bit surprising for spec-mv-let, since it was
; designed to handle certain special variables related to the waterfall.  Those
; are handled in make-closure-expr-with-acl2-bindings; but they are just a
; limited subset of those in the system, for example not including those
; supporting hons or memoization.

  :parents (parallelism)
  :short "Parallel programming in ACL2(p)"
  :long "<p>Here we document support for parallel programming in ACL2(p), an
 experimental extension of ACL2; also see @(see parallelism).</p>

 <p>One of ACL2's strengths lies in its ability to execute industrial models
 efficiently.  The ACL2 source code provides an experimental parallel execution
 capability that can increase the speed of explicit evaluation, including
 simulator runs using such models, and it can also decrease the time required
 for proofs that make heavy use of the evaluation of ground terms.</p>

 <p>The parallelism primitives are @(tsee plet), @(tsee pargs), @(tsee pand),
 @(tsee por), and @(tsee spec-mv-let).  @(tsee Pand) and @(tsee por) terminate
 early when an argument is found to evaluate to @('nil') or non-@('nil'),
 respectively, thus potentially improving on the efficiency of lazy evaluation.
 @(tsee Spec-mv-let) is a modification of @(tsee mv-let) that supports
 speculative and parallel execution.</p>

 <p>Of the above five parallelism primitives, all but @(tsee spec-mv-let) allow
 for limiting parallel execution (spawning of so-called ``threads'') depending
 on resource availability.  Specifically, the primitives allow specification of
 a size condition to control the @(see granularity) under which threads are
 allowed to spawn.  You can use such @(see granularity) declarations in
 recursively-defined functions to implement data-dependent parallelism in their
 execution.</p>

 <p>We recommend that in order to learn to use the parallelism primitives, you
 begin by reading examples: see @(see parallelism-tutorial).  That section will
 direct you to further documentation topics.</p>

 <p>In addition to providing parallel programming primitives, ACL2(p) also
 provides the ability to execute the main ACL2 proof process in parallel.  See
 @(see set-waterfall-parallelism) for further details.</p>

 <p><em>Disclaimer</em>.  The parallelism primitives have been designed for
 executing purely functional code, but some ACL2 functions do interesting
 things ``under the hood'' in order to achieve their effects.  For example,
 @(see hons) primitives such as @(tsee hons-wash) may not have the intended
 effect when executed under the parallelism primitives.</p>")

(defxdoc parallel-proof

; Parallelism blemish: write a few introductory words to "advertise" parallel
; proof in ACL2(p), perhaps by way of a very simple example.

  :parents (parallelism)
  :short "Parallel proof in ACL2(p)"
  :long "<p>Here we document support for parallel proof in ACL2(p), an
 experimental extension of ACL2; also see @(see parallelism), and for parallel
 programming in particular, see @(see parallel-programming).</p>")

(defxdoc parallel-pushing-of-subgoals-for-induction
  :parents (parallel-proof)
  :short "Consequences of how parallelized proofs of subgoals are pushed for induction"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 <p>The following discussion, concerning the naming of subgoals pushed for
 proof by induction and the timeliness of aborting when two or more goals are
 pushed for proof by induction, only applies when waterfall parallelism is
 enabled (see @(see set-waterfall-parallelism)).</p>

 <p>When two sibling subgoals (e.g. 4.5 and 4.6) both push goals to be proved
 by induction (e.g., 4.6 pushes *1 and 4.5 pushes *2), a name is assigned to
 the second pushed subgoal (e.g., *2) as if the first push hasn't happened
 (e.g., *2 is mistakenly called *1).  In such a case, we say what the name
 _could_ be.  The following non-theorem illustrates how this works.</p>

 @({
  (set-waterfall-parallelism :full)
  (thm (equal (append (car (cons x x)) y z) (append x x y)))
 })

 <p>There is another consequence of the way the parallelized waterfall pushes
 subgoals for proof by induction.  Without waterfall parallelism enabled, ACL2
 sometimes decides to abort instead of pushing a goal for later proof by
 induction, preferring instead to induct on the original conjecture.  But with
 waterfall parallelism enabled, the prover no longer necessarily immediately
 aborts to prove the original conjecture.  Suppose for example that sibling
 subgoals, Subgoal 4.6 and Subgoal 4.5, each push a subgoal for induction.  If
 the waterfall is performing the proof of each of these subgoals in parallel,
 the proof will no longer abort immediately after the second push occurs, that
 is at Subgoal 4.5.  As a result, the prover will continue through Subgoal 4.4,
 Subgoal 4.3, and beyond.  It is not until the results of combining the proof
 results of Subgoal 4.6 with the results from the remaining sibling subgoals
 (4.5, 4.4, and so on), that the proof attempt will abort and revert to prove
 the original conjecture by induction.  This example illustrates behavior that
 is rather like the case that @(':')@(tsee otf-flg) is @('t'), in the sense
 that the abort does not happen immediately, but also rather like the case that
 @(':')@(tsee otf-flg) is @('nil'), in the sense that the abort does occur
 before getting to Subgoal 3.</p>")

(defxdoc parallelism
  :parents (acl2)
  :short "Experimental extension for parallel execution and proofs"
  :long "<p>This documentation topic relates to an experimental extension of
 ACL2, ACL2(p), created initially by David L. Rager.  See @(see
 compiling-acl2p) for how to build an executable image that supports parallel
 execution.  Also see community books directory @('books/parallel/') for
 examples.  For a completely different sort of parallelism, at the system
 level, see @(see provisional-certification).</p>

 <p>IMPORTANT NOTE.  We hope and expect that every evaluation result is
 correctly computed by ACL2(p), and that every formula proved using ACL2(p) is
 a theorem of the ACL2 logic (and in fact is provable using ACL2).  However, we
 do not guarantee these properties.  Since ACL2(p) is intended to be an aid in
 efficient evaluation and proof development, we focus less on ironclad
 soundness and more on providing an efficient and working implementation.
 Nevertheless, if you encounter a case where ACL2(p) computes an incorrect
 result, or produces a proof where ACL2 fails to do so (and this failure is not
 discussed in @(see unsupported-waterfall-parallelism-features)), please notify
 the implementors.</p>

 <p>The ACL2 source code provides experimental parallel execution and proof
 capabilities.  For example, one of ACL2's strengths lies in its ability to
 simulate industrial models efficiently, and it can also decrease the time
 required for proofs about such models both by making use of parallel
 evaluation and by dispatching proof subgoals in parallel.</p>

 <p>While we aim to support Clozure Common Lisp (CCL), Steel Bank Common Lisp
 (SBCL), and Lispworks, SBCL and Lispworks both currently sometimes experience
 problems when evaluating the ACL2 proof process (the ``waterfall'') in
 parallel.  Therefore, CCL is the recommend Lisp for anyone that wants to use
 parallelism and isn't working on fixing those problems.</p>")

(defxdoc parallelism-at-the-top-level
  :parents (parallel-programming)
  :short "Parallel execution in the ACL2 top-level loop"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 <p>Calls of parallelism primitives made explicitly in the ACL2 top-level loop,
 as opposed to inside function bodies, will never cause parallel execution.
 Such calls will either execute with serial execution or will cause an error;
 see @(see set-parallel-execution).  For a way around this restriction, see
 @(see top-level).</p>

 <p>Consider for example the following call of @(tsee pargs) in the ACL2
 top-level loop.  Instead of executing @('pargs'), ACL2 macroexpands away this
 call, leaving us with serial execution of the arguments to the @(tsee cons)
 call, or else causes an error (see @(see set-parallel-execution)).  If there
 is no error, then</p>

 @({
  (pargs (cons (expensive-fn-1 4) (expensive-fn-2 5)))
 })

 <p>expands into:</p>

 @({
  (cons (expensive-fn-1 4) (expensive-fn-2 5))
 })

 <p>One trivial way to enable parallel execution of a form is to surround it
 with a call to macro @(see top-level).  Consider the following example.</p>

 @({
  (top-level (pargs (cons (expensive-fn-1 4) (expensive-fn-2 5))))
 })

 <p>Then in an executable image that supports parallel execution &mdash; see
 @(see compiling-acl2p) for instructions on how to build such an executable
 &mdash; @('(expensive-fn-1 4)') and @('(expensive-fn-2 5)') can evaluate in
 parallel.</p>

 <p>A second way to enable parallel execution of a form is to place it inside a
 function body.  For example, consider the following definition.</p>

 @({
  (defun foo (x y)
    (pargs (cons (expensive-fn-1 x) (expensive-fn-2 y))))
 })

 <p>Then in an executable image that supports parallel execution, submission of
 the form @('(foo 4 5)') can cause parallel execution of @('(expensive-fn-1
 4)') and @('(expensive-fn-2 5)').</p>

 <p>Note that @(see guard)s need not be verified in order to obtain @(see
 parallel) execution.  The only restrictions on parallel execution are to use
 an ACL2 executable supporting it, to avoid calling parallelism primitives
 directly in the top-level loop, to have sufficient resources (especially,
 threads) available, and to avoid explicitly disabling parallel execution (see
 @(see set-parallel-execution)).</p>")

(defxdoc parallelism-build
  :parents (parallelism)
  :short "Building an ACL2 executable with parallel execution enabled"
  :long "<p>See @(see compiling-acl2p).</p>")

(defxdoc parallelism-performance
  :parents (parallel-programming)
  :short "Performance issues for parallel execution"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 <p>See @(see granularity) for an important construct that limits the spawning
 of parallel computations, which can be important when a computation is too
 short-lived to warrant a separate thread.</p>

 <p>There are times in which parallelism provides no speedup because of garbage
 collection in the underlying Lisp implementation.  The following example
 illustrates this phenomenon.  If you change the @(tsee granularity)
 declaration so that the depth bound is 3, 4, or larger instead of 2, you may
 still find no speedup.  In all cases you may find that parallelism results in
 a significantly greater time spent in garbage collection.</p>

 @({
  (include-book \"finite-set-theory/osets/sets\" :dir :system)
  (defun set::pmergesort-exec (x depth)
      (declare (xargs :mode :program))
      (cond ((endp x) nil)
            ((endp (cdr x)) (set::insert (car x) nil))
            (t (mv-let (part1 part2)
                       (set::split-list x nil nil)
                       (pargs
                        (declare (granularity (< depth 2)))
                        (set::union (set::pmergesort-exec part1
                                                            (1+ depth))
                                     (set::pmergesort-exec part2
                                                            (1+ depth))))))))
  (defconst *x* (reverse (fromto 1 400000)))
  (time$ (length (set::pmergesort-exec *x* 0)))
  (set-parallel-execution nil)
  (time$ (length (set::pmergesort-exec *x* 0)))
 })")

(defxdoc parallelism-tutorial
  :parents (parallel-programming)
  :short "A tutorial on how to use the parallelism library."
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 <p>In this topic we introduce the ACL2 parallelism primitives using the
 example of a doubly-recursive Fibonacci function, whose basic definition is as
 follows.  See @(see parallelism) for a very high-level summary of the
 parallelism capability described here, and see @(see compiling-acl2p) for how
 to build an executable image that supports parallel execution.  Here, we
 assume that such an executable is being used.</p>

 <p><b>Serial Fibonacci</b></p>

 @({
  (defun fib (x)
    (declare (xargs :guard (natp x)))
    (cond ((or (zp x) (<= x 0)) 0)
          ((= x 1) 1)
          (t (+ (fib (- x 1)) (fib (- x 2))))))
 })

 <p><b>Introducing</b> @(tsee Pargs)</p>

 <p>A simple way to introduce parallelism into this function definition is to
 wrap the addition expression with a call of @(tsee pargs), and the arguments
 to the addition will be computed in parallel whenever resources are available.
 As a result, we end up with a very similar and thus intuitive function
 definition.  Note that we replaced @(tsee +) by @(tsee binary-+), since @(tsee
 pargs) expects a function call, not a macro call.</p>

 @({
  (defun pfib (x)
    (declare (xargs :guard (natp x)))
    (cond ((or (zp x) (<= x 0)) 0)
          ((= x 1) 1)
          (t (pargs (binary-+ (pfib (- x 1))
                              (pfib (- x 2)))))))
 })

 <p><b>Introducing the Granularity Problem</b></p>

 <p>After you submit the above two versions of the Fibonacci function, test
 them with the following forms.</p>

 @({
  (time$ (fib 10))
  (time$ (pfib 10))
 })

 <p>Now increase the argument by increments of 5 to 10 until you find your
 curiosity satisfied or your patience wearing thin.  You can interrupt
 evaluation if necessary and return to the ACL2 loop.  You will immediately
 notice that you have not increased execution speed, at least not by much, by
 introducing parallelism.</p>

 <p>First, consider the computation of @('(pfib 4)').  Assuming resources are
 available, @('(pfib 4)') will create a thread for computing @('(pfib 3)') and
 another thread for @('(pfib 2)').  It is easy to imagine that setting up each
 thread takes much longer than the entire computation of @('(fib 4)').</p>

 <p>Second, we must realize that if we have two threads available for computing
 @('(fib 10)'), then the evaluation of @('(fib 8)') will probably complete
 before the evaluation of @('(fib 9)').  Once @('(fib 8)') finishes,
 parallelism resources will become available for the next recursive call made
 on behalf of @('(fib 9)').  If for example that call is @('(fib 3)'), we will
 waste a lot of cycles just handing work to the thread that does this
 relatively small computation.  We need a way to ensure that parallelism
 resources are only used on problems of a \"large\" size.  Ensuring that only
 \"large\" problems are spawned is called the ``granularity problem.''</p>

 <p>In summary: We want to tell ACL2 that it can evaluate the arguments of
 @(tsee pargs) in parallel only when the parameter of @('pfib') is greater than
 some threshold.  Our tests using CCL have suggested that 27 is a reasonable
 threshold.</p>

 <p><b>Explicit Programming for the Granularity Problem</b></p>

 <p>One way to avoid the granularity problem is to duplicate code as
 follows.</p>

 @({
  (defun pfib (x)
    (declare (xargs :guard (natp x)))
    (cond ((or (zp x) (<= x 0)) 0)
          ((= x 1) 1)
          (t (if (> x 27) ; the granularity test
                 (pargs (binary-+ (pfib (- x 1))
                                  (pfib (- x 2))))
               (binary-+ (pfib (- x 1))
                         (pfib (- x 2)))))))
 })

 <p>Duplicating code is fundamentally a bad design principle, because it can
 double the work for future maintenance.  A ``granularity form'' is an
 expression</p>

 @({
  (declare (granularity <form>))
 })

 <p>that can allow threads to be spawned (without duplicating code) whenever
 the evaluation of @('<form>') results in a non-@('nil') value.  It may be
 placed inside any call of a parallelism primitive, in a position documented
 separately for each primitive.  Here is a definition of @('pfib') using this
 feature for a call of the parallelism primitive @(tsee pargs).</p>

 @({
  (defun pfib (x)
    (declare (xargs :guard (natp x)))
    (cond ((or (zp x) (<= x 0)) 0)
          ((= x 1) 1)
          (t (pargs
              (declare (granularity (> x 27)))
              (binary-+ (pfib (- x 1))
                        (pfib (- x 2)))))))
 })

 <p>Test each version as follows (or substitute your own natural number for
 33).</p>

 @({
    (time$ (fib 33))
    (time$ (pfib 33))
 })

 <p><b>Another Granularity Issue Related to Thread Limitations</b></p>

 <p>Our implementation of parallelism primitives has the property that once a
 thread is assigned a computation, that assignment stays in effect until the
 computation is complete.  In particular, if a thread encounters a parallelism
 primitive that spawns child threads, the parent thread stays assigned, waiting
 until the child computations complete before it can continue its own
 computation.  In the meantime, the parent thread reduces the number of
 additional threads that Lisp can provide by 1, rather than being reassigned to
 do other work.</p>

 <p>How can this lack of reassignment affect the user?  Consider, for example,
 the application of a recursive function to a long list.  Imagine that this
 function is written so that the body contains a recursive call, for example as
 @('(pargs (process (car x)) (recur (cdr x)))').  Each such @(tsee pargs) call
 that spawns child work must wait for its children, one of which is the work of
 evaluating @('(recur (cdr x))'), to complete.  There is an ACL2 limit on how
 much pending work can be in the system, limiting the number of @(tsee pargs)
 calls that can result in parallel execution.  For example, if the ACL2 limit
 is k and each call of @(tsee pargs) actually spawns threads for evaluating its
 arguments, then after k @('cdr')s there will be no further parallel
 execution.</p>

 <p>Possible solutions may include reworking of algorithms (for example to be
 tree-based rather than list-based) or using appropriate granularity forms.  We
 hope that future implementations will allow thread ``re-deployment'' in order
 to mitigate this problem.  This problem applies to @(tsee plet), @(tsee
 pargs), @(tsee pand), @(tsee por), and @(tsee spec-mv-let).</p>

 <p><b>Introducing</b> @(tsee Plet)</p>

 <p>We can use a @(tsee let) binding to compute the recursive calls of @('fib')
 and then add the bound variables together, as follows.</p>

 @({
  (defun fib (x)
    (declare (xargs :guard (natp x)))
    (cond ((or (zp x) (<= x 0)) 0)
          ((= x 1) 1)
          (t (let ((a (fib (- x 1)))
                   (b (fib (- x 2))))
               (+ a b)))))
 })

 <p>By using the parallelism primitive @(tsee plet), we can introduce
 parallelism much as we did using @(tsee pargs), with an optional granularity
 form, as follows.</p>

 @({
  (defun pfib (x)
    (declare (xargs :guard (natp x)))
    (cond ((or (zp x) (<= x 0)) 0)
          ((= x 1) 1)
          (t (plet
              (declare (granularity (> x 27)))
              ((a (pfib (- x 1)))
               (b (pfib (- x 2))))
              (+ a b)))))
 })

 <p>Notice that this time, we were able to use @('+') rather than being forced
 to use @('binary-+').  Unlike @(tsee pargs), which expects a function call
 (not a macro call), @(tsee plet) allows macros at the top level of its
 body.</p>

 <p><b>Introducing</b> @(tsee Pand) (By Way of a Tree Validation Example)</p>

 <p>Consider ``genetic trees'' that contains leaves of DNA elements, in the
 sense that each tip is one of the symbols @('A'), @('G'), @('C'), or @('T').
 First we define the function @('valid-tip') which recognizes whether a tip
 contains one of these symbols.</p>

 @({
  (defun valid-tip (tip)
    (declare (xargs :guard t))
    (or (eq tip 'A)
        (eq tip 'G)
        (eq tip 'C)
        (eq tip 'T)))
 })

 <p>Now we define a function that traverses the tree, checking that every tip
 is valid.</p>

 @({
  (defun valid-tree-serial (tree)
    (declare (xargs :guard t))
    (if (atom tree)
        (valid-tip tree)
      (and (valid-tree-serial (car tree))
           (valid-tree-serial (cdr tree)))))
 })

 <p>We also define a parallel version.</p>

 @({
  (defun valid-tree-parallel (tree)
    (declare (xargs :guard t))
    (if (atom tree)
        (valid-tip tree)
      (pand (valid-tree-parallel (car tree))
            (valid-tree-parallel (cdr tree)))))
 })

 <p>Before we can time the functions, we need to create test trees.  We have
 found that test trees need to be approximately 1 gigabyte before we clearly
 see speedup, and we make them asymmetric to demonstrate the ability of our
 implementation to adapt to asymmetric data.  We can create the trees with the
 execution of the following forms.</p>

 @({
  (defun make-valid-binary-tree (x)
    (declare (xargs :mode :program))
    (if (< x 0)
        (cons (cons 'C 'G) (cons 'A 'T))
      (cons (make-valid-binary-tree (- x 2)) ; 2 to make asymmetric
            (make-valid-binary-tree (- x 1)))))

  (defconst *valid-tree* (make-valid-binary-tree 30)) ; takes awhile
  (defconst *invalid-tree* (cons *valid-tree* nil)) ; nil is invalid tip
 })

 <p>We can time our functions with the forms:</p>

 @({
  (time$ (valid-tree-serial *valid-tree*))
  (time$ (valid-tree-parallel *valid-tree*))
 })

 <p>Unfortunately, the serial version runs faster than the parallelism version;
 however, there is more to this story.</p>

 <p><b>Demonstrating Early Termination with an Invalid Tree</b></p>

 <p>Now observe this magic:</p>

 @({
  (time$ (valid-tree-serial   *invalid-tree*))
  (time$ (valid-tree-parallel *invalid-tree*))
 })

 <p>The serial version took awhile, while the parallel version finished almost
 immediately.  The test for validation was split into testing the @(tsee car)
 and the @(tsee cdr) of the @('*invalid-tree*') root, and since the @('cdr')
 was equal to @('nil'), its test returned immediately.  This immediate return
 quickly interrupted the computation associated with the @('car'), and returned
 the result.</p>

 <p><b>Granularity with</b> @(tsee Pand)</p>

 <p>We can also define a parallel version with a granularity form:</p>

 @({
  (defun valid-tree-parallel (tree depth)
    (declare (xargs :guard (natp depth)))
    (if (atom tree)
        (valid-tip tree)
      (pand
       (declare (granularity (< depth 5)))
       (valid-tree-parallel (car tree) (1+ depth))
       (valid-tree-parallel (cdr tree) (1+ depth)))))
 })

 <p>We can test this form by executing our previous forms.  You will probably
 find some speedup on a machine with several cores available, but more speedup
 can likely be obtained with an expensive test on the leaves in place of
 @('valid-tip').</p>

 @({
  (time$ (valid-tree-serial   *valid-tree*))
  (time$ (valid-tree-parallel *valid-tree* 0))
 })

 <p><b>Introducing</b> @(tsee Por)</p>

 <p>@(tsee Por) can be used in the same way as @(tsee pand), but with early
 termination occurring when an argument evaluates to a non-@('nil') value, in
 which case the value returned is @('t').  Finally, @(tsee por) also supports
 the use of a @(see granularity) form.</p>")

(defxdoc pargs
  :parents (parallel-programming acl2-built-ins)
  :short "Parallel evaluation of arguments in a function call"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism), and see @(see parallel-programming), which has a disclaimer.</p>

 @({
  Example Forms:
  (pargs (binary-+ (fibonacci (- x 1)) (fibonacci (- x 2))))

  (pargs (declare (granularity (> x 35)))
         (binary-+ (fibonacci (- x 1)) (fibonacci (- x 2))))

  General Form:
  (pargs (declare (granularity expr)) ; optional granularity declaration
         (f arg1 ... argN))
 })

 <p>where @('N >= 0') and each @('argi') and @('expr') are arbitrary terms.
 Logically, @('pargs') is just the identity macro, in the sense that the above
 forms can logically be replaced by @('(f arg1 ... argN)').  However, this
 @('pargs') form may parallelize the evaluation of arguments @('arg1') through
 @('argN') before applying function @('f') to those results.  If the above
 @(tsee granularity) declaration is present, then its expression (@('expr')
 above) is first evaluated, and if the result is @('nil'), then such
 parallelism is avoided.  Even if parallelism is not thus avoided, parallelism
 may be limited by available resources.</p>

 <p>Since macros can change expressions in unexpected ways, it is illegal to
 call @('pargs') on a form that is a macro call.  To parallelize computation of
 arguments to a macro, see @(see plet).</p>

 <p>See @(see parallelism-at-the-top-level) for restrictions on evaluating
 parallelism primitives from within the ACL2 top-level loop.</p>")

(defxdoc pathname
  :parents (books-reference)
  :short "Introduction to filename conventions in ACL2"
  :long "<p>The notion of pathname objects from Common Lisp is not supported in
 ACL2, nor is the function @('pathname').  However, ACL2 supports file
 operations, using conventions for naming files based on those of the
 Unix (trademark of AT&amp;T) operating system, so that the character @('/') is
 used to terminate directory names.  Some file names are ``absolute''
 (complete) descriptions of a file or directory; others are ``relative'' to the
 current working directory or to the connected book directory (see @(see cbd)).
 We emphasize that even for users of Windows-based systems or Macintosh
 computers, ACL2 file names are in the Unix style.  We will call these <i>ACL2
 pathnames</i>, often omitting the ``ACL2.''</p>

 <p>Pathnames starting with the directory separator (@('/')) or the tilde
 character (@('~')) are absolute pathnames.  All other pathnames are relative
 pathnames.  An exception is in the Microsoft Windows operating system, where
 it is illegal for the pathname to start with a tilde character but the drive
 may be included, e.g., @('\"c:/home/smith/acl2/book-1.lisp\"').  In fact, the
 drive <i>must</i> be included in the portcullis of a book; see @(see
 portcullis).  Note also that some host Common Lisps will not support pathnames
 starting with @('\"~\"'), for example @('~smith'), though ACL2 will generally
 support those starting with @('\"~/\"') regardless of the host Common
 Lisp.</p>

 <p>Consider the following examples.  The filename string</p>

 @({
  \"/home/smith/acl2/book-1.lisp\"
 })

 <p>is an absolute pathname, with top-level directory @('\"home\"'), under that
 the directory @('\"smith\"') and then the directory @('\"acl2\"'), and
 finally, within that directory the file @('\"book-1.lisp\"').  If the
 connected book directory is @('\"/home/smith/\"') (see @(see cbd)), then the
 filename string above also corresponds to the relative filename string
 \"acl2/book1.lisp\".</p>

 <p>Finally, we note that (on non-Windows systems) the pathname @('\"~\"') and
 pathnames starting with @('\"~/\"') are illegal in books being certified.
 Otherwise, a subsidiary @(tsee include-book) form would have a different
 meaning at certification time than at a later time when the certified book is
 included by a different user.</p>")

(defxdoc patterned-congruence
  :parents (rule-classes)
  :short "Removing restrictions on classic @(see congruence) rules"
  :long "<p>This topic assumes familiarity with the basics of congruence
 rules; see @(see congruence).  Some aspects of congruence rules carry over to
 patterned congruence rules; in particular, they may be @(see disable)d, but
 they are not tracked for reporting in the summary.</p>

 <p>We begin our discussion by showing some patterned congruence rules and
 using them to illustrate some terminology.</p>

 @({
 Example forms:

 ; ``Shallow'' patterned congruence rule:
 (implies (e1 y1 y2)
          (e2 (f1 3 y1 (cons x x))
              (f1 3 y2 (cons x x))))

 ; ``Deep'' patterned congruence rule:
 (implies (e1 y1 y2)
          (e2 (mv-nth 1 (foo x y1 z))
              (mv-nth 1 (foo x y2 z))))

 ; ``Deep'' patterned congruence rule:
 (implies (e1 y1 y2)
          (e2 (mv-nth 1 (foo x (g y1) z))
              (mv-nth 1 (foo x (g y2) z))))
 })

 <p>In the example forms above, @('e1') and @('e2') are known equivalence
 relations, which (as for classic congruence rules) we call the ``inner'' and
 ``outer'' equivalences.  The examples above are not classic, because the
 ``function symbol'' of the rule &mdash; @('f1') in the first example,
 @('mv-nth') in the second and third examples &mdash; is not being applied to
 distinct variables.  The first example is called ``shallow'' because the
 ``variable'' of the rule, @('y1'), is a top-level argument of the ``lhs'' of
 the rule, which is the first call of @('f1'); the others do not have this
 property, as @('y1') is buried under further function calls.</p>

 <p>We invite you to browse the community book
 <tt>demos/patterned-congruences.lisp</tt>, which provides several examples of
 patterned congruence rules and their use, as well as several examples of
 formulas that are illegal as patterned congruence rules for various
 reasons.</p>

 <p>We now define the class of patterned congruence rules.  The general form of
 a patterned congruence rule is</p>

 @({
 (implies (equiv1 x y)
          (equiv2 lhs rhs)),
 })

 <p>where the rule is not classic (see @(see congruence)) and the following
 conditions hold.  @('Equiv1') and @('equiv2') are known equivalence relations,
 which (as in the classic case) we call the ``inner'' and ``outer''
 equivalences, respectively.  The terms @('lhs') and @('rhs') are function
 calls, and we call these the @('lhs') and @('rhs') of the rule, respectively.
 The variable @('x') occurs in @('lhs') and the variable @('y') occurs in
 @('rhs').  These must be the only occurrences of @('x') and @('y') in either
 @('lhs') or @('rhs'), and @('rhs') must be the result of substituting @('y')
 for @('x') in @('lhs').  None of the following may occur as a function symbol
 of @('lhs') (or, equivalently, @('rhs')): @('if'), @('implies'), @('equal'),
 or a @(tsee lambda).</p>

 <p>Patterned congruence rules are used, much like classic congruence rules, by
 the ACL2 rewriter to determine which equivalence relations to maintain as it
 dives into a term.  Recall (see @(see congruence)) that if it suffices for the
 rewriter to maintain @('e2') when rewriting a term, then it suffices to
 maintain @('e1') when rewriting an argument of that term provided there is an
 applicable congruence rule with outer equivalence @('e2') and inner
 equivalence @('e1').  An analogous principle holds for patterned congruence
 rules, which by the way consider refinements of the outer equivalence just as
 is done by classic congruence rules.  But there is a new wrinkle because the
 lhs of a patterned congruence rule is a function call that can have
 non-variable arguments.  Consider the following events.</p>

 @({
 (defun e1 (x y)
   (equal x y))

 (defequiv e1)

 (defun f10 (x)
   (list 3 x x))

 (defun f11 (x y)
   (declare (ignore y))
   x)

 (defthm e1-implies-iff-f11-cong-2
   (implies (e1 y1 y2)
            (iff (f11 (f10 x) y1)
                 (f11 (f10 x) y2)))
   :rule-classes (:congruence))

 (in-theory (disable f11 (:t f11) e1))
 })

 <p>The following proof fails, because the indicated call of @('f10') expands
 before the rewriter is applied to @('b2') &mdash; otherwise @('b2') would
 rewrite to @('b1') because @('(e1 b1 b2)') is known in that context and by the
 rule above, it suffices to maintain @('e1') when rewriting @('b2').</p>

 @({
 (thm (implies (e1 b1 b2)
               (iff (f11 (f10 a)
                         b1)
                    (f11 (f10 a) ; expands before b2 is rewritten
                         b2))))
 })

 <p>On the other hand, the following succeeds because the rewrite discussed
 above does indeed take place when the indicated call of @('f10') does not
 expand.</p>

 @({
 (thm
   (implies (e1 b1 b2)
            (iff (f11 (f10 a)
                      b1)
                 (f11 (f10 a) ; does not expand
                      b2)))
   :hints ((\"Goal\" :in-theory (disable f10))))
 })

 <p>This inherent sequentiality of matching is important for soundness, as is
 illustrated by examples using the function @('some-consp') in the
 aforementioned community book, <tt>demos/patterned-congruences.lisp</tt>.</p>

 <p>The example above illustrates the following point: as the rewriter dives
 into a term, then when matching is attempted using a patterned congruence
 rule, rewriting has already taken place to the left of the current subterm.
 By contrast, note that this pass through the rewriter will not yet have
 completed rewriting of terms to the right of the current subterm when matching
 a patterned congruence rule.</p>

 <p>Patterned congruence rules are used primarily during the process of
 <i>rewriting</i>.  In particular, unlike classic congruence rules, they are
 <i>not</i> used to do equality substitution at the goal level.  The simplest
 way to understand this point may be with the following trivial example.</p>

 @({
 (defstub foo (x y z) t)

 (thm (implies (equal u (* a b))
               (foo u u b)))
 })

 <p>The theorem fails, of course, but what is interesting is that ACL2
 simplifies it by replacing the variable @('u') by the term @('(* a b)')
 throughout the goal and then dropping the equality, to produce the following
 goal.</p>

 @({
 (FOO (* A B) (* A B) B)
 })

 <p>This sort of substitution can also be made when @('equal') is replaced by a
 known equivalence relation, if a classic congruence rule for @('foo')
 justifies the substitution.  But that is not the case for our implementation
 of patterned congruence rules.</p>

 <p>The discussion above is intended to suffice for effective use of patterned
 congruence rules.  If you are interested in their <i>implementation</i>, we
 invite you to read the long comment entitled ``Essay on Patterned Congruences
 and Equivalences'' in ACL2 source file <tt>rewrite.lisp</tt>.</p>")

(defxdoc pbt
  :parents (history)
  :short "Print the @(see command)s back through a @(see command) descriptor"
  :long "@({
  Examples:
  :pbt :max      ; print back through the most recent command
  :pbt :x        ; print back through the most recent command
  :pbt fn        ; print back through the introduction of fn
  :pbt 5         ; print back through the fifth command executed
  :pbt (:x -4)   ; print back through the most recent five commands
 })

 <p>See @(see command-descriptor).</p>

 <p>@('Pbt') takes one argument, a @(see command) descriptor, and prints the
 @(see command)s from @(':max') (aka @(':x')) through the one described.  See
 @(see command-descriptor) for a description of what a @(see command)
 descriptor is.  See @(see pc) for a description of the format used to display
 @(see command)s.  @('Pbt') will print the @(see command)s that @(tsee ubt)
 will undo.</p>")

(defxdoc pc
  :parents (history)
  :short "Print the @(see command) described by a @(see command) descriptor"
  :long "@({
  Examples:
  :pc 3    ; print the third command executed
  :pc :max ; print the most recent command
  :pc :x   ; print the most recent command
  :pc fn   ; print the command that introduced fn
 })

 <p>See @(see command-descriptor).</p>

 <p>@('Pc') takes one argument, a @(see command) descriptor, and prints the
 @(see command) identified by that descriptor, doing so in full unless the
 @(see ld-evisc-tuple) is non-nil, in which case it abbreviates using that
 evisc-tuple; see @(see evisc-tuple).  See @(see command-descriptor).  For
 example:</p>

 @({
  ACL2 !>:pc foo
   LVd     52 (DEFUN FOO (X) X)
 })

 <p>@('Pc') always prints a space first, followed by four (possibly blank)
 @(see characters) (``LVd'' above) explained below.  Then @('pc') prints the
 @(see command) number, a number uniquely identifying the @(see command)'s
 position in the sequence of @(see command)s since the beginning of the user's
 session.  Finally, the @(see command) itself is printed.</p>

 <p>While @('pc') always prints a space first, some @(see history) @(see
 command)s, for example @(':')@(tsee pcs) and @(':')@(tsee pe), use the first
 column of output to delimit a region of @(see command)s or to point to a
 particular event (perhaps as modified using @(tsee extend-pe-table)) within a
 @(see command).</p>

 <p>For example, @(':pcs 52 54') will print something like</p>

 @({
  /LVd     52 (DEFUN FOO (X) X)
   LV      53 (DEFUN BAR (X) (CONS X X))
  \\        54 (DEFTHM FOO-BAR (EQUAL (CAR (BAR X)) (FOO X)))
            : ...
          127 (DEFUN LATEST (X) X)
 })

 <p>Here, the two slash @(see characters) in the first column are intended to
 suggest a bracket delimiting @(see command)s 52 through 54.  The last @(see
 command) printed by @(tsee pcs) is always the most recent @(see command),
 i.e., the @(see command) at @(':here'), and is separated from the rest of the
 display by an ellipsis if some @(see command)s are omitted.</p>

 <p>Similarly, the @(':')@(tsee pe) @(see command) will print a particular
 event (perhaps as modified using @(tsee extend-pe-table)) within a @(see
 command) block and will indicate that event by printing a ``@(tsee >)'' in the
 first column.  The symbol is intended to be an arrow pointing at the event in
 question.</p>

 <p>For example, @(':')@(tsee pe) @('true-listp-app') might print:</p>

 @({
           1 (INCLUDE-BOOK \"list-book\")
              \\
  >           (DEFTHM TRUE-LISTP-APP
                      (EQUAL (TRUE-LISTP (APP A B)) (TRUE-LISTP B)))
 })

 <p>using the arrow to indicate the event itself.  The slash printed to connect
 the @(see command), @(tsee include-book), with the event, @(tsee defthm), is
 intended to suggest a tree branch indicating that the event is inferior to
 (and part of) the @(see command).</p>

 <p>The mysterious @(see characters) sometimes preceding a @(see command) have
 the following interpretations.  The first two have to do with the function
 symbols introduced by the @(see command) and are blank if no symbols were
 introduced.</p>

 <p>At any time we can classify our function symbols into disjoint sets, which
 we will here name with @(see characters).  The ``@('P')'' functions are those
 in @(':')@(tsee program) mode.  The ``@('L')'' functions are those in
 @(':')@(tsee logic) mode whose @(see guard)s have not been verified.  The
 ``@('V')'' functions are those in @(':')@(tsee logic) mode whose @(see guard)s
 have been verified.  You may also see the use of (lower-case) ``@('v')'' to
 indicate functions introduced by @(tsee encapsulate).  Note that @(tsee
 verify-termination) and @(tsee verify-guards) cause function symbols to be
 reclassified.  If a @(see command) introduces function symbols then the first
 mysterious character indicates the class of the symbols at the time of
 introduction and the second character indicates the current class of the
 symbols (if the current class is different from the introductory class).</p>

 <p>Thus, the display</p>

 @({
   PLd     52 (DEFUN FOO (X) X)
 })

 <p>tells us that @(see command) 52 introduced a @(':')@(tsee program) function
 but that some @(see command) after 52 changed its mode to @(':')@(tsee logic)
 and that the @(see guard)s of @('foo') have not been verified.  That is,
 @('foo')'s termination has been verified even though it was not verified as
 part of the @(see command) that introduced @('foo').  Had a subsequent @(see
 command) verified the @(see guard)s of @('foo'), the display would contain a
 @('V') where the @('L') is.</p>

 <p>The display</p>

 @({
   P d     52 (DEFUN FOO (X) X)
 })

 <p>indicates that @('foo') was introduced in @(':')@(tsee program) mode and
 still is in that mode.</p>

 <p>The third character indicates the @(see enable)d/@(see disable)d status of
 the @(see rune)s introduced by the @(see command).  If the status character is
 blank then all the @(see rune)s (if any) introduced are @(see enable)d.  If
 the status character is ``@('D')'' then some @(see rune)s were introduced and
 they are all @(see disable)d.  If the status character is ``@('d')'' then at
 least one, but not all, of the @(see rune)s introduced is @(see disable)d.
 Thus, in the display</p>

 @({
   L d     52 (DEFUN FOO (X) X)
 })

 <p>we see that some @(see rune) introduced by @(see command) 52 is @(see
 disable)d.  As noted in the documentation for @(see rune), a @(tsee defun)
 @(see command) introduces many @(see rune)s, e.g., the axiomatic definition
 rule, @('(:definition fn)'), the executable-counterpart rule,
 @('(:executable-counterpart fn)'), and @(see type-prescription)s,
 @('(:type-prescription fn)').  The display above does not say which of the
 @(see rune)s based on @('foo') is @(see disable)d, but it does tell us one of
 them is; see @(see disabledp) for how to obtain the disabled runes for a given
 function symbol.</p>

 <p>Remark for users of the @(see break-rewrite) utility.  Inside the
 @(':')@(tsee brr) loop, the status character shows whether rules are disabled
 at the current point of the proof that is currently underway, rather than
 whether rules are disabled globally.  For example, if you break while the
 prover is working on Subgoal 3, and the @(see hints) supplied for the proof
 specify @('(\"Subgoal 3\" :in-theory (disable foo))'), then regardless of
 whether or not rules associated with @('foo') are enabled globally, the status
 character indicates whether they are enabled while processing Subgoal 3.</p>

 <p>Finally, a fourth character is printed, indicating whether functions are
 @(see memoize)d.  A symbol may be memoized if it is a function symbol that is
 not constrained (i.e., introduced by @(tsee defchoose) or in the @(see
 signature) of an @(tsee encapsulate) event).  If the command introduces no
 symbol that may be memoized, then a space is printed.  Otherwise, if every
 memoizable symbol is memoized, an ``@('M')'' is printed.  Otherwise, an
 ``@('m')'' is printed.</p>")

(defxdoc pcb
  :parents (history)
  :short "Print the @(see command) block described by a @(see command) descriptor"
  :long "@({
  Examples:
  :pcb :max ; print the most recent command block
  :pcb :x   ; print the most recent command block
  :pcb fn   ; print the command block that introduced fn
  :pcb 5    ; print the fifth command block
 })

 <p>See @(see command-descriptor).</p>

 <p>@('Pcb') takes one argument, a @(see command-descriptor), and prints in an
 abbreviated format the @(see command) block of the command described.  See
 @(see pc) for description of the format in which @(see command)s are
 displayed.  The command block of a command consists of the command itself and
 all of the @(see events) it created.  If the command created a single event
 and that event is in fact the command (i.e., if the command typed was just an
 event such as a @(tsee defun) or @(tsee defthm) rather than a macro that
 expanded to some event forms), then @('pcb') just prints the command (unless
 the event is replaced using @(tsee extend-pe-table)).  @('Pcb') sketches the
 command and all of the @(see events) it created, rather than printing them
 fully.  If you wish to see just the command, in its entirety, use @(tsee pc).
 If you wish to see one of the @(see events) within the block, in its entirety,
 use @(tsee pe).  If you wish to see the command sketched and all of the events
 it created, in their entirety, use @(tsee pcb!).  For a sequence of commands,
 see @(see pcs) and @(see gcs).</p>")

(defxdoc pcb!
  :parents (history)
  :short "Print in full the @(see command) block described by a @(see command) descriptor"
  :long "@({
  Examples:
  :pcb! :max ; print the most recent command block
  :pcb! :x   ; print the most recent command block
  :pcb! fn   ; print the command block that introduced fn
  :pcb! 5    ; print the fifth command block
 })

 <p>See @(see command-descriptor).</p>

 <p>@('Pcb!') takes one argument, a @(see command) descriptor, and prints the
 @(see command) block of the @(see command) described.  Unlike @(tsee pcb),
 @('pcb!') prints the event forms in full (see @(see pcb) for details) &mdash;
 unless the @(see ld-evisc-tuple) is non-nil, in which case it abbreviates
 using that evisc-tuple; see @(see evisc-tuple).</p>")

(defxdoc pcs
  :parents (history)
  :short "Print the sequence of @(see command)s between two @(see command) descriptors"
  :long "@({
  Examples:
  :pcs 1 5              ; print commands 1 through 5
  :pcs 5 1              ; same as above
  :pcs :x (:x -3)       ; print the 3 most recently executed commands
  :pcs fn assoc-of-fn   ; print the commands between the one that introduced
                        ; fn and the one that introduced assoc-of-fn
 })

 <p>@('Pcs') takes two arguments, both of which are @(see command) descriptors,
 and prints the @(see command)s between them with @(tsee pc).  The order of the
 two descriptors is irrelevant.  See @(see command-descriptor) for a
 description of @(see command) descriptors.  See @(see pc) for a description of
 the format in which @(see command)s are displayed.</p>

 <p>For a related utility that simply returns a sequence of commands, see @(see
 get-command-sequence).</p>")

(defxdoc pe
  :parents (history)
  :short "Print the events named by a logical name"
  :long "@({
  Example:
  :pe fn   ; sketches the command that introduced fn and
           ; prints in full the event within it that created fn.
 })

 <p>See @(see logical-name).</p>

 <p>@('Pe') takes one argument, a logical name, and prints the event
 corresponding to the name, doing so in full unless the @(see ld-evisc-tuple)
 is non-nil, in which case it abbreviates using that evisc-tuple; see @(see
 evisc-tuple).  @('Pe') also sketches the @(see command) responsible for that
 event if the @(see command) is different from the event itself.  See @(see pc)
 for a description of the format used to display a @(see command).  To remind
 you that the event is inferior to the @(see command), i.e., you can only undo
 the entire @(see command), not just the event, the event is indented slightly
 from the @(see command) and a slash (meant to suggest a tree branch) connects
 them.</p>

 <p>If the given logical name corresponds to more than one event, then @(':pe')
 will print the above information for every such event.  Here is an example of
 such behavior.</p>

 @({
  ACL2 !>:pe nth
        -4270  (ENCAPSULATE NIL ...)
               \\
  >V            (VERIFY-TERMINATION NTH)

  Additional events for the logical name NTH:
   PV   -4949  (DEFUN NTH (N L)
                      \"Documentation available via :doc\"
                      (DECLARE (XARGS :GUARD (AND (INTEGERP N)
                                                  (>= N 0)
                                                  (TRUE-LISTP L))))
                      (IF (ENDP L)
                          NIL
                          (IF (ZP N)
                              (CAR L)
                              (NTH (- N 1) (CDR L)))))
  ACL2 !>
 })

 <p>If you prefer to see only the formula for the given name, for example if it
 is part of a large @(tsee mutual-recursion), see @(see pf).</p>

 <p>See @(see extend-pe-table) for a way to specify a form to be printed in
 place of the actual event.  To avoid such replacement, see @(see pe!).</p>")

(defxdoc pe!
  :parents (history)
  :short "Print events as with @(tsee pe) but ignoring the @(see pe-table)"
  :long "<p>This alternative to @(tsee pe) temporarily clears the @(see
  pe-table) so that original @(see events) are displayed.</p>")

(defxdoc pf
  :parents (history)
  :short "Print the formula corresponding to the given name"
  :long "@({
  Examples:
  :pf (:definition fn) ; prints the definition of fn as an equality
  :pf fn               ; same as above

  :pf (:rewrite foo)   ; prints the statement of the rewrite rule foo
  :pf foo              ; same as above
 })

 <p>@('pf') takes one argument, an event name or a @(see rune), and prints the
 formula associated with name.  If the argument is the name of a macro
 associated with a function name by @(see macro-aliases-table), then the
 function name is used as the argument.</p>")

(defxdoc pkg-imports
  :parents (packages)
  :short "List of symbols imported into a given package"
  :long "<p>Completion Axiom (@('completion-of-pkg-imports')):</p>

 @({
  (equal (pkg-imports x)
         (if (stringp x)
             (pkg-imports x)
           nil))
 })

 <p>@(see Guard) for @('(pkg-imports x)'):</p>

 @({
  (stringp x)
 })

 <p>@('(Pkg-imports pkg)') returns a duplicate-free list of all symbols
 imported into @('pkg'), which should be the name of a package known to ACL2.
 For example, suppose @('\"MY-PKG\"') was created by</p>

 @({
  (defpkg \"MY-PKG\" '(ACL2::ABC LISP::CAR)).
 })

 <p>Then @('(pkg-imports \"MY-PKG\")') equals the list @('(ACL2::ABC
 LISP::CAR)').</p>

 <p>If @('pkg') is not a string, then @('(pkg-imports pkg)') is @('nil').  If
 @('pkg') is a string but not the name of a package known to ACL2, then the
 value of the form @('(pkg-imports pkg)') is unspecified, and its evaluation
 will fail to yield a value.  By ``the symbols imported into @('pkg')'' we mean
 the symbols imported into @('pkg') by the @(tsee defpkg) event that introduced
 @('pkg').  There are no imports for built-in packages except for the
 @('\"ACL2\"') package, which imports the symbols in the list value of the
 constant @('*common-lisp-symbols-from-main-lisp-package*').  In particular,
 this is the case for the @('\"COMMON-LISP\"') package.  Users familiar with
 Common Lisp may find this surprising, since in actual Common Lisp
 implementations it is often the case that many symbols in that package are
 imported from other packages.  However, ACL2 treats all symbols in the
 constant @('*common-lisp-symbols-from-main-lisp-package*') as having a @(tsee
 symbol-package-name) of @('\"COMMON-LISP\"'), as though they were not
 imported.  ACL2 admits a symbol imported into in the @('\"COMMON-LISP\"')
 package only if it belongs to that list: any attempt to read any other symbol
 imported into the @('\"COMMON-LISP\"') package, or to produce such a symbol
 with @(tsee intern$) or @(tsee intern-in-package-of-symbol), will cause an
 error.</p>

 <p>The following axioms formalize properties of @('pkg-imports') discussed
 above (use @(':')@(tsee pe) to view them).</p>

 @({
  symbol-package-name-intern-in-package-of-symbol
  intern-in-package-of-symbol-is-identity
  symbol-listp-pkg-imports
  no-duplicatesp-pkg-imports
  completion-of-pkg-imports
 })")

(defxdoc pkg-witness
  :parents (packages acl2-built-ins)
  :short "Return a specific symbol in the indicated package"
  :long "<p>For any string @('pkg') that names a package currently known to
 ACL2, @('(pkg-witness pkg)') is a symbol in that package whose @(tsee
 symbol-name) is the value of constant @('*pkg-witness-name*').  Logically,
 this is the case even if the package is not currently known to ACL2.  However,
 if @('pkg-witness') is called on a string that is not the name of a package
 known to ACL2, a hard Lisp error will result.</p>

 <p>@('(Pkg-witness pkg)') has a guard of @('(and (stringp pkg) (not (equal pkg
 \"\")))').  If @('pkg') is not a string, then @('(pkg-witness pkg)') is equal
 to @('(pkg-witness \"ACL2\")')</p>")

(defxdoc pl
  :parents (history)
  :short "Print the rules for the given name or term"
  :long "@({
  Examples:
  :pl foo     ; prints rules that rewrite some call of foo
  :pl (+ x y) ; prints rules that rewrite (+ x y)
 })

 <p>Also see @(see pl2), which restricts output to rules that you specify for a
 given term.</p>

 <p>@('Pl') takes one argument, which should be a symbol or a term.</p>

 <p>First suppose that the argument is a symbol.  Then it should be either a
 function symbol or else a macro alias for a function symbol (see @(see
 macro-aliases-table)), which is treated as the corresponding function symbol.
 In this case @(':pl') displays rules that apply to terms whose top function
 symbol is the one specified, specifically, rules of class @(':')@(tsee
 rewrite), @(':')@(tsee definition), @(':')@(tsee meta), @(':')@(tsee linear),
 @(':')@(tsee type-prescription), @(':')@(tsee forward-chaining), @(':')@(tsee
 elim), and @(':')@(tsee induction).</p>

 <p>Otherwise the argument should be a term (in user syntax, so that for
 example macros are permitted).  In this case, @(':pl') displays the
 @(':')@(tsee rewrite), @(':')@(tsee definition), and @(':meta') rules that
 rewrite the specified term, followed by the applicable @(':')@(tsee
 type-prescription) rules.  Each rule is displayed with additional information,
 such as the hypotheses that remain after applying some simple techniques to
 discharge them that are likely to apply in any context.  Note that for
 @(':')@(tsee meta) rules, only those are displayed that meet two conditions:
 the application of the metafunction returns a term different from the input
 term, and if there is a hypothesis metafunction then it also returns a term.
 (A subtlety: In the case of extended metafunctions (see @(see
 extended-metafunctions)), a trivial metafunction context is used for the
 application of the metafunction.)</p>

 <p>Note that some rule classes are not handled by @(':pl').  In particular, if
 you want to see all @(':')@(tsee clause-processor) rules, issue the command
 @(':print-clause-processor-rules'), and for trusted clause-processors,
 @('(table trusted-clause-processor-table)'); see @(see clause-processor) and
 see @(see define-trusted-clause-processor).</p>")

(defxdoc pl2
  :parents (history)
  :short "Print rule(s) for the given form"
  :long "@({
  Examples:
  :pl2 (+ x y) nil ; prints rules that apply to (+ x y)
  :pl2 (+ x y) foo ; prints rules named foo that apply to (+ x y)
  :pl2 (+ x y) (:rewrite foo) ; if the rule with rune (:rewrite foo) applies
                              ;   to (+ x y), then print it
  :pl2 (+ x y) (:type-prescription foo)
                              ; as above, but for the indicated
                              ;   type-prescription rule
 })

 <p>@('Pl2') takes two arguments.  The first is a term.  The second is either
 @('nil') or a ``rule-id'' that is either a symbol or a @(see rune).  The
 result is to print rules of class @(':')@(tsee rewrite), @(':')@(tsee
 definition), @(':meta'), @(':')@(tsee linear), and @(':')@(tsee
 type-prescription) that apply to the given term.  Indeed, @(':pl2') prints
 exactly what is printed by applying @(':')@(tsee pl) to the first argument
 &mdash; see @(see pl) &mdash; except that if the second argument is not
 @('nil') then it is used to filter the rules printed, as follows.</p>

 <blockquote>

 <p>If the rule-id is a symbol, then only rules whose name is that symbol will
 be printed.</p>

 <p>If the rule-id is a @(see rune), then at most one rule will be printed: the
 rule named by that rune (if the rule would be printed by @(':')@(tsee
 pl)).</p></blockquote>")

(defxdoc plet
  :parents (parallel-programming acl2-built-ins)
  :short "Parallel version of @(tsee let)"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism), and see @(see parallel-programming), which has a disclaimer.</p>

 @({
  Example Forms:
  (plet ((a (fibonacci (- x 1)))
         (b (fibonacci (- x 2))))
        (+ a b))

  (plet (declare (granularity (> x 35)))
        ((a (fibonacci (- x 1)))
         (b (fibonacci (- x 2))))
        (+ a b))

  General Form:
  (plet (declare (granularity expr)) ; optional granularity declaration
        ((var1 val1)
         ...
         (varN valN))
        (declare ...) ... (declare ...) ; optional declarations
        body)
 })

 <p>The syntax of @('plet') is identical to the syntax of @(tsee let), except
 that @('plet') permits an optional granularity declaration in the first
 argument position; see @(see granularity).  In the logic a call of @('plet')
 macroexpands to the corresponding call of @(tsee let), where the granularity
 declaration (if any) is dropped.</p>

 <p>@('Plet') cause the evaluation of each @('vali') above to be done in
 parallel before processing the body.  If the above @(tsee granularity)
 declaration is present, then its expression (@('expr') above) is first
 evaluated, and if the result is @('nil'), then such parallelism is avoided.
 Even if parallelism is not thus avoided, parallelism may be limited by
 available resources.</p>

 <p>See @(see parallelism-at-the-top-level) for restrictions on evaluating
 parallelism primitives from within the ACL2 top-level loop.</p>")

(defxdoc plusp
  :parents (numbers acl2-built-ins)
  :short "Test whether a number is positive"
  :long "<p>@('(Plusp x)') is true if and only if @('x > 0').</p>

 <p>The @(see guard) of @('plusp') requires its argument to be a rational
 (@(see real), in ACL2(r)) number.</p>

 <p>@('Plusp') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def plusp)")

(defxdoc pointers
  :parents (documentation)
  :short "Links pointing to relevant documentation topics")

(defxdoc por
  :parents (parallel-programming acl2-built-ins)
  :short "Parallel, Boolean version of @(tsee or)"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism), and see @(see parallel-programming), which has a disclaimer.</p>

 @({
  Example Forms:
  (por (subsetp-equal x y)
       (subsetp-equal y x))

  (por (declare
        (granularity
         (and (> (length x) 500)
              (> (length y) 500))))
        (subsetp-equal x y)
        (subsetp-equal y x))
 })

 @({
  General Form:
  (por (declare (granularity expr)) ; optional granularity declaration
       arg1 ... argN)
 })

 <p>where @('N >= 0') and each @('argi') and @('expr') are arbitrary terms.</p>

 <p>@('Por') evaluates its arguments in parallel.  It returns a Boolean result:
 @('t') if any argument evaluates to non-@('nil'), else @('nil').  Note that
 while @(tsee or) returns the first non-@('nil') value from evaluating its
 arguments left-to-right (if any such value is not @('nil')) @(tsee por) always
 returns a Boolean result, in support of efficiency (see @(see
 early-termination)) in light of the nondeterministic order in which argument
 values are returned.</p>

 <p>Another difference between @('por') and @(tsee or) is that for a call of
 @('por'), even if the an argument's value is not @('nil'), a subsequent
 argument may be evaluated.  See @(see pand) for a discussion of the analogous
 property of @('pand').  In particular, @(see guard)s generated from calls of
 @('por') may not assume for an argument that the preceding arguments evaluated
 to @('nil').</p>

 <p>See @(see parallelism-tutorial) for another example.  Also see @(see
 parallelism-at-the-top-level) for restrictions on evaluating parallelism
 primitives from within the ACL2 top-level loop.  Finally see @(see
 early-termination) to read how @('por') can offer more efficiency than @(tsee
 or) by avoiding evaluation of some of its arguments.</p>")

(defxdoc portcullis
  :parents (books-tour)
  :short "The gate guarding the entrance to a certified book"
  :long "<p>The certificate (see @(see certificate) for general information) of
 a certified file contains a portcullis and a @(see keep).  These names come
 from castle lore.  The portcullis of a castle is an iron grate that slides up
 through the ceiling of the tunnel-like entrance.  The portcullis of a book
 ensures that @(tsee include-book) does not start to read the book until the
 appropriate context has been created.</p>

 <p>Technically, the portcullis consists of the @(see version) number of the
 certifying ACL2, a list of @(see command)s used to create the ``certification
 @(see world)'' and an alist specifying @(see book-hash) values for all the
 @(see books) included in that @(see world).  The portcullis is constructed
 automatically by @(tsee certify-book) from the @(see world) in which @(tsee
 certify-book) is called, but that @(see world) must have certain properties
 described below.  After listing the properties we discuss the issues in a more
 leisurely manner.</p>

 <p>Each @(see command) in the portcullis must be either a @(tsee defpkg) form
 or an embedded event form (see @(see embedded-event-form)).</p>

 <p>Consider a book to be certified.  The book is a file containing event
 forms.  Suppose the file contains references to such symbols as
 @('my-pkg::fn') and @('acl2-arith::cancel'), but that the book itself does not
 create the packages.  Then a hard Lisp error would be caused merely by the
 attempt to read the expressions in the book.  The corresponding @(tsee
 defpkg)s cannot be written into the book itself because the book must be
 compilable and Common Lisp compilers differ on the rules concerning the inline
 definition of new packages.  The only safe course is to make all @(tsee
 defpkg)s occur outside of compiled files.</p>

 <p>More generally, when a book is certified it is certified within some
 logical @(see world).  That ``certification @(see world)'' contains not only
 the necessary @(tsee defpkg)s but also, perhaps, function and constant
 definitions and maybe even references to other @(see books).  When @(tsee
 certify-book) creates the @(see certificate) for a file it recovers from the
 certification @(see world) the @(see command)s used to create that @(see
 world) from the initial ACL2 @(see world).  Those @(see command)s become part
 of the portcullis for the certified book.  In addition, @(tsee certify-book)
 records in the portcullis certain <i>book-hash</i> values (see @(see
 book-hash)) for all the @(see books) included in the certification @(see
 world).</p>

 <p>@(tsee Include-book) presumes that it is impossible even to read the
 contents of a certified book unless the portcullis can be ``raised.'' To raise
 the portcullis we must be able to execute (possibly redundantly, but certainly
 without error), all of the @(see command)s in the portcullis and then verify
 that the @(see books) thus included were identical to those used to build the
 certification @(see world) (up to book-hash).  This raising of the portcullis
 must be done delicately since @(tsee defpkg)s are present: we cannot even read
 a @(see command) in the portcullis until we have successfully executed the
 previous ones, since packages are being defined.</p>

 <p>Clearly, a book is most useful if it is certified in the most elementary
 extension possible of the initial logic.  If, for example, your certification
 @(see world) happens to contain a @(tsee defpkg) for @('\"MY-PKG\"') and the
 function @('foo'), then those definitions become part of the portcullis for
 the book.  Every time the book is included, those names will be defined and
 will have to be either new or redundant (see @(see redundant-events)).  But if
 those names were not necessary to the certification of the book, their
 presence would unnecessarily restrict the utility of the book.</p>

 <p>See @(see keep) to continue the guided tour of @(see books).</p>")

(defxdoc pos-listp
  :parents (numbers lists acl2-built-ins)
  :short "Recognizer for a true list of positive integers"
  :long "<p>The predicate @('pos-listp') tests whether its argument is a true
 list of positive integers.</p>

 @(def pos-listp)")

(defxdoc position
  :parents (lists strings acl2-built-ins)
  :short "Position of an item in a string or a list"
  :long "@({
  General Forms:
  (position x seq)
  (position x seq :test 'eql)   ; same as above (eql as equality test)
  (position x seq :test 'eq)    ; same, but eq is equality test
  (position x seq :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Position x seq)') is the least index (zero-based) of the element @('x')
 in the string or list @('seq'), if @('x') is an element of @('seq').
 Otherwise @('(position x seq)') is @('nil').  The optional keyword,
 @(':TEST'), has no effect logically, but provides the test (default @(tsee
 eql)) used for comparing @('x') with items of @('seq').</p>

 <p>The @(see guard) for a call of @('position') depends on the test.  In all
 cases, the second argument must satisfy @(tsee stringp) or @(tsee true-listp).
 If the test is @(tsee eql), then either the first argument must be suitable
 for @(tsee eql) (see @(see eqlablep)) or the second argument must satisfy
 @(tsee eqlable-listp).  If the test is @(tsee eq), then either the first
 argument must be a symbol or the second argument must satisfy @(tsee
 symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('position') and its variants:</p>

 <blockquote><p>@('(position-eq x seq)') is equivalent to @('(position x seq
 :test 'eq)');</p>

 <p>@('(position-equal x seq)') is equivalent to @('(position x seq :test
 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('position-equal').</p>

 <p>@('Position') is defined by Common Lisp.  See any Common Lisp documentation
 for more information.</p>

 @(def position-equal)
 @(def position-equal-ac)")

(defxdoc posp
  :parents (numbers acl2-built-ins)
  :short "A recognizer for the positive integers"
  :long "<p>@('(posp x)') is logically equivalent to @('(not (zp x))') (see
 @(see zp)) and also to @('(and (natp x) (not (equal x 0)))').</p>

 <p>The community book @(see arithmetic/natp-posp) has some lightweight rules
 for reasoning about @('posp') and @('natp'), and is included in the @(see
 arithmetic-1) library.  For a somewhat heavier and more comprehensive
 alternative, you may wish to instead see the @(see arith-equivs) book.</p>

 @(def posp)")

(defxdoc post-induction-key-checkpoints
  :parents (introduction-to-the-theorem-prover)
  :short "Reading post-induction key checkpoints"
  :long "<p>Each post-induction key checkpoint is a theorem if and only if the
 original conjecture was a theorem.  The reason is that each subgoal produced
 by induction concludes with the original formula and simplification preserves
 equivalence.</p>

 <p>So if you see a post-induction key checkpoint that is not a theorem, stop
 looking at the checkpoints!  Your original conjecture is not a theorem!  Fix
 it.</p>

 <p>If you're convinced all the post-induction conjectures are theorems, ask
 whether each has the hypotheses you'd need to prove it.  If the case analysis
 feels inappropriate or induction hypotheses seem to be missing, then ACL2
 might have done the wrong induction.  Find the induction scheme it did by
 reading the first induction message printed after the conjecture was
 submitted.  If it is wrong, then extend ACL2's induction analysis or tell ACL2
 what induction to do, as explained shortly.</p>

 <p>But before you decide the induction hypothesis is missing, look closely for
 contradictions among the hypotheses of the checkpoint formula.  For example,
 perhaps one of the hypotheses is @('(MEMBER e x)') and another is <tt>(NOT
 (MEMBER e' x'))</tt> where @('e'), @('x'), @('e''), and @('x'') are possibly
 complicated expressions.</p>

 <p>Is it possible that @('e') and @('e'') are equal and @('x') and @('x'') are
 equal?  If so, then the two hypotheses are contradictory and the checkpoint
 would be proved if you could find rules that would simplify those expressions
 to their common forms.  So look for theorems about those subexpressions.</p>

 <p>Or maybe you can get @('e') and @('e'') to reduce to some common @('d') but
 but find that @('x') and @('x'') are really different.  Then ask whether</p>

 @({
  (implies (member d x) (member d x'))
 })

 <p>If you could prove that, the key checkpoint would be proved.  Of course,
 you may need other hypotheses from the checkpoint to state your theorems.</p>

 <p>If you have been working your way through the tutorial introduction to the
 theorem prover, use your browser's <b>Back Button</b> now to @(see
 introduction-to-key-checkpoints).</p>")

(defxdoc pprogn
  :parents (programming-with-state acl2-built-ins)
  :short "Evaluate a sequence of forms that return @(see state)"
  :long "@({
  Example Form:
  (pprogn
   (cond ((or (equal (car l) #\\) (equal (car l) slash-char))
          (princ$ #\\ channel state))
         (t state))
   (princ$ (car l) channel state)
   (mv (cdr l) state))
 })

 <p>The convention for @('pprogn') usage is to give it a non-empty sequence of
 forms, each of which (except possibly for the last) returns state (see @(see
 state)) as its only value.  The @(see state) returned by each but the last is
 passed on to the next.  The value or values of the last form are returned as
 the value of the @('pprogn').</p>

 <p>If you are using single-threaded objects you may wish to define an analogue
 of this function for your own @(see stobj).</p>

 <p>General Form:</p>

 @({
  (PPROGN form1
          form2
          ...
          formk
          result-form)
 })

 <p>This general form is equivalent, via macro expansion, to:</p>

 @({
  (LET ((STATE form1))
       (LET ((STATE form2))
            ...
            (LET ((STATE formk))
                 result-form)))
 })")

(defxdoc pr
  :parents (history)
  :short "Print the rules stored by the event with the given name"
  :long "@({
  Examples:

  :pr fn ; prints the rules from the definition of fn (including any
         ; :type-prescription rule and :definition rule)

  :pr assoc-append ; if assoc-append is a rewrite rule, prints that rule
 })

 <p>Also see @(see pr!), which is similar but works at the command level
 instead of at the event level, and see @(see pl), which displays all rewrite
 rules for calls of @('fn'), not just those introduced at definition time.</p>

 <p>@('Pr') takes one argument, a logical name, and prints the rules associated
 with it.  In each case it prints the rune, the current enabled/disabled
 status, and other appropriate fields from the rule.  It may be helpful to read
 the documentation for various kinds of rules in order to understand the
 information printed by this command.  For example, the information printed for
 a linear rule might be:</p>

 @({
    Rune:     (:LINEAR ABC)
    Enabled:  T
    Hyps:     ((CONSP X))
    Concl:    (< (ACL2-COUNT (CAR X)) (ACL2-COUNT X))
    Max-term: (ACL2-COUNT (CAR X))
    Backchain-limit-lst:    (3)
 })

 <p>The @('hyps') and @('concl') fields for this rule are fairly
 self-explanatory, but it is useful to see @(see linear) to learn about maximal
 terms (which, as one might guess, are stored under ``Max-term'').</p>

 <p>Currently, this function does not print congruence rules or equivalence
 rules.</p>

 <p>The expert user might also wish to use @(tsee find-rules-of-rune).  See
 @(see find-rules-of-rune).</p>")

(defxdoc pr!
  :parents (history)
  :short "Print rules stored by the command with a given command descriptor"
  :long "@({
  Examples:

  :pr! fn ; prints the rules from the definition of fn (including any
          ; :type-prescription rule and :definition rule), as well as all other
          ; rules created by the command that created by fn (which could be
          ; many rules if, for example, fn was defined by an include-book
          ; command).

  :pr! :max ; prints all the rules stored by the most recent command
 })

 <p>Also see @(see pr), which is similar but works at the event level instead
 of at the command level.</p>

 <p>@(tsee Pr) takes one argument, a command descriptor, and prints the rules
 created by the corresponding event.  In each case it prints the rune, the
 current enabled/disabled status, and other appropriate fields from the rule.
 See @(see pr) for further details.</p>")

(defxdoc practice-formulating-strong-rules
  :parents (introduction-to-the-theorem-prover)
  :short "A few simple checkpoints suggesting strong rules"
  :long "<p>Consider these definitions:</p>

 @({
  (defun rev (x)
    (if (endp x)
        nil
        (append (rev (cdr x)) (list (car x)))))

  (defun nats-below (j)
    (if (zp j)
        '(0)
        (cons j (nats-below (- j 1)))))
 })

 <p>We assume you are familiar with such ACL2 built-ins as @('append'),
 @('member'), @('subsetp') and @('true-listp').  When we use throw-away names
 like @('FOO'), @('BAR'), and @('MUM') below we mean to suggest some arbitrary
 function you shouldn't think about!  We're just trying to train your eye to
 ignore irrelevant things.</p>

 <p>Below are some terms that should suggest rewrite rules to you.  Imagine
 that each of these terms occurs in some Key Checkpoint.  What rules come to
 mind?  Try to think of the strongest rules you can.</p>

 <p>Term 1:<br></br>

 @('(TRUE-LISTP (APPEND (FOO A) (BAR B)))')</p>

 <p>Answers: See @(see practice-formulating-strong-rules-1)</p>

 <p>Term 2:<br></br>

 @('(TRUE-LISTP (REV (FOO A)))')</p>

 <p>Answers: See @(see practice-formulating-strong-rules-2)</p>

 <p>Term 3:<br></br>

 @('(MEMBER (FOO A) (APPEND (BAR B) (MUM C)))')</p>

 <p>Answers: See @(see practice-formulating-strong-rules-3)</p>

 <p>Term 4:<br></br>

 @('(SUBSETP (APPEND (FOO A) (BAR B)) (MUM C))')</p>

 <p>Answers: See @(see practice-formulating-strong-rules-4)</p>

 <p>Term 5:<br></br>

 @('(SUBSETP (FOO A) (APPEND (BAR B) (MUM C)))')</p>

 <p>Answers: See @(see practice-formulating-strong-rules-5)</p>

 <p>Term 6:<br></br>

 @('(MEMBER (FOO A) (NATS-BELOW (BAR B)))')</p>

 <p>Answers: See @(see practice-formulating-strong-rules-6)</p>

 <p>We recommend doing all of these little exercises.  When you're finished,
 use your browser's <b>Back Button</b> to return to @(see
 strong-rewrite-rules).</p>")

(defxdoc practice-formulating-strong-rules-1
  :parents (introduction-to-the-theorem-prover)
  :short "Rules suggested by @('(TRUE-LISTP (APPEND (FOO A) (BAR B)))')"
  :long "<p>What rules come to mind when looking at the following subterm of a
 Key Checkpoint?  Think of <i>strong</i> rules (see @(see
 strong-rewrite-rules)).</p>

 @({
  (TRUE-LISTP (APPEND (FOO A) (BAR B)))
 })

 <p>Obviously, you must think about the conditions under which @('(APPEND x
 y)') returns a true-list.  Recall that @('APPEND') concatenates @('x') and
 @('y'), with @('y') being the terminal sublist.  Its definition is equivalent
 to</p>

 @({
  (defun append (x y)
    (if (endp x)
        y
        (cons (car x)
              (append (cdr x) y))))
 })

 <p>Technical Note: @('Append') is really a macro that permits you to write
 calls of @('append') with more than two arguments.</p>

 <p>In a sense, @('append') ``expects'' its arguments to be lists ending in
 @('nil'), so-called @('true-listp')s.  (Such expectations are formalized in
 ACL2 by the notion of the ``@(see guard)'' <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 of the function, but we strongly recommend not investigating guards until
 you're good at using the system.)</p>

 <p>New users frequently start every new theorem by listing all their
 expectations on the arguments of functions in the problem.  For example, if
 the new user wants to make some statement about when @('(append x y)') is a
 @('true-listp'), it is not uncommon for him or her first to write:</p>

 @({
  (implies (and (true-listp x)
                (true-listp y))
           ...)
 })

 <p>to get ``comfortable.''  Then, thinking about when @('(append x y)') is a
 @('true-listp') is easy: it always returns a @('true-listp').  It's always a
 @('true-listp').''  This thinking produces the theorem:</p>

 @({
  (defthm true-listp-append-really-weak
    (implies (and (true-listp x)
                  (true-listp y))
             (true-listp (append x y))))
 })

 <p>You'll note we gave it a name suggesting it is ``really weak.''</p>

 <p>One sense in which it is weak is that it has an unnecessary hypothesis.  If
 @('y') is a @('true-listp'), then @('(append x y)') is too, whether @('x') is
 a @('true-listp') or not.  In ACL2, all functions are total.  Logically
 speaking, it doesn't matter whether @('endp') expects its argument to be a
 @('true-listp') or not, it behaves.  @('(Append x y)') either returns @('y')
 or a @('cons') whose second argument is generated by @('append').  Thus, if
 @('y') is a @('true-listp'), the answer is too.  So here is an improved
 version of the rule:</p>

 @({
  (defthm true-listp-append-weak
    (implies (true-listp y)
             (true-listp (append x y))))
 })

 <p>We still think of it as ``weak'' because it has a hypothesis that limits
 its applicability.</p>

 <p>The strong version of the rule is</p>

 @({
  (defthm true-listp-append-strong
    (equal (true-listp (append x y))
           (true-listp y))).
 })

 <p>That is, @('append') returns a @('true-listp') <i>precisely</i> when its
 second argument is a @('true-listp').  We recommend that the strong version be
 made a :@(tsee rewrite) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> rule.</p>

 <p>The weak version of the rule allows us to reduce @('(TRUE-LISTP (APPEND x
 y))') to true if we can show that @('(TRUE-LISTP y)') is true.  But suppose
 @('(TRUE-LISTP y)') is actually false.  Then @('(TRUE-LISTP (APPEND x y))')
 would not simplify under the weak version of the rule.  But under the strong
 version it would simplify to @('NIL').</p>

 <p>Technical Note: The weak version of the rule is a useful :@(tsee
 type-prescription) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> rule.  The type mechanism cannot currently exploit
 the strong version of the rule.</p>

 <p>The strategy of ``getting comfortable'' by adding a bunch of hypotheses
 before you know you need them is not conducive to creating strong rules.  We
 tend to state the main relationship that we intuit about some function and
 then add the hypotheses we need to make it true.  In this case, there were no
 necessary hypotheses.  But if there are, we first identify them and then we
 ask ``what can I say about the function if these hypotheses aren't true?''
 and try to strengthen the statement still further.</p>

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 practice-formulating-strong-rules).</p>")

(defxdoc practice-formulating-strong-rules-2
  :parents (introduction-to-the-theorem-prover)
  :short "Rules suggested by @('(TRUE-LISTP (REV (FOO A)))')"
  :long "<p>What rules come to mind when looking at the following subterm of a
 Key Checkpoint?  Think of <i>strong</i> rules (see @(see
 strong-rewrite-rules)).</p>

 @({
  (TRUE-LISTP (REV (FOO A)))
 })

 <p>The definition of @('rev') in this problem is</p>

 @({
  (defun rev (x)
    (if (endp x)
        nil
        (append (rev (cdr x)) (list (car x)))))
 })

 <p>Since the definition terminates with an @('endp') test and otherwise
 @('cdr')s the argument, the author of @('rev') was clearly expecting @('x') to
 be a @('true-listp').  (Indeed, the ``@(see guard)'' <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 for @('rev') must include @('(true-listp x)') since that is @('endp')'s
 guard.)  So you're naturally justified in limiting your thoughts about @('(rev
 x)') to @('x') that are true-lists.  This gives rise to the theorem:</p>

 @({
  (defthm true-listp-rev-weak
    (implies (true-listp x)
             (true-listp (rev x))))
 })

 <p>This is the kind of thinking illustrated in the earlier @('append') example
 (see @(see practice-formulating-strong-rules-1)), and, to paraphrase Z in
 <i>Men in Black</i>, it exemplifies ``everything we've come to expect from
 years of training with typed languages.''</p>

 <p>But logically speaking, the definition of @('rev') does not require @('x')
 to be a @('true-listp').  It can be any object at all: ACL2 functions are
 total.  @('Rev') either returns @('nil') or the result of appending a
 singleton list onto the right end of its recursive result.  That call of
 @('append') always returns a @('true-listp') since the singleton list is a
 true list.  (See @(see practice-formulating-strong-rules-1).)</p>

 <p>So this is a theorem and a very useful :@(tsee rewrite) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 rule:</p>

 @({
  (defthm true-listp-rev-strong
    (true-listp (rev x))).
 })

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 practice-formulating-strong-rules).</p>")

(defxdoc practice-formulating-strong-rules-3
  :parents (introduction-to-the-theorem-prover)
  :short "Rules suggested by @('(MEMBER (FOO A) (APPEND (BAR B) (MUM C)))')"
  :long "<p>What rules come to mind when looking at the following subterm of a
 Key Checkpoint?  Think of <i>strong</i> rules (see @(see
 strong-rewrite-rules)).</p>

 @({
  (MEMBER (FOO A) (APPEND (BAR B) (MUM C)))
 })

 <p>Since @('(append x y)') contains all the members of @('x') and all the
 members of @('y'), @('e') is a member of @('(append x y)') precisely when
 @('e') is a member of @('x') or of @('y').  So a strong statement of this
 is:</p>

 @({
  (defthm member-append-strong-false
    (equal (member e (append x y))
           (or (member e x)
               (member e y))))
 })

 <p>However, this is not a theorem because @('member') is not Boolean.
 @('(Member e x)'), for example, returns the first tail of @('x') that starts
 with @('e'), or else @('nil').  To see an example of this formula that
 evaluates to @('nil'), let</p>

 @({
  e = 3
  x = '(1 2 3)
  y = '(4 5 6).
 })

 <p>Then the left-hand side, @('(member e (append x y))') evaluates to @('(3 4
 5 6)') while the right-hand side evaluates to @('(3)').</p>

 <p>However, the two sides are propositionally equivalent (both either @('nil')
 or non-@('nil') together).  So this is a useful :@(tsee rewrite) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 rule:</p>

 @({
  (defthm member-append-strong
    (iff (member e (append x y))
         (or (member e x)
             (member e y)))).
 })

 <p>It tells the system that whenever it encounters an instance of @('(MEMBER e
 (APPEND x y))') in a propositional occurrence (where only its truth value is
 relevant), it should be replaced by this disjunction of @('(MEMBER e x)') and
 @('(MEMBER e y)').</p>

 <p>The following two formulas are true but provide much weaker rules and we
 would not add them:</p>

 @({
  (implies (member e x) (member e (append x y)))

  (implies (member e y) (member e (append x y)))
 })

 <p>because they each cause the system to backchain upon seeing @('(MEMBER e
 (APPEND x y))') expressions and will not apply unless one of the two
 side-conditions can be established.</p>

 <p>There is a rewrite rule that is even stronger than
 @('member-append-strong').  It is suggested by the counterexample, above, for
 the @('EQUAL') version of the rule.</p>

 @({
  (defthm member-append-really-strong
    (equal (member e (append x y))
           (if (member e x)
               (append (member e x) y)
               (member e y))))
 })

 <p>While @('member-append-strong') only rewrites @('member-append')
 expressions occurring propositionally, the @('-really-strong') version
 rewrites <i>every</i> occurrence.</p>

 <p>However, this rule will be more useful than @('member-append-strong') only
 if you have occurrences of @('member') in non-propositional places.  For
 example, suppose you encountered a term like:</p>

 @({
  (CONS (MEMBER e (APPEND x y)) z).
 })

 <p>Then the @('-strong') rule does not apply but the @('-really-strong') rule
 does.</p>

 <p>Furthermore, the @('-really-strong') rule, by itself, is not quite as good
 as the @('-strong') rule in propositional settings!  For example, if you have
 proved the @('-really-strong') rule, you'll notice that the system still has
 to use induction to prove</p>

 @({
  (IMPLIES (MEMBER E A)
           (MEMBER E (APPEND B A))).
 })

 <p>The @('-really-strong') rule would rewrite it to</p>

 @({
  (IMPLIES (MEMBER E A)
           (IF (MEMBER E A)
               (APPEND (MEMBER E A) B)
               (MEMBER E B)))
 })

 <p>which would further simplify to</p>

 @({
  (IMPLIES (MEMBER E A)
           (APPEND (MEMBER E A) B))
 })

 <p>What lemma does this suggest?  The answer is the rather odd:</p>

 @({
  (implies x (append x y))
 })

 <p>which rewrites propositional occurrences of @('(APPEND x y)') to @('T') if
 @('x') is non-@('nil').  This is an inductive fact about @('append').</p>

 <p>A problem with the @('-really-strong') rule is that it transforms even
 propositional occurrences of @('member') into mixed propositional and
 non-propositional occurrences.</p>

 @({
  (defthm member-append-really-strong
    (equal (member e (append x y))      ; <-- even if this is a propositional occurrence
           (if (member e x)
               (append (member e x) y)  ; <-- the member in here is not!
               (member e y))))
 })

 <p>So if you are using the @('-really-strong') lemma in a situation in which
 all your @('member') expressions are used propositionally, you'll suddenly
 find yourself confronted with non-propositional uses of @('member').</p>

 <p>Our advice is not to use the @('-really-strong') version unless your
 application is inherently using @('member') in a non-propositional way.</p>

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 practice-formulating-strong-rules).</p>")

(defxdoc practice-formulating-strong-rules-4
  :parents (introduction-to-the-theorem-prover)
  :short "Rules suggested by @('(SUBSETP (APPEND (FOO A) (BAR B)) (MUM C))')"
  :long "<p>What rules come to mind when looking at the following subterm of a
 Key Checkpoint?  Think of <i>strong</i> rules (see @(see
 strong-rewrite-rules)).</p>

 @({
  (SUBSETP (APPEND (FOO A) (BAR B)) (MUM C))
 })

 <p>When is @('(append x y)') a subset of @('z')?  When everything in @('x') is
 in @('z') and everything in @('y') is in @('z').  We would make it a rewrite
 rule:</p>

 @({
  (defthm subsetp-append-1-strong
    (equal (subsetp (append x y) z)
           (and (subsetp x z)
                (subsetp y z))))
 })

 <p>We put the ``@('-1-')'' in the name because there is a comparable theorem
 for when the @('append') is in the second argument of the @('subsetp'); see
 @(see practice-formulating-strong-rules-5).</p>

 <p>This strong rule is better than the conditional rule;</p>

 @({
  (defthm subsetp-append-1-weak
    (implies (and (subsetp x z)
                  (subsetp y z))
             (subsetp (append x y) z)))
 })

 <p>for all the usual reasons.</p>

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 practice-formulating-strong-rules).</p>")

(defxdoc practice-formulating-strong-rules-5
  :parents (introduction-to-the-theorem-prover)
  :short "Rules suggested by @('(SUBSETP (FOO A) (APPEND (BAR B) (MUM C)))')"
  :long "<p>What rules come to mind when looking at the following subterm of a
 Key Checkpoint?  Think of <i>strong</i> rules (see @(see
 strong-rewrite-rules)).</p>

 @({
  (SUBSETP (FOO A) (APPEND (BAR B) (MUM C)))
 })

 <p>When is @('x') a subset of @('(append y z)')?  Clearly it is if @('x') is a
 subset of @('y') or @('x') is a subset of @('z').  We could write that:</p>

 @({
  (defthm subsetp-append-2-weak
    (implies (or (subsetp x y)
                 (subsetp x z))
             (subsetp x (append y z))))
 })

 <p>The rule generated from this is: ``if you ever encounter (an instance of)
 @('(SUBSETP x (APPEND y z))'), backchain to the @('or') above and try to
 establish it.  If you can establish it, replace the target by @('T').''</p>

 <p>This does not fully characterize the situation though.  For example, @(''(1
 2 3 4)') is a subset of @('(append '(1 3) '(2 4))') without being a subset of
 either argument of the @('append').</p>

 <p>However, no obvious equivalence comes to mind &mdash; indeed, to express
 any of the ideas floating around here requires defining and introducing more
 functions, which is not recommended unless those functions are already in the
 problem.</p>

 <p>For example, if you defined the concept of ``@('set-minus')'' so that
 @('(set-minus x y)') consists of those elements of @('x') not in @('y'), then
 you could prove:</p>

 @({
  (defthm subset-append-2-strong-but-messy
    (equal (subsetp x (append y z))
           (and (subsetp (set-minus x z) y)
                (subsetp (set-minus x y) z))))
 })

 <p>But this rewrite rule would ``trade'' @('append') away and introduce
 @('set-minus').  That might be a good strategy if @('set-minus') were already
 in the problem.  But if it were not, it might not be.  We wouldn't recommend
 this rule unless it were helpful in normalizing the expressions in the
 problem.</p>

 <p>We recommend sticking with the weak version of the rule,</p>

 @({
  (defthm subsetp-append-2-weak
    (implies (or (subsetp x y)
                 (subsetp x z))
             (subsetp x (append y z)))).
 })

 <p>This illustrates the fact that sometimes there is no strong version of a
 rule!</p>

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 practice-formulating-strong-rules).</p>")

(defxdoc practice-formulating-strong-rules-6
  :parents (introduction-to-the-theorem-prover)
  :short "Rules suggested by @('(MEMBER (FOO A) (NATS-BELOW (BAR B)))')"
  :long "<p>What rules come to mind when looking at the following subterm of a
 Key Checkpoint?  Think of <i>strong</i> rules (see @(see
 strong-rewrite-rules)).</p>

 @({
  (MEMBER (FOO A) (NATS-BELOW (BAR B)))
 })

 <p>The definition of @('NATS-BELOW') is</p>

 @({
  (defun nats-below (j)
    (if (zp j)
        '(0)
        (cons j (nats-below (- j 1)))))
 })

 <p>Thus, @('(nats-below 7)') is @('(7 6 5 4 3 2 1 0)').  So when is @('k') a
 member of @('(nats-below j)')?</p>

 <p>The weakest version is</p>

 @({
  (defthm member-nats-below-weak
    (implies (and (natp k)
                  (natp j)
                  (<= k j))
             (member k (nats-below j))))
 })

 <p>But clearly we could improve this to:</p>

 @({
  (defthm member-nats-below-weak-better
    (implies (and (natp k)
                  (natp j))
             (iff (member k (nats-below j))
                  (<= k j))))
 })

 <p>or even</p>

 @({
  (defthm member-nats-below-weak-better
    (implies (natp j)
             (iff (member k (nats-below j))
                  (and (natp k)
                       (<= k j)))))
 })

 <p>Clearly though, we'd like to get rid of the @('(natp j)') hypothesis and
 the neatest plausible version is:</p>

 @({
  (defthm member-nats-below-weak-neatest
    (iff (member k (nats-below j))
         (and (natp j)
              (natp k)
              (<= k j))))
 })

 <p>But it is not a theorem!  For example, if @('j') is @('-1') and @('k') is
 0, then the left-hand side above returns @('t'), because @('(nats-below j)')
 is @('(0)'), but the right-hand side is @('nil').</p>

 <p>But this suggests a strategy for dealing with necessary hypotheses, like
 @('(natp j)').  We can move them into an @('IF') on the right-hand side!
 Something like this might be a useful rewrite rule:</p>

 @({
  (iff (member k (nats-below j))
       (if (natp j)
           (and (natp k)
                (<= k j))
           ...)).
 })

 <p>We know, from @('member-nats-below-weak-better'), that if @('(natp j)') is
 true, the @('member') is equivalent to @('(and (natp k) (<= k j))').  So now
 consider what we know if @('(natp j)') is false.  If we can think of some term
 it's equivalent to and that term is simpler than the @('member') expression,
 we have a strong rule.</p>

 <p>But by inspection of the definition of @('nats-below'), we see that when
 @('(natp j)') is false, @('(nats-below j)') is the list @('(0)') because
 @('(zp j)') is t.  That is, @('nats-below') treats all non-natural arguments
 like they were @('0').  Thus, when @('(natp j)') is false, @('(member k
 (nats-below j))') is @('(member k '(0))'), which is @('(equal k 0)').</p>

 <p>So the strong version is</p>

 @({
  (defthm member-nats-below-strong
     (iff (member k (nats-below j))
          (if (natp j)
              (and (natp k)
                   (<= k j))
              (equal k 0))))
 })

 <p>This is a great :@(tsee rewrite) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 rule.  It gets rid of the @('member') and @('nats-below') and introduces
 arithmetic.</p>

 <p>This example illustrates the idea of putting an @('if') on the
 right-hand-side of the equivalence.  Many users tend to limit themselves to
 propositional forms inside @('iff') or to simple expressions inside of
 @('equal').  But it is quite natural to use @('if') to express what the answer
 is: if @('j') is a natural, then @('k') is in @('(nats-below j)') precisely if
 @('k') is a natural less than or equal to @('j'); if @('j') is not a natural,
 then @('k') is in @('(nats-below j)') precisely if @('k') is @('0').</p>

 <p>Use @('if') to lay out the cases you must consider, if you can think of a
 simpler, equivalent expression for every possible case.</p>

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 practice-formulating-strong-rules).</p>")

(defxdoc primitive
  :parents (programming acl2-built-ins)
  :short "Primitive functions built into ACL2 without definitions"
  :long "<p>The ACL2 @(see ground-zero) @(see theory) includes axioms about
 some built-in functions that are not given explicit definitions, such as
 @(tsee <), @(tsee car), and @(tsee symbolp).  We sometimes call such functions
 <i>primitives</i>.  The built-in constant @('*primitive-formals-and-guards*')
 is an alist that associates each primitive with its list of formals and its
 @(see guard); that is, each element of that alist is of the form @('(name
 formals guard)').  The value of this constant is displayed below.</p>

 @(def *primitive-formals-and-guards*)")

(defxdoc princ$
  :parents (io acl2-built-ins)
  :short "Print an atom"
  :long "<p>Use @('princ$') to do basic printing of atoms (i.e., other than
 @('cons') pairs).  In particular, @('princ$') prints a string without the
 surrounding double-quotes and without escaping double-quote characters within
 the string.  Note that @('princ$') is sensitive to the print-base,
 print-radix, and print-case; see @(see set-print-base-radix) and see @(see
 set-print-case).  @('Princ$') returns @(tsee state).</p>

 @({
  Examples:
  ACL2 !>(princ$ \"Howdy ho\" (standard-co state) state)
  Howdy ho<state>
  ACL2 !>(pprogn (princ$ \"Howdy ho\" (standard-co state) state)
                 (newline (standard-co state) state))
  Howdy ho
  <state>
  ACL2 !>(princ$ \"ab\\\"cd\" *standard-co* state)
  ab\"cd<state>
  ACL2 !>
  ACL2 !>(princ$ 17 *standard-co* state)
  17<state>
  ACL2 !>(set-print-base 16 state) ; might be nicer to use set-print-base-radix
  <state>
  ACL2 !>(princ$ 17 *standard-co* state)
  11<state>
  ACL2 !>(set-print-radix t state)
  <state>
  ACL2 !>(princ$ 17 *standard-co* state)
  #x11<state>
  ACL2 !>(princ$ 'xyz *standard-co* state)
  XYZ<state>
  ACL2 !>(set-print-case :downcase state)
  <state>
  ACL2 !>(princ$ 'xyz *standard-co* state)
  xyz<state>
  ACL2 !>
 })

 <p>The @(see guard) for @('(princ$ x channel state)') is essentially as
 follows; see @(see io) for an explanation of guards of certain built-in
 functions that take @(see state), such as @('princ$').</p>

 @({
  (and (or (acl2-numberp x)
           (characterp x)
           (stringp x)
           (symbolp x))
       (state-p1 state-state)
       (symbolp channel)
       (open-output-channel-p1 channel :character state-state))
 })

 <p>See @(see fmt) for more sophisticated printing routines, and see @(see IO)
 for general information about input and output.</p>")

(defxdoc print-base-p
  :parents (io acl2-built-ins)
  :short "Recognizer for print bases that are understood by functions such as
@(see explode-nonnegative-integer) and @(see explode-atom)."
  :long "@(def print-base-p)")

(defxdoc print-control
  :parents (io)
  :short "Advanced controls of ACL2 printing"
  :long "<p>See @(see IO) for a summary of printing in ACL2.  Here we document
 some advanced ways to control what is printed by ACL2's primary printing
 routines.</p>

 <p>See @(tsee set-print-base-radix), @(tsee set-print-base), @(tsee
 set-print-radix), and @(tsee set-print-case) for discussions of the most
 common ways to control what is printed.  Indeed, these are the only ways to
 control the behavior of @(tsee princ$) and @('prin1$').</p>

 <p>See @(tsee set-fmt-hard-right-margin) for how to set the right margin for
 prover output and, more generally, output from formatted printing
 functions (see @(tsee fmt)).  Note that @('set-print-right-margin'), mentioned
 below, does not affect such printing.</p>

 <p>The rest of this topic is for advanced users of ACL2.  We refer to Common
 Lisp behavior, as described in any good Common Lisp documentation.</p>

 <p><b>Print-control variables</b>.  @(tsee Set-print-base), @(tsee
 set-print-radix), and @(tsee set-print-case) assign to corresponding so-called
 ``@(see state) global variables'' @(''print-base'), @(''print-radix'), and
 @(''print-case'), which can be accessed using the expressions @('(@
 print-base)'), @('(@ print-radix)'), and @('(@ print-case)'), respectively;
 see @(see assign).  Here is a table showing all print-control variables, their
 setters, and their defaults.  Also see @(tsee set-print-base-radix).</p>

 @({
  print-base          set-print-base          10
  print-case          set-print-case          :upcase
  print-circle        set-print-circle        nil
    [but see remark on print-circle-files, below]
  print-escape        set-print-escape        t
  print-length        set-print-length        nil
  print-level         set-print-level         nil
  print-lines         set-print-lines         nil
  print-pretty        set-print-pretty        nil
  print-radix         set-print-radix         nil
  print-readably      set-print-readably      nil
  print-right-margin  set-print-right-margin  nil
 })

 <p>Each ACL2 print-control variable @('print-xxx') can correspond in function
 to Common Lisp variable @('*PRINT-XXX*').  Specifically, the evaluation of
 forms @('(set-print-base t)'), @('(set-print-radix t)'), and
 @('(set-print-case t)') affects ACL2 printing functions in much the same way
 that setting to @('t') Common Lisp variables @('*PRINT-BASE*'),
 @('*PRINT-RADIX*'), and @('*PRINT-CASE*'), respectively, affects Common Lisp
 printing.  The same is true for @('print-escape'), except that this does not
 affect @(tsee princ$) or @('prin1$'), which correspond to Common Lisp
 functions @('princ') and @('prin1'): @('princ') treats @('*PRINT-ESCAPE*') as
 @('nil') while @('prin1') treats @('*PRINT-ESCAPE*') as @('t').  Moreover, all
 print-control variables not mentioned in this paragraph are set to their
 defaults in @(tsee princ$) and @('prin1$'), as indicated by ACL2 constant
 @('*print-control-defaults*'), except that @('print-readably') is set to
 @('nil') in @('princ$').</p>

 <p>@(tsee Fmt) and its related functions are sensitive to state globals
 @(''print-base'), @(''print-radix'), @(''print-case'), @(''print-escape'), and
 @(''print-readably'), in analogy with Common Lisp functions that don't fix
 @('*PRINT-ESCAPE*') or @('*PRINT-READABLY*').  But the @(tsee fmt) functions
 do not respect settings of other print-control variables; for example, they
 act as though @(''print-circle') is @('nil').  Since ACL2 output is produced
 using the same underlying print routines as the @(tsee fmt) functions, it also
 is insensitive to all print-control variables except for the five above.  To
 control the print-level and print-length used for producing ACL2 output, see
 @(see set-evisc-tuple).</p>

 <p>@(see Print-object$) and @(see print-object$-preserving-case) are sensitive
 to the values of all of the print-control variables except for
 @(''print-escape').</p>

 <p>Evaluate @('(reset-print-control)') to restore all print-control variables
 to their original settings, as stored in constant
 @('*print-control-defaults*').</p>

 <p>(Remark on @('print-circle-files'): ACL2 typically binds @(''print-circle')
 to @('t') before writing @(see certificate) files, or auxiliary files that are
 compiled when @(tsee make-event) forms are present in a book, or files in
 support of @(':')@(tsee comp) commands.  This binding allows for structure
 sharing that can keep these files from growing large.  End of Remark.)</p>

 <p>(Remark for those using ACL2 built on CLtL1 (non-ANSI) Gnu Common
 Lisp (GCL): Note that Common Lisp variables @('*PRINT-LINES*'),
 @('*PRINT-MISER-WIDTH*'), @('*PRINT-READABLY*'), @('*PRINT-PPRINT-DISPATCH*'),
 and @('*PRINT-RIGHT-MARGIN*') do not have any effect for such GCL
 versions.)</p>")

(defxdoc print-gv

; The following example could be the basis of additional documentation, to
; clarify what is meant when a natural number is specified for :substitute.
; But such an example might add noise more than it adds clarification.

;   (defun foo (x)
;     (declare (xargs :guard (and (integerp x) (< 0 x))))
;     (list x x))
;   (foo t) ; guard violation
;
;   Then:
;
;   ACL2 !>(print-gv :substitute 2)
;
;   (FLET ((FOO{GUARD} (X)
;                      (DECLARE (IGNORABLE X))
;                      (AND (INTEGERP X) (< 0 X))))
;         (FOO{GUARD} T))
;
;   ACL2 !>(print-gv :substitute 3)
;
;   (AND (INTEGERP T) (< 0 T))
;
;   ACL2 !>
;
;   Reason: the cons-count of the translation (quote t) of t is 2.
;   The cons-count must be less than the given natural number :substitute
;   argument in order to avoid FLET.

  :parents (guard debugging)
  :short "Print a form whose evaluation caused a guard violation"
  :long "<p>By default, ACL2 checks input constraints on functions, known as
 @(see guard)s.  When guards are violated, an informative message is printed;
 but sometimes it is useful to investigate why the guard check fails.  The
 utility @('print-gv') is provided for that purpose.  (Alternatively, you may
 prefer to avoid guards entirely with @('(set-guard-checking :none)'); see
 @(see set-guard-checking).)</p>

 @({
  Example Forms:
  (print-gv)
  :print-gv ; same as above
  (print-gv ; same as above, showing all system defaults
   :conjunct nil
   :evisc-tuple (print-gv-evisc-tuple)
   :substitute nil)
  (print-gv :substitute 20)
  (print-gv :evisc-tuple (evisc-tuple 4 4 nil nil))
  (print-gv :evisc-tuple (evisc-tuple 4 4 nil nil))
  (print-gv :evisc-tuple (evisc-tuple 4 ; print-level
                                      5 ; print-length
                                      (world-evisceration-alist state nil)
                                      nil ; hiding-cars
                                      ))
 })

 @({
  General Form:
  (print-gv :conjunct c
            :substitute s
            :evisc-tuple e)
 })

 <p>where the keyword arguments are optional.  These arguments have the
 following effects and system defaults, but note that the defaults can be
 changed by the user; see @(see set-print-gv-defaults).</p>

 <p>The @(':conjunct') argument is @('nil') by default, indicating that a form
 is to be displayed whose evaluation represents the @(see guard) evaluation
 that produced @('nil').  A value of @('t') indicates that ACL2 should parse
 the guard into conjuncts, and display the conjunct that actually evaluated to
 @('nil').  It does this by evaluating each conjunct in turn until one produces
 a result of @('nil').</p>

 <p>The @(':evisc-tuple') argument should be an @(see evisc-tuple).  Its
 default is the value of the expression @('(print-gv-evisc-tuple)'), which
 specifies hiding only the ACL2 logical @(see world), so that the symbol
 @('<world>') is printed instead of the actual world.  See @(see evisc-tuple)
 for a discussion of evisc-tuples.</p>

 <p>The @(':substitute') argument is @('nil') by default, indicating that the
 displayed form uses @(tsee flet), which avoids duplicate occurrences of actual
 parameters.  A value of @('t') indicates that ACL2 should instead substitute
 those actuals into the guard.  Otherwise the value should be a natural number
 @('n'), which behaves the same as @('nil') except when large duplicated terms
 are to be avoided in the precise sense below, in which case the behavior is
 the same as @('t'), that is, @('flet') is used.  The latter case (using
 @('flet')) applies when some variable in the guard or (if @(':conjunct t') is
 specified) conjunct has at least two occurrences, and corresponds to an actual
 parameter with at least @('n') conses.  Note that the number of conses is
 counted in the ``translated'' term (guard or conjunct); see @(see term).</p>

 <p>Again, the user can change these defaults; see @(see
 set-print-gv-defaults).  For example, one might wish to evaluate
 @('(set-print-gv-defaults :substitute 20) so that @(tsee flet) is used only
 when that avoids certain duplicated large terms, as discussed just above.</p>

 <p>To see how one might use @('print-gv'), consider the following
 definition.</p>

 @({
 (defun foo (x)
   (declare (xargs :guard (and (integerp x)
                               (posp (+ -2 x))
                               (posp (+ 3 x))
                               (posp (+ -4 x)))))
   x)
 })

 <p>Now suppose we evaluate a call of foo and obtain a guard violation.</p>

 @({
 ACL2 !>(foo 1)


 ACL2 Error in TOP-LEVEL:  The guard for the function call (FOO X),
 which is (AND (INTEGERP X) (POSP (+ -2 X)) (POSP (+ 3 X)) (POSP (+ -4 X))),
 is violated by the arguments in the call (FOO 1).
 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.
 })

 <p>Let us investigate this guard failure.  First we use @('print-gv') to
 obtain a form that represents our guard violation.  Just for fun, we'll check
 that it indeed evaluates to @('nil').</p>

 @({
 ACL2 !>:print-gv

 (FLET ((FOO{GUARD} (X)
                    (DECLARE (IGNORABLE X))
                    (AND (INTEGERP X)
                         (POSP (+ -2 X))
                         (POSP (+ 3 X))
                         (POSP (+ -4 X)))))
       (FOO{GUARD} 1))

 ACL2 !>(FLET ((FOO{GUARD} (X)
                   (DECLARE (IGNORABLE X))
                   (AND (INTEGERP X)
                        (POSP (+ -2 X))
                        (POSP (+ 3 X))
                        (POSP (+ -4 X)))))
              (FOO{GUARD} 1))
 NIL
 })

 <p>This form doesn't tell us which of the four conjuncts actually evaluated to
 @('nil').  We can fix that by using the @(':conjunct') keyword argument.</p>

 @({
 ACL2 !>(print-gv :conjunct t)

 Showing guard conjunct (#2 of 4) that evaluates to nil:

 (FLET ((FOO{GUARD} (X) (POSP (+ -2 X)))) (FOO{GUARD} 1)).

 ACL2 !>
 })

 <p>But here's another way to analyze the guard failure.  Let's change @(tsee
 and) to @(tsee list) in the result of @(':print-gv'), to see which conjuncts
 are false.  Of course, the user can massage the guard form in any way that
 might be helpful.</p>

 @({
 ACL2 !>(FLET ((FOO{GUARD} (X)
                   (DECLARE (IGNORABLE X))
                   (list (INTEGERP X)
                         (POSP (+ -2 X))
                         (POSP (+ 3 X))
                         (POSP (+ -4 X)))))
              (FOO{GUARD} 1))
 (T NIL T NIL)
 ACL2 !>
 })

 <p>The @('NIL') results show that the second and fourth conjuncts of the guard
 were false in our particular case.</p>

 <p>The following hack will give you access in raw Lisp to the form printed by
 @('(print-gv)').  After a guard violation, just submit the following form to
 raw Lisp.</p>

 @({
  (print-gv1 (wormhole-data (cdr (assoc 'ev-fncall-guard-er-wormhole
                                        *wormhole-status-alist*)))
             nil ; conjunct
             nil ; substitute
             'top state)
 })

 <p>If you use local @(see stobj)s (see @(see with-local-stobj)) or stobj
 fields of stobjs, you may need to edit the output of @('print-gv') in order to
 evaluate it.  Consider the following example.</p>

 @({
  (defstobj st fld)

  (defun g (x st)
    (declare (xargs :guard (consp x) :stobjs st)
             (ignore x))
    (fld st))

  (defun test ()
    (with-local-stobj
     st
     (mv-let (result st)
             (mv (g 3 st) st)
             result)))

  (test)
 })

 <p>Then @(':print-gv') yields the result shown below.</p>

 @({
  (FLET ((G{GUARD} (X ST)
                   (DECLARE (IGNORABLE X ST))
                   (AND (STP ST) (CONSP X))))
        (G{GUARD} 3 |<some-stobj>|))
 })

 <p>In this example you could replace ``@('|<some-stobj>|')'' by ``@('st')'' to
 obtain a result of @('nil').  But similar cases may require the use of a local
 stobj that is no longer available, in which case you may need to be creative
 in order to take advantage of @(':print-gv').  Here is such an example.</p>

 @({
  (defstobj st2 fld2)

  (defun g2 (st2)
    (declare (xargs :guard (null (fld2 st2)) :stobjs st2))
    (mv 0 st2))

  (defun test2 ()
    (with-local-stobj
     st2
     (mv-let (result st2)
             (let ((st2 (update-fld2 17 st2)))
               (g2 st2))
             result)))

  (test2)
 })

 <p>In this case, @(':print-gv') yields the following.</p>

 @({
  (FLET ((G2{GUARD} (ST2)
                    (DECLARE (IGNORABLE ST2))
                    (AND (ST2P ST2) (NULL (FLD2 ST2)))))
        (G2{GUARD} |<some-stobj>|))
 })

 <p>But if you replace ``@('|<some-stobj>|')'' by ``@('st')'', the guard holds;
 it is only the local stobj, which is no longer available, that produced a
 guard violation (because its field had been updated to a cons).</p>

 @({
  ACL2 !>(FLET ((G2{GUARD} (ST2)
                           (DECLARE (IGNORABLE ST2))
                           (AND (ST2P ST2) (NULL (FLD2 ST2)))))
               (G2{GUARD} st2))
  T
  ACL2 !>
 })

 <p>Finally, we note that while @('print-gv') is a utility for debugging guard
 violations, in contrast, see @(see guard-debug) for a utility to assist in
 debugging failed proofs arising from guard verification.</p>")

(defxdoc printing-to-strings
  :parents (io)
  :short "Printing to strings instead of files or standard output"
  :long "<p>Each of ACL2's formatted printing functions, @('FM*'), has an
 analogous macro @('FM*-TO-STRING') indicated below.  These functions do not
 include a channel or @(tsee state) as an argument, and @('FM*-TO-STRING')
 returns the string that @('FM*') would print to the state, in place of
 @('state'); see @(see fmt).  The legal keyword arguments are described
 below.</p>

 @({
  General Forms:                                 result
  (fms-to-string string alist &key ...)          ; string
  (fmt-to-string string alist &key ...)          ; (mv col string)
  (fmt1-to-string string alist column &key ...)  ; (mv col string)
  (fms!-to-string string alist &key ...)         ; string
  (fmt!-to-string string alist &key ...)         ; (mv col string)
  (fmt1!-to-string string alist column &key ...) ; (mv col string)
 })

 <p>The legal keyword arguments are as follows.  They are all optional with a
 default of @('nil').</p>

 <blockquote><p>@('Evisc-tuple') is evaluated, and corresponds exactly to the
 @('evisc-tuple') argument of the corresponding @('FM*') function; see @(see
 fmt).</p>

 <p>@('Fmt-control-alist') should typically evaluate to an alist that maps
 print-control variables to values; see @(see print-control).  Any alist
 mapping variables to values is legal, however.  By default the print controls
 are set according to the value of constant @('*fmt-control-defaults*');
 @('fmt-control-alist') overrides these defaults.  For example,
 @('*fmt-control-defaults*') sets the right margin just as it is set in the
 initial ACL2 @(see state), by binding @('fmt-soft-right-margin') and
 @('fmt-hard-right-margin') to their respective defaults of
 @('*fmt-soft-right-margin-default*') and @('*fmt-hard-right-margin-default*').
 The following example shows how you can override those defaults, in this case
 arranging to print flat by setting the right margin to a large number.</p>

 @({
  (fmt-to-string \"~x0\"
                 (list (cons #\\0 (make-list 30)))
                 :fmt-control-alist
                 `((fmt-soft-right-margin . 10000)
                   (fmt-hard-right-margin . 10000)))
 })</blockquote>

 <p>The following remark is subtle; see @(see fmt!) for relevant background.
 By default, there is identical behavior for each pair of functions of the form
 @('fm<..>-to-string') and @('fm<..>!-to-string'): both functions act like the
 @('fm<..>!')  function, which is to say, they both avoid printing a
 backslash (@('\\')) when the right margin is exceeded, so that the results can
 be read by ACL2.  If you include the pair @('(:WRITE-FOR-READ NIL)') in
 @(':fmt-control-alist'), then the @('fm<..>-to-string') functions will be free
 to insert such backslashes; but that pair will have no effect on the
 @('fm<..>!-to-string') functions.</p>

 <p>Note that @(see iprinting) is turned off during evaluation of calls of
 these functions, even if it is enabled globally.  The reason is that for each
 iprint index, @('i'), that is bound during creation of the result string, that
 binding would disappear after the string is returned; so it would be
 misleading or an error to read @('#@i#') after that return.</p>

 <p>Also see @(see io) for a discussion of the utility
 @('get-output-stream-string$'), which allows for accumulating the results of
 more than one printing call into a single string but requires the use of
 @(tsee state).</p>")

(defxdoc profile
  :parents (events)
  :short "Turn on profiling for one function"
  :long "<p>NOTE: An alternative to this utility, which has significantly less
 functionality but doesn't use @(see hons-enabled) features of ACL2, may be
 found in community book @('books/misc/profiling.lisp').  See @(see
 hons-and-memoization) for a general discussion of @(see memoization), on which
 this @('profile') utility is built, and the related features of hash consing
 and applicative hash tables.</p>

 <p>@('Profile') can be useful in Common Lisp debugging and performance
 analysis, including examining the behavior of ACL2 functions.</p>

 @({
  Example:
  (profile 'fn)       ; keep count of the calls of fn
  (profile 'fn        ; as above, with with some memoize options
           :trace t
           :forget t)
  (memsum) ; report statistics on calls of memoized functions (e.g., fn)
  (clear-memoize-statistics) ; clear memoization (and profiling) statistics
 })

 <p>Evaluation of @('(profile 'fn)') redefines @('fn') so that a count will be
 kept of the calls of FN.  The information recorded may be displayed, for
 example, by invoking @('(')@(tsee memoize-summary)@(')') or (equivalently)
 @('(memsum)').  If you wish to gather fresh statistics for the evaluation of a
 top-level form, see @(see clear-memoize-statistics).</p>

 <p>@('Profile') is just a macro that calls @(tsee memoize) to do its work.
 @('Profile') gives the two keyword parameters @(':condition') and
 @(':recursive') of @(tsee memoize) the value @('nil').  Other keyword
 parameters for @('memoize'), which must not include @(':condition'),
 @(':condition-fn'), or @(':recursive'), are passed through.  To eliminate
 profiling, use @(tsee unmemoize); for example, to eliminate profiling for
 function @('fn'), evaluate @('(unmemoize 'fn)').</p>

 <p>Functions @(tsee profile-all) and @(tsee profile-acl2) are available for
 profiling all functions or all ACL2 functions, respectively.</p>")

(defxdoc prog2$
  :parents (progn$ acl2-built-ins)
  :short "Execute two forms and return the value of the second one"
  :long "<p>See @(see hard-error), see @(see illegal), and see @(see cw) for
 examples of functions to call in the first argument of @('prog2$').  Also see
 @(see progn$) for an extension of @('prog2$') that handles than two
 arguments.</p>

 <p>Semantically, @('(Prog2$ x y)') equals @('y'); the value of @('x') is
 ignored.  However, @('x') is first evaluated for side effect.  Since the ACL2
 @(see programming) language is applicative, there can be no logical impact of
 evaluating @('x').  However, @('x') may involve a call of a function such as
 @(tsee hard-error) or @(tsee illegal), which can cause so-called ``hard
 errors'', or a call of @(tsee cw) to perform output.</p>

 <p>Here is a simple, contrived example using @(tsee hard-error).  The
 intention is to check at run-time that the input is appropriate before calling
 function @('bar').</p>

 @({
  (defun foo-a (x)
    (declare (xargs :guard (consp x)))
    (prog2$
     (or (good-car-p (car x))
         (hard-error 'foo-a
                     \"Bad value for x: ~p0\"
                     (list (cons #\\0 x))))
     (bar x)))
 })

 <p>The following similar function uses @(tsee illegal) instead of
 @('hard-error').  Since @('illegal') has a guard of @('nil'), @(see guard)
 verification would guarantee that the call of @('illegal') below will never be
 made (at least when guard checking is on; see @(see set-guard-checking)).</p>

 @({
  (defun foo-b (x)
    (declare (xargs :guard (and (consp x) (good-car-p (car x)))))
    (prog2$
     (or (good-car-p (car x))
         (illegal 'foo-b
                  \"Bad value for x: ~p0\"
                  (list (cons #\\0 x))))
     (bar x)))
 })

 <p>We conclude with a simple example using @(tsee cw) from the ACL2
 sources.</p>

 @({
  (defun print-terms (terms iff-flg wrld)

  ; Print untranslations of the given terms with respect to iff-flg, following
  ; each with a newline.

  ; We use cw instead of the fmt functions because we want to be able to use this
  ; function in print-type-alist-segments (used in brkpt1), which does not return
  ; state.

    (if (endp terms)
        terms
      (prog2$
       (cw \"~q0\" (untranslate (car terms) iff-flg wrld))
       (print-terms (cdr terms) iff-flg wrld))))
 })")

(defxdoc progn
  :parents (events)
  :short "Evaluate some @(see events)"
  :long "@({
  Example Form:
  (progn (defun foo (x) x)
         (defmacro my-defun (&rest args)
           (cons 'defun args))
         (my-defun bar (x) (foo x)))

  General form:
  (progn event1 event2 ... eventk)
 })

 <p>where @('k') &gt;= 0 and each @('eventi') is a legal embedded event form
 (see @(see embedded-event-form)).  Each event is printed (by default) and
 evaluated, in sequence.  If any event fails, the entire @('progn') call is
 deemed to have failed, and the logical @(see world) is rolled back to what it
 was immediately before the @('progn') call was evaluated.  A utility is
 provided to assist in debugging failures of such execution; see @(see
 redo-flat).</p>

 <p>NOTE: If the @('eventi') above are not all legal embedded event forms (see
 @(see embedded-event-form)), consider using @(tsee er-progn) or (with great
 care!) @(tsee progn!) instead.  If your goal is simply to execute a sequence
 of top-level forms that are not necessarily all legal embedded event forms,
 consider using @('ld') instead; see @(see ld).</p>

 <p>For a related event form that does allow introduction of @(see constraint)s
 and @(tsee local) @(see events), see @(see encapsulate).</p>

 <p>ACL2 does not allow the use of @('progn') in definitions.  Instead, the
 macro @(tsee er-progn) can be used for sequencing @(see state)-oriented
 operations; see @(see er-progn) and see @(see state).  If you are using
 single-threaded objects (see @(see stobj)) you may wish to define a version of
 @(tsee er-progn) that cascades the object through successive changes.  ACL2's
 @(tsee pprogn) is the @('state') analogue of such a macro.</p>")

(defxdoc progn!
  :parents (events)
  :short "Evaluate some forms, not necessarily @(see events)"
  :long "<p><b>WARNING!</b> This event is intended for advanced users who, in
 essence, want to build extensions of ACL2.  See see @(see defttag), in
 particular, the ``WARNING'' there, and see the warning about @(see stobj)s at
 the end of this documentation topic.</p>

 <p>@('Progn!') can be used like @(tsee progn), even in @(see books).  But
 unlike @(tsee progn), @('progn!') does not require its constituent forms to be
 @(see events) (see @(see embedded-event-form)), except that the first form
 cannot be a symbol unless it is @(':state-global-bindings') (advanced feature,
 described below).  However, see @(see make-event) for a ``Restriction to the
 Top Level'' that still applies under a call of @('progn!').</p>

 <p>Because @('progn!') allows non-events, it differs from @('progn') in
 another important respect: @('progn!') is illegal unless there is an active
 ttag; see @(see defttag).</p>

 <p>See community book @(see hacker) for two macros, @(see with-raw-mode) and
 @(see with-redef-allowed), each defined in terms of @('progn!'), that allow
 arbitrary forms in contexts that would normally require legal embedded event
 forms.</p>

 <p>Given a form @('(progn! form1 form2 ... formk)'), ACL2 will evaluate each
 @('formi') in turn (for i from 1 to k).  If a form returns more than one value
 (see @(see mv)) where the first value returned is not @('nil'), then no later
 form will be evaluated and the result returned by the @('progn!') call will be
 @('(mv erp val state)') for some non-@('nil') value @('erp'), signifying an
 error (see @(see ld-error-triples)).  Otherwise the evaluation is considered
 to have succeeded, and will continue with later forms.  The value returned by
 a call of @('progn!') with no such error is of the form @('(mv nil v state)'),
 where @('v') depends on the last form as follows.  If the last form evaluates
 to a single value, then @('v') is that value, except if the value is a @(see
 stobj), say @('ST'), then @('v') is the symbol @('REPLACED-ST').  Otherwise
 the last form evaluates to some @('(mv nil x ...)'), and @('v') is @('x')
 unless after the final form's evaluation we are in raw-mode (see @(see
 set-raw-mode)), in which case the @('progn!') call returns @('nil') (so that
 ACL2 can at least print the result &mdash; imagine Lisp returning a pathname
 object from a @('load') call, for example).</p>

 <p>The normal undoing mechanism does not generally apply to forms within a
 @('progn!') that are not legal ACL2 @(see events) (see @(see
 embedded-event-form)).  In particular, note that a non-@(tsee local) call of
 @('progn!') in an @(tsee encapsulate) event will generally be evaluated twice:
 once on each pass.  This fact is worth keeping in mind if you are using
 @('progn!') to change the state of the system; ask yourself if it is
 acceptable to apply that state-changing operation more than once.</p>

 <p>Please note that @('progn!') may differ from @(tsee progn) in the following
 sense: definitions within a call of @('progn!') might not be compiled.  For
 example, consider the following book.</p>

 @({
  (in-package \"ACL2\")
  (defttag :test)
  (progn  (defun f1 (x) x))
  (progn! (defun f2 (x) x))
 })

 <p>If the underlying Lisp is GCL 2.6.7, then after including this certified
 book (where the default certification took place, creating a compiled file),
 then @('f1') is a compiled function but @('f2') is not.  For other Lisps
 supported by ACL2, both @('f1') and @('f2') are compiled, though we are not
 sure that every function under every call of @('progn!') would similarly be
 compiled.</p>

 <p>We now describe, for system hackers only, a sophisticated extension of
 @('progn!') not mentioned above: support for keyword argument
 @(':state-global-bindings').  If the first argument of @('progn!') is this
 keyword, then the second argument is treated as a list of bindings as expected
 by ACL2 system function @(tsee state-global-let*).  Thus, in the ACL2
 loop,</p>

 @({
  (progn! :state-global-bindings bindings form1 form2 ... formk)
 })

 <p>is treated as follows:</p>

 @({
  (progn! (state-global-let* bindings (progn! form1 form2 ... formk)))
 })

 <p>However, in raw Lisp the former is just:</p>

 @({
  (progn form1 form2 ... formk)
 })

 <p>Thus, one should use the @(':state-global-bindings') argument with care,
 since the behavior in the ACL2 loop can differ from that in Common Lisp.  The
 intention is that one bind only @(see state) global variables that are
 relevant to evaluation of the forms within the ACL2 loop and are harmlessly
 ignored for evaluation of those forms in raw Lisp.  Here is a typical sort of
 example, as @(see state) global @('ld-redefinition-action') is not relevant to
 the evaluation of @(tsee defun) in raw Lisp.</p>

 @({
  (progn! (remove-untouchable 'ld-redefinition-action nil)
          (progn! :state-global-bindings
                  ((ld-redefinition-action '(:doit . :overwrite)))
                  (defun foo (x)
                    (cons x x)))
          (push-untouchable 'ld-redefinition-action nil))
 })

 <p>Finally, we point out a pitfall of @('progn!') related to @(see stobj)s.
 The following book can cause a hard Lisp error, depending on the host Common
 Lisp, when certified with a non-@('nil') value for @('compile-flg') (see @(see
 certify-book)).</p>

 @({
  (in-package \"ACL2\")
  (defstobj st fld)
  (defttag :my-ttag)
  (progn! (update-fld 3 st))
 })

 <p>The problem is that the @(see stobj) variable @('st') is not known to raw
 Lisp.  The compilation problem disappears if the last form above is replaced
 with the following two forms.</p>

 @({
  (include-book \"hacking/hacker\" :dir :system)
  (with-raw-mode (update-fld 3 *the-live-st*))
 })")

(defxdoc progn$
  :parents (basics acl2-built-ins)
  :short "Execute a sequence of forms and return the value of the last one"
  :long "<p>This macro expands to a corresponding nest of calls of @('prog2$');
 see @(see prog2$).  The examples below show how this works: the first case
 below is typical, but we conclude with two special cases.</p>

 @({
  ACL2 !>:trans1 (progn$ (f1 x) (f2 x) (f3 x))
   (PROG2$ (F1 X) (PROG2$ (F2 X) (F3 X)))
  ACL2 !>:trans1 (progn$ (f1 x) (f2 x))
   (PROG2$ (F1 X) (F2 X))
  ACL2 !>:trans1 (progn$ (f1 x))
   (F1 X)
  ACL2 !>:trans1 (progn$)
   NIL
  ACL2 !>
 })")

(defxdoc program
  :parents (defun-mode)
  :short "To set the default @(see defun-mode) to @(':')@(tsee program)"
  :long "@({
  Example:
  ACL2 !>:program
  ACL2 p!>
 })

 <p>Typing the keyword @(':program') sets the default @(see defun-mode) to
 @(':program').</p>

 <p>Functions defined in @(':program') mode are logically undefined but can be
 executed on constants outside of deductive contexts.  See @(see
 defun-mode).</p>

 <p>Calls of the following macros are ignored (skipped) when in @(':program')
 mode.</p>

 @({
  local
  verify-guards
  verify-termination
  defaxiom
  defthm
  deftheory
  in-theory
  in-arithmetic-theory
  regenerate-tau-database
  theory-invariant
  defchoose
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 <p>See @(see defun-mode) for a discussion of the @(see defun-mode)s available
 and what their effects on the logic are.  See @(see default-defun-mode) for a
 discussion of how the default @(see defun-mode) is used.  This event is
 equivalent to @('(table acl2-defaults-table :defun-mode :program)'), and hence
 is @(tsee local) to any @(see books) and @(tsee encapsulate) @(see events) in
 which it occurs. See @(see acl2-defaults-table).</p>

 <p>Recall that the top-level form @(':program') is equivalent to
 @('(program)'); see @(see keyword-commands).  Thus, to change the default
 @(see defun-mode) to @(':program') in a book, use @('(program)'), which is an
 embedded event form, rather than @(':program'), which is not a legal form for
 @(see books).  See @(see embedded-event-form).</p>

 <p>See @(see program-wrapper) for how to use program-mode functions to avoid
 expensive @(see guard) checks.</p>")

(defxdoc program-only
  :parents (guard)
  :short "Functions that cannot be in @(see logic) mode"
  :long "<p>Functions are considered to be ``program-only'' when they are in
 @(see program) mode and they belong to the list @('(@
 program-fns-with-raw-code)').  For such a function, its
 executable-counterpart (see @(see evaluation)) always checks the guard.  If
 the guard fails, then even if guard-checking is off, an error is signaled
 because a program-only function is assumed to have an executable-counterpart
 that should only execute the raw Lisp definition.  Moreover, an error is
 always signaled when in @(see safe-mode) (e.g., during macroexpansion),
 because there is no guarantee that evaluation of the raw Lisp code will be
 ``safe''.</p>

 <p>See @(see safe-mode-cheat-sheet) for possible workarounds.</p>")

(defxdoc program-wrapper
  :parents (program programming advanced-features)
  :short "Avoiding expensive guard checks using @(see program)-mode functions"
  :long "<p>Application programs can benefit from the avoidance of expensive
 @(see guard) checks, as illustrated by the following contrived example.  In
 this example, imagine that @('expensive-guard') is a @(see guard) that is
 expensive to evaluate, and that @('expensive-update') is a function that you
 want to run in a context where you know the guard is true, so you want to
 avoid the expense of evaluating that guard.  Then when you call
 @('expensive-update-wrapper'), the call will be evaluated directly in raw
 Lisp, hence without any subsidiary guard-checking for the function
 @('expensive-update').</p>

 @({
 (defun fib (n)
   (declare (xargs :guard (natp n)))
   (if (zp n)
       0
     (if (eql n 1)
         1
       (+ (fib (- n 1))
          (fib (- n 2))))))

 (defun expensive-guard (n)
   (declare (xargs :guard t))
   (and (natp n)
        (natp (fib n))))

 (defstobj st (fld :type integer :initially 0))

 (defun expensive-update (n st)
   (declare (xargs :stobjs st
                   :guard (expensive-guard n)))
   (update-fld n st))

 (defun expensive-update-wrapper (n st)
   (declare (xargs :stobjs st :mode :program))
   (expensive-update n st))
 })

 <p>Remark.  The example was chosen to illustrates an additional point: if you
 evaluate (for example) the form @('(expensive-update-wrapper 3 st)'), you will
 see an @('\"Invariant-risk\"') warning, which could indicate extra checks that
 slow down evaluation.  This might not be a significant issue in practice.  See
 @(see invariant-risk).</p>")

(defxdoc programming

; This section should include documentation for all functions in ACL2 constant
; *primitive-formals-and-guards*.

  :parents (acl2)
  :short "Programming in ACL2"
  :long "<p>This @(see documentation) topic is a parent topic under which we
 include documentation topics for built-in functions, macros, and special
 forms, as well as topics for notions important to programming with ACL2.  If
 you don't find what you're looking for, see the Index or see individual topics
 that may be more directly appropriate; for example, see @(see events) for
 top-level event constructors like @(tsee defun).  A subtopic, @(see
 acl2-built-ins), contains as subtopics (displayed in a flat list) most of the
 topics in the @(see documentation) hierarchy that appear under this
 `programming' topic.</p>

 <p>Also see @(see debugging) for utilities that can aid in programming.</p>")

(defxdoc programming-knowledge-taken-for-granted
  :parents (introduction-to-the-theorem-prover)
  :short "Background knowledge in ACL2 programming for theorem prover tutorial"
  :long "<p>This brief review of the programming language is presented as a
 sequence of questions and answers meant to test your knowledge of the ACL2
 programming language.  If you want a gentle introduction to the programming
 language, see <a
 href='http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html'>http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html</a>.</p>

 <p>Before we get started with the programming drill, let us remind you that
 all we're interested in here is the language, not the ``program development
 environment.''  It's impossible to program in ACL2 or any other language
 without a decent environment, one that at the very least includes a way to
 prepare and edit files of programs.  The two most popular program development
 environments among ACL2 users are @(see Emacs) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> and
 the Eclipse-based @(see ACL2-Sedan) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>.
 The Sedan provides the most support for the new user, including real-time
 syntax checking and a facility for testing among many other features.  But in
 this drill we're not interested in the program development environment, we're
 interested in your understanding of the ACL2 language.</p>

 <p><b>Q</b>: What do you think this command does?</p>

 @({
  (defun rev (x)
    (if (endp x)
        nil
        (append (rev (cdr x)) (list (car x)))))
 })

 <p><b>A</b>: It defines a function named @('rev') that takes one argument,
 treats it like a list, and reverses the order of the elements in that list.
 To figure this out from the definition, you have to know that @('append')
 concatenates two lists.  Logically speaking, the @('defun') of @('rev') adds
 the axiom:</p>

 @({
  (rev x)
  =
  (if (endp x)
      nil
      (append (rev (cdr x)) (list (car x)))),
 })

 <p>implicitly quantified for all @('x').</p>

 <p><b>Q</b>: Given the @('defun') of @('rev') above, what are the <i>formal
 parameters</i>?  What is the <i>body</i> of the definition?  Write down a
 <i>call</i> of <i>append</i> that occurs in the body of @('rev').  What are
 the <i>actuals</i> of that call?  <b>A</b>: The <i>formals</i> of @('rev') is
 the list of variables after the first @('rev') in the @('defun'), namely
 @('(x)').  We say @('x') is the first (and only) <i>formal</i> here.  The
 <i>body</i> of @('rev') is the entire @('if')-expression.  The only
 <i>call</i> of @('append') in the body is</p>

 @({
  (append (rev (cdr x)) (list (car x)))
 })

 <p>and the <i>actuals</i> of that call are, respectively, @('(rev (cdr x))')
 and @('(list (car x))').</p>

 <p><b>Q</b>: What do you get if you evaluate @('(rev '(a b c d))')?  <b>A</b>:
 @('(D C B A)').</p>

 <p><b>Q</b>: How did @('rev') change the case of the elements, e.g., lowercase
 @('a') was in the input list but uppercase @('A') was in the output?
 <b>A</b>: This is a trick question.  @('Rev') doesn't change the case of the
 elements.  ACL2 is case-insensitive when dealing with symbols.  The symbol
 @('a') is read in as the symbol @('A').  Thus, when writing function names,
 for example, we can write @('rev'), @('Rev'), @('REV'), or even @('ReV') and
 always be referring to the function @('REV').  By default, ACL2 prints symbols
 in uppercase.</p>

 <p><b>Q</b>: What does @('(rev '((a b c) \"Abc\" \"a\" b #\\c))') return?
 <b>A</b>: @('(#\\c B \"a\" \"Abc\" (A B C))').  If you thought the answer was
 any of these, then you need to think or read more carefully:</p>

 @({
  (#\\C B \"A\" \"ABC\" (A B C))

  (#\\C B \"A\" \"ABC\" (C B A))
 })

 <p>The first wrong answer above is wrong because Lisp is ``case insensitive''
 only for symbols, not for character objects like @('#\\c') (the lowercase
 character c) or for strings.  Furthermore, @('\"A\"') is a string, not a
 symbol; it is different from @('A').  The second wrong answer above is wrong
 because @('rev') does not go into the individual elements of the list, it just
 reverses the order of the elements.  So it doesn't change the element @('(A B
 C)') to @('(C B A)').</p>

 <p><b>Q</b>: In the question about what @('(rev '(a b c d))') returns, we put
 a quote mark before the @('(a b c d)') but not before the answer, @('(D C B
 A)').  Why?  <b>A</b>: The phrase ``<i>x</i> evaluates to <i>y</i>'' treats
 <i>x</i> as a <i>term</i> to be evaluated and <i>y</i> as an <i>object</i>.
 @('(Rev '(a b c d))') is a term to be evaluated and denotes a call of the
 function @('rev') on the value of the argument term @(''(a b c d)').  The
 value of that argument term is the object @('(a b c d)').  The value of the
 call of @('rev') is the object @('(d c b a)').  If you have an object,
 <i>obj</i>, and you wish to create a term whose value is <i>obj</i>, then you
 put a quote mark in front of it, <i>'obj</i>.</p>

 <p><b>Q</b>: Can @('rev') be applied to something other than a list?
 <b>A</b>: Yes, every ACL2 function can be applied to any object.  ACL2 is an
 untyped programming language: every variable ranges over the entire universe
 of objects.  In normal usage, @('rev') is applied to lists but there is
 nothing about the syntax of the language that prevents it being applied to
 non-lists.</p>

 <p><b>Q</b>: So what does @('(rev 23)') evaluate to?  <b>A</b>: @('Nil').</p>

 <p><b>Q</b>: Why?  <b>A</b>: Because @('(endp 23)') is @('t'), because
 @('endp') is defined:</p>

 @({
  (defun endp (x) (not (consp x)))
 })

 <p>Thus, if @('rev') is applied to anything that is not a cons, it returns
 @('nil').</p>

 <p><b>Q</b>: So what does @('(rev '(a b c . d))') evaluate to?  <b>A</b>:
 @('(c b a)').  To explain why requires demonstrating that you know what @('(a
 b c . d)') means.  It is the object computed by evaluating:</p>

 @({
  (cons 'a
        (cons 'b
              (cons 'c
                    'd))).
 })

 <p>That is, it is a list whose ``terminal marker'' is the atom @('D').
 @('Rev') treats that list exactly as it treats the @('nil')-terminated list of
 the same elements, @('(a b c)'), because @('(endp 'D)') = @('(endp nil)') =
 @('t').</p>

 <p><b>Q</b>: What does @('(rev 1 2 3)') evaluate to?  <b>A</b>: That's a trick
 question.  @('Rev') takes one argument, not three.  So @('(rev 1 2 3)') is an
 ill-formed term.</p>

 <p><b>Q</b>: What does @('(rev '(a b c . d . nil))') evaluate to?  <b>A</b>:
 That is a trick question.  There is no such object.  In Lisp's ``dot
 notation'' every dot must be followed by a well-formed object and then a close
 parenthesis.  Usually that ``well-formed object'' is an atom.  If it is not an
 atom, i.e., if it is a cons, then the entire expression could have been
 written without that dot.  For example, @('(a b c . (d e))') is an object, but
 it could be written @('(a b c d e)').</p>

 <p><b>Q</b>: Do @('(rev (rev x))') and @('x') always evaluate to the same
 object?  <b>A</b>: No.  @('(Rev (rev 23))') evaluates to @('nil'), not
 @('23').</p>

 <p><b>Q</b>: Do @('(rev (rev x))') and @('x') always evaluate to the same
 object when @('x') is a cons?  <b>A</b>: No.  @('(rev (rev '(a b c . d)))')
 evaluates to @('(a b c)'), not @('(a b c . d)').</p>

 <p><b>Q</b>: When are @('(rev (rev x))') and @('x') equal?  <b>A</b>: When the
 terminal marker of @('x') is @('nil').</p>

 <p><b>Q</b>: Can you define a Lisp function that recognizes
 @('nil')-terminated lists?  <b>A</b>: Yes, but it is not necessary for the
 user to define that concept because Common Lisp provides such a function which
 is logically defined as follows:</p>

 @({
  (defun true-listp (x)
    (if (consp x)
        (true-listp (cdr x))
        (equal x nil))).
 })

 <p>This can be paraphrased: @('(true-listp x)') means that if @('x') is a
 @('cons'), its @('cdr') is a @('true-listp') and if @('x') is not a @('cons'),
 it must be @('nil').  Thus, @('(true-listp '(a b c))') is @('t') and
 @('(true-listp '(a b c . d))') is @('nil').</p>

 <p><b>Q</b>: Can you write a Lisp formula that says ``If @('z') is a
 @('nil')-terminated list then reversing the result of reversing @('z') is
 @('z')''?</p>

 <p><b>A</b>: Yes:</p>

 @({
  (implies (true-listp z)
           (equal (rev (rev z)) z)).
 })

 <p><b>Q</b>: Is this all there is to ACL2 programming?  <b>A</b>: No!  ACL2
 provides many other features.  For a full list of all the primitive functions
 in ACL2 see @(see programming) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>.
 Some highlights for the beginner are mentioned below, but all of the links
 below ought to be tagged with the <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 sign.</p>

 <p>* @(tsee list): build a @('nil')-terminated list from the values of
 <i>n</i> terms, e.g., @('(list x (+ 1 x) (+ 2 x))') returns @('(3 4 5)') if
 @('x') is @('3').</p>

 <p>* @(see list*): build a non-@('nil') terminated list of <i>n</i> objects
 from the values of <i>n+1</i> terms, e.g., @('(list* x (+ 1 x) (+ 2 x) (* -1
 x))') returns the list @('(3 4 5 . -3)') if @('x') is @('3').</p>

 <p>* @(tsee and), @(tsee or), @(tsee not), @(tsee implies), @(tsee iff): The
 propositional connectives.  @('And') and @('or') are allowed to take a varying
 number of arguments, e.g., @('(and p q r)') is just an abbreviation for
 @('(and p (and q r))').  In Lisp, @('and') returns @('nil') if any of its
 arguments evaluates to @('nil'); otherwise it returns the value of the last
 argument!  Thus, @('(and t t 3)') returns @('3')!  If you object to the idea
 that @('and') is not Boolean, don't give it non-Boolean arguments!  Similarly,
 @('or') returns the value of the first argument that evaluates to
 non-@('nil'), or @('nil') if they all evaluate to @('nil').  Both @('and') and
 @('or') can be thought of as ``lazy'' in that they don't always have to
 evaluate all their arguments.  This is really accomplished by treating
 @('and') and @('or') as abbreviations for @('if') nests.</p>

 <p>* @(tsee +), @(tsee *), @(tsee -), @(tsee /), @(tsee floor), @(tsee mod),
 @(tsee <), @(tsee <=), @(tsee >=), @(tsee >): the Lisp elementary arithmetic
 operators.  Both @('+') and @('*') allow varying numbers of arguments.  All
 the arithmetic operators default non-numeric arguments to @('0').  If you
 don't like the idea that @('(+ 1 2 t)') is @('3'), don't ask @('+') to add
 @('t') to something!</p>

 <p>* @(tsee natp), @(tsee integerp), @(tsee rationalp), @(tsee characterp),
 @(tsee stringp), @(tsee symbolp), @(tsee consp): the recognizers for the
 primitive data types.  The first three recognize subsets of the ACL2 numeric
 universe.  The naturals are a subset of the integers, the integers are a
 subset of the rationals, and the rationals are a subset of the objects
 recognized by @(tsee acl2-numberp), which also includes the @(tsee
 complex-rationalp)s.  The other recognizers listed above recognize characters,
 strings, symbols, and conses.</p>

 <p>* @(tsee cond): a convenient way to write a cascading nest of @('if')s,
 e.g.,</p>

 @({
  (cond ((not (natp x)) 'non-natural)
        ((equal x 0) 'zero)
        ((evenp x) 'positive-even)
        (t 'positive-odd))
 })

 <p>abbreviates</p>

 @({
  (if (not (natp x))
      'non-natural
      (if (equal x 0)
          'zero
          (if (evenp x)
              'positive-even
              'positive-odd))).
 })

 <p>* @(tsee case): a convenient way to case split on the identity of an
 object.</p>

 @({
  (case key
    (non-natural -1)
    (zero 0)
    ((positive-even positive-odd) 'positive-natural)
    (otherwise 'unknown))
 })

 <p>abbreviates</p>

 @({
  (cond ((eql key 'non-natural) -1)
        ((eql key 'zero) 0)
        ((member key '(positive-even positive-odd))
         'positive-natural)
        (t 'unknown)).
 })

 <p>* user defined macros: using @(tsee defmacro) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 you can introduce your own abbreviations.  We recommend you not do this until
 you're good at list processing since macros are functions that build objects
 representing terms.</p>

 <p>* @(tsee mutual-recursion): allows you to define mutually-recursive
 functions.</p>

 <p>* @(tsee mv) and @(tsee mv-let): allow functions to return
 ``multiple-values''.  In Lisp, such functions return vectors of values, the
 vectors are represented as lists of values, but the implementations are
 generally more efficient.  For example, @('(mv x y z)') returns a ``vector''
 consisting of the values of @('x'), @('y'), and @('z').</p>

 @({
  (mv-let (a b c)
          (foo x)
          (bar a b c x))
 })

 <p>evaluates @('(foo x)'), treats the result as a vector of three values,
 binds the variables @('a'), @('b'), and @('c') to those three values, and
 evaluates and returns @('(bar a b c x)').</p>

 <p>ACL2 also provides many other features, such as single-threaded objects
 which may be ``destructively modified'' (see @(see stobj) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>,
 including a very special single-threaded object that records the @(tsee state)
 <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> of the ACL2 system), file input and output (see
 @(see io) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>), applicative arrays (see @(see arrays) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 and property lists (see @(see getprop) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 and other facilities necessary for it to be a practical programming language.
 However, we <b>strongly</b> recommend that as a new user you stay away from
 these features until you are good at proving theorems about elementary list
 processing!</p>

 <p>If this little drill made sense to you, you know enough of the programming
 language to get started. Use your browser's <b>Back Button</b> now to return
 to @(see introduction-to-the-theorem-prover).</p>

 <p>If you are uncomfortable with ACL2 programming, we recommend that you study
 <a
 href='http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html'>http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html</a>
 and <a
 href='http://www.cs.utexas.edu/users/moore/publications/acl2-programming-exercises1.html'>http://www.cs.utexas.edu/users/moore/publications/acl2-programming-exercises1.html</a>.</p>

 <p>However, we strongly recommend that you first invest in learning either the
 @(see Emacs) or Eclipse-based @(see ACL2-Sedan) program development
 environments, since it is foolish to try to learn how to program in a
 stand-alone read-eval-print loop!</p>

 <p>While getting started, many users find the Hyper-Card a handy index into
 the documentation for the ACL2 language:</p>

 <p><a
 href='http://www.cs.utexas.edu/users/moore/publications/hyper-card.html'>http://www.cs.utexas.edu/users/moore/publications/hyper-card.html</a></p>

 <p>Once you are comfortable with the ACL2 programming language, use your
 browser's <b>Back Button</b> to return to @(see
 introduction-to-the-theorem-prover).</p>")

(defxdoc programming-with-state
  :parents (state programming)
  :short "Programming using the von Neumannesque ACL2 @(see state) object"
  :long "<p>This @(see documentation) section introduces some common techniques
 for programming using the ACL2 state object.  A prerequisite is thus a basic
 understanding of that object; see @(see state).  We hope this section is
 useful, and we invite suggestions for improvements and additions.</p>

 <p>A supplement to this section is the ACL2 source code, which uses most (and
 probably all) of the techniques discussed here.  That code is thus a source of
 many examples, which can serve as ``templates'' to guide one's own programming
 with state.</p>

 <p>Recall that ``ACL2'' stands for ``A Computational Logic for Applicative
 Common Lisp''.  In particular, the language is applicative: there are no
 global variables or side effects.  For many purposes this does not feel
 restrictive; for example, an ACL2 user who is programming in raw Lisp may well
 be more comfortable coding a factorial function applicatively, using
 recursion, rather than using iteration with repeated assignment to the same
 variable.</p>

 <p>However, there are situations that call for reading or modifying the system
 state, such as performing input and output, signaling errors, saving
 information from one computation for use in a later one, or reading and
 updating system-level or environmental data.  This section provides an
 introductory guide for writing functions that traffic in state.  We emphasize
 that this guide is intended as an introduction; more complete documentation
 may often be found by following links to documentation of individual
 utilities, and again, more examples may be found by searching the ACL2 source
 code for uses of the functions and macros mentioned below.  The rest of this
 section is organized as follows.</p>

 @({
  ENABLING PROGRAMMING WITH STATE
  STATE GLOBALS AND THE ACL2 LOGICAL WORLD
  A REMARK ON GUARDS
  ERRORS AND ERROR TRIPLES
  SEQUENTIAL PROGRAMMING
  BINDING VARIABLES USING ERROR TRIPLES
  BINDING STATE GLOBAL VARIABLES
  INPUT AND OUTPUT
  TIMINGS
  ENVIRONMENT AND SYSTEM
  REMARKS ON EVENTS AND LD
  ADVANCED TOPICS
 })

 <p>ENABLING PROGRAMMING WITH STATE</p>

 <p>In order to submit a definition that takes @(tsee state) as a formal
 parameter, you must either declare @('state') as a @(':')@(tsee stobj) (see
 @(see xargs)) or first evaluate the following form at the top level:
 @('(set-state-ok t)').</p>

 <p>Consider for example the following trivial definition.</p>

 @({
  (defun foo (state)
    (mv 3 state))
 })

 <p>If you submit the above definition in a fresh ACL2 session, you will get
 this error message.</p>

 @({
    ACL2 Error in ( DEFUN FOO ...):  The variable symbol STATE should not
    be used as a formal parameter of a defined function unless you are
    aware of its unusual status and the restrictions enforced on its use.
    See :DOC set-state-ok.
 })

 <p>If first you evaluate @('(set-state-ok t)'), you can admit the above
 definition.  Alternatively, you can declare @('state') as a @(':')@(tsee
 stobj), as follows.</p>

 @({
  (defun foo (state)
    (declare (xargs :stobjs state))
    (mv 3 state))
 })

 <p>A difference in the two approaches is that for the latter, a @(see guard)
 proof obligation is generated by default.  See the section below entitled ``A
 remark on guards''.</p>

 <p>STATE GLOBALS AND THE ACL2 LOGICAL WORLD</p>

 <p>Recall (see @(see state)) that one of the fields of the ACL2 state object
 is the global-table, which logically is an alist associating symbols, known as
 ``state globals'' or ``state global variables'', with values.  But no such
 alist actually exists in the implementation.  Instead, ACL2 provides utilities
 for reading state globals &mdash; see @(see @) and see @(see f-get-global)
 &mdash; and utilities for writing them &mdash; see @(see assign) and see @(see
 f-put-global).  The following log shows how they work; further explanation
 follows below.</p>

 @({
  ACL2 !>(assign my-var (+ 3 4))
   7
  ACL2 !>(@ my-var)
  7
  ACL2 !>(f-put-global 'my-var (+ 1 5) state)
  <state>
  ACL2 !>(f-get-global 'my-var state)
  6
  ACL2 !>
 })

 <p>Note that the first result is indented by one space.  This is ACL2's way to
 indicate that the @(tsee assign) expression returned an ``error triple'' and
 that no error was signaled.  We discuss error triples in more detail below;
 also see @(see error-triple).</p>

 <p>As illustrated above, the output signatures of the utilities for assigning
 to state globals differ from each other as follows: @(tsee f-put-global)
 returns @('state'), but @(tsee assign) returns an error triple @('(mv nil val
 state)') where @('val') is the value assigned to the state global.  The output
 signatures of the utilities for reading, @('@') and @('f-get-global'), are
 identical.  In fact, the form @('(f-get-global 'my-var state)') is the
 single-step macroexpansion of the form @('(@ my-var)'), as can be confirmed
 using @(tsee trans1).</p>

 @({
  ACL2 !>:trans1 (@ my-var)
   (F-GET-GLOBAL 'MY-VAR STATE)
  ACL2 !>
 })

 <p>State globals are useful for conveying persistent state information.
 Consider for example the utility @(tsee set-inhibit-output-lst).  The form
 @('(set-inhibit-output-lst '(prove proof-tree))') is approximately equivalent
 to (assign inhibit-output-lst '(prove proof-tree)).  We say ``approximately''
 because @('set-inhibit-output-lst') additionally does some error checking to
 insure that all the tokens in the new list are legal.  When deciding whether
 to print output, the ACL2 system reads the value of state global variable
 @('inhibit-output-lst').</p>

 <p>A particularly useful state global is @('current-acl2-world'), whose value
 is the ACL2 logical @(see world).  Because the ACL2 world is commonly accessed
 in applications that use the ACL2 state, ACL2 provides a function that returns
 the world: @('(w state) = (f-get-global 'current-acl2-world state)').  While
 it is common to read the world, only functions @('set-w') and @('set-w!') are
 available to write the world, but these are untouchable and should generally
 be avoided except by system implementors (see @(see remove-untouchable)).</p>

 <p>A REMARK ON GUARDS</p>

 <p>For a function definition (see @(see defun)), if @('state') is specified as
 a @(see stobj) as with the form @('(declare (xargs :stobjs state))'), then the
 @(see guard) for that function is considered to include the condition
 @('(state-p state)').  By default, @(see guard) verification will then be
 performed.</p>

 <p>We can illustrate this point by modifying the example above as follows, to
 read the value of state global @('gag-mode').</p>

 @({
  (defun foo (state)
    (declare (xargs :stobjs state))
    (f-get-global 'gag-mode state))
 })

 <p>If you try this in a fresh ACL2 session, the proof will fail with the
 following key checkpoint, which says that the state global @('gag-mode') is
 bound in the global-table of the state.</p>

 @({
    (IMPLIES (STATE-P1 STATE)
             (ASSOC-EQUAL 'GAG-MODE (NTH 2 STATE)))
 })

 <p>How can we deal with this proof failure?  One way is simply to ignore the
 issue by defining the function in @(':')@(tsee program) mode, as follows.</p>

 @({
  (defun foo (state)
    (declare (xargs :stobjs state
                    :mode :program))
    (f-get-global 'gag-mode state))
 })

 <p>Perhaps a better way is to strengthen the guard to assert that the
 indicated state global is bound, as follows.</p>

 @({
  (defun foo (state)
    (declare (xargs :guard (boundp-global 'gag-mode state)
                    :stobjs state))
    (f-get-global 'gag-mode state))
 })

 <p>Also see @(see guard-miscellany) for a discussion of how guards are
 generated from @(tsee xargs) fields of @(see declare) forms, specifically, for
 keywords @(':guard') and @(':stobjs').</p>

 <p>ERRORS AND ERROR TRIPLES</p>

 <p>When evaluation returns three values, where the first two are ordinary
 objects and the third is the ACL2 state, the result may be called an ``error
 triple''.  (Whether it is treated as an error triple depends on the
 programmer.)  Error triples are often denoted @('(mv erp val state)'), and
 common ACL2 programming idioms treat @('erp') as a flag indicating whether an
 error is being signaled and @('val') as the ``value'' computed.  Also see
 @(see error-triple).</p>

 <p>Even ACL2 users who are not programmers encounter error triples, because
 these are the values returned by evaluation of ACL2 @(see events).  Consider
 the following log, where the only user input is the @('defun') form following
 the @(see prompt).</p>

 @({
  ACL2 !>(defun foo (x) x)

  Since FOO is non-recursive, its admission is trivial.  We observe that
  the type of FOO is described by the theorem (EQUAL (FOO X) X).

  Summary
  Form:  ( DEFUN FOO ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FOO
  ACL2 !>
 })

 <p>All output above results from explicit calls of output functions, except
 for the next-to-last line, which contains @('FOO').  Notice the single-space
 indentation preceding @('FOO').  That space indicates that in fact, the value
 returned by evaluation of the @('defun') form is the error triple whose error
 flag is @('nil') and whose computed value is @('FOO').  By default, ACL2
 prints any error triple @('(mv nil val state)') by inserting a space before
 printing @('val').  You can change the default by setting state global @(tsee
 ld-post-eval-print) to @('t'); notice how the same result is printed
 below.</p>

 @({
  ACL2 !>:u
            0:x(EXIT-BOOT-STRAP-MODE)
  ACL2 !>(set-ld-post-eval-print t state)
  (NIL T <state>)
  ACL2 !>(defun foo (x) x)

  Since FOO is non-recursive, its admission is trivial.  We observe that
  the type of FOO is described by the theorem (EQUAL (FOO X) X).

  Summary
  Form:  ( DEFUN FOO ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  (NIL FOO <state>)
  ACL2 !>
 })

 <p>The way error triples are printed by @('ld') is controlled not only by
 state global @('ld-post-eval-print'), but also by state global
 @('ld-error-triples').  These are examples of ``ld specials''; see @(see ld),
 see @(see ld-post-eval-print), and see @(see ld-error-triples).</p>

 <p>It is so common to produce an error triple whose first (error flag)
 component is @('nil') that ACL2 provides a handy macro, @('value'), for this
 purpose.  Thus, @('(value <expression>)') is equivalent to @('(mv nil
 <expression> state)').  Also see @(see value-triple) for a similar construct
 that is a legal event form.</p>

 <p>We turn now to the topic of errors.  The macro @(tsee ER) ``causes'' an
 error, but there are really two quite different kinds of errors: ``soft'' and
 ``hard'' errors.  We use the term ``soft error'' to refer to a form that
 returns an error triple @('(mv erp val state)') for which @('erp') is
 non-@('nil').  Soft errors do not interrupt the normal flow of evaluation: the
 error triple is returned to the caller which interprets the @('erp') flag and
 @('val') as directed by the programmer.  Macros discussed below make it
 convenient to think about soft errors as short-circuiting the computation.
 Hard errors, on the other hand, do actually rip control away from the current
 evaluation and return it to the top-level loop.  Logically speaking,
 expressions that cause hard errors return @('nil') in the error case, but the
 @('nil') is never seen in actual evaluation because control does not return to
 the caller.</p>

 <p>Note that the function @(tsee abort!), which you can invoke by typing
 @(':')@(tsee a!), always returns to the top level.  Note that ACL2 can prove
 that @('(abort!)') returns @('nil') but that this cannot be confirmed by
 computation.</p>

 @({
  ACL2 !>(thm (equal (abort!) nil))

  Q.E.D.

  Summary
  Form:  ( THM ...)
  Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL)
          (:TYPE-PRESCRIPTION ABORT!))
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

  Proof succeeded.
  ACL2 !>(equal (abort!) nil)
  Abort to ACL2 top-level
  ...
  ACL2 !>
 })

 <p>(What actually happens with a hard error, including non-default cases, is a
 bit subtle; most readers will probably want to skip this paragraph.  The
 read-eval-print loop implemented by @(tsee ld) is implemented by a call of the
 ACL2 evaluator function, @('trans-eval'), on each input form.  If a hard error
 occurs during evaluation of an input form, its @('trans-eval') call will
 return with a soft error.  @(tsee Ld), in turn handles that soft error
 appropriately; see @(see ld-error-action).)</p>

 <p>The most common way to signal errors is the macro @(tsee er), which prints
 a formatted error message and returns a soft or hard error as specified by the
 call.  Note however that soft errors are signaled using @(':')@(tsee program)
 mode functions.</p>

 <p>Since the output signatures of soft and hard errors are different &mdash;
 hard errors ``return'' a single value while soft errors return a triple
 &mdash; mixing them in an expression requires embedding the hard error form in
 (an irrelevant) triple, as illustrated below.  All branches of the expression
 must produce an error triple if any branch does.</p>

 @({
  ACL2 !>(defun chk-find-or-abort (e x state)
           (declare (xargs :mode :program))
           (if (endp x)
               (value                          ; Note use of VALUE!
                 (er hard 'chk-find-or-abort
                     \"Did not find ~x0!\"
                      e))
               (if (not (integerp (car x)))
                   (er soft 'chk-find-or-abort
                       \"Non-integer, ~x0, in list!\"
                       (car x))
                   (if (eql (car x) e)
                       (value x)
                       (chk-find-or-abort e (cdr x) state)))))

  Summary
  Form:  ( DEFUN CHK-FIND-OR-ABORT ...)
  Rules: NIL
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   CHK-FIND-OR-ABORT
  ACL2 !>(chk-find-or-abort 3 '(1 2 3 4 5) state)
   (3 4 5)
  ACL2 !>(chk-find-or-abort 3 '(1 A 3 4 5) state)

  ACL2 Error in CHK-FIND-OR-ABORT:  Non-integer, A, in list!

  ACL2 !>(chk-find-or-abort 3 '(1 2 4 5) state)

  HARD ACL2 ERROR in CHK-FIND-OR-ABORT:  Did not find 3!
  ...
  ACL2 !>
 })

 <p>See @(see er) for further discussion of errors.  For some other individual
 topics related to errors see @(see assert$), see @(see break-on-error), see
 @(see error1), see @(see hard-error), see @(see illegal), and see @(see
 ld-error-triples).</p>

 <p>In the next section we discuss soft errors further, in the context of
 programming.</p>

 <p>SEQUENTIAL PROGRAMMING</p>

 <p>This section describes handy ways to modify state in steps, using macros
 that implement a sequence of @(tsee let) or @(tsee mv-let) bindings.  For
 example, suppose you want to assign the values 1 and 2 to two state globals
 @('one-var') and @('two-var'), respectively.  Because of ACL2's syntactic
 restrictions on @(tsee state), it is not legal simply to write
 @('(f-put-global 'two-var 2 (f-put-global 'one-var 1 state))').  However,
 @(tsee let) comes to the rescue as follows.</p>

 @({
  (let ((state (f-put-global 'one-var 1 state)))
    (let ((state (f-put-global 'two-var 2 state)))
      state))
 })

 <p>It is so common to bind state successively in such a manner that ACL2
 provides a macro, @(tsee pprogn), for this purpose.  Thus, an equivalent
 solution to the problem above is</p>

 @({
  (pprogn (f-put-global 'one-var 1 state)
          (f-put-global 'two-var 2 state)
          state)
 })

 <p>or, more simply, as follows.</p>

 @({
  (pprogn (f-put-global 'one-var 1 state)
          (f-put-global 'two-var 2 state))
 })

 <p>See @(see pprogn).  Note that the last form is allowed to return multiple
 values; the only requirement on the last form is that its value include
 @('state').</p>

 <p>It is also common to update the state using a sequence of forms such that
 each returns an error triple, where the intention is for evaluation to
 short-circuit immediately if a soft error is encountered.  Suppose
 @('<expr1>') and @('<expr2>') are expressions that return error triples, where
 the @('state') components of the error triples might be updated, and one
 wishes to evaluate @('<expr1>') and then @('<expr2>'), returning the
 (multiple) values returned by @('<expr2>') unless the error triple returned by
 @('<expr1>') is a soft error, in which case that error triple is returned.
 One can of course do so as follows.</p>

 @({
  (mv-let (erp val state)
          <expr1>
          (cond (erp (mv erp val state))
                (t <expr2>)))
 })

 <p>But ACL2 provides a handy macro, @(tsee er-progn), for this purpose.  The
 following code is equivalent to the code just above.</p>

 @({
  (er-progn <expr1> <expr2>)
 })

 <p>See @(see er-progn) for more details.  Note that unlike @(tsee pprogn), the
 return @(see signature) for the last expression must be the same as that of
 the others: an error triple.</p>

 <p>Let's consider how to use @('pprogn') and @('er-progn') together.  In the
 following example @('f1') and @('f2') both return @('state'), while each of
 @('g1') and @('g2') returns an error triple.  The following code modifies
 state by executing these in the order @('f1'), @('g1'), @('f2'), and finally
 @('g2'), returning @('(mv nil val state)') where @('val') is the value
 component of the error triple returned by @('g2') &mdash; except we return a
 soft error if @('g1') or @('g2') returns a soft error.</p>

 @({
  (pprogn (f1 x state)
          (er-progn (g1 x state)
                    (pprogn (f2 x state)
                            (g2 x state))))
 })

 <p>Finally, consider the @(see events) @(tsee progn) and @(tsee progn!).
 These have similar behavior to that of @(tsee er-progn).  However, @(tsee
 progn) and @(tsee progn!) may only be used in event contexts, for example at
 the top level or immediately underneath a call of @(tsee encapsulate) or
 @(tsee progn), while @(tsee er-progn) has no such restriction.  So when
 writing code, use @('er-progn') rather than @(tsee progn) or @(tsee progn!).
 In particular, the body of a @(tsee defun) must not have any calls of
 @('progn') (or of @('progn!')  either), and the same restriction holds for any
 code to be executed, such as the body of a @(tsee make-event) form.</p>

 <p>BINDING VARIABLES USING ERROR TRIPLES</p>

 <p>In this section we discuss the macro @('er-let*'), which is a variant of
 the special form, @(tsee let*), that is useful when programming with
 state.</p>

 <p>The macro @('er-let*') is useful when binding variables to the value
 components of error triples.  It is actually quite similar to @('er-progn'),
 described above, except that @('er-let*') binds variables.  First consider the
 following example.</p>

 @({
  (er-let* ((x1 (f1 state))
            (x2 (f2 x1 state)))
    (value (cons x1 x2)))
 })

 <p>The code just above is essentially equivalent to writing the following.</p>

 @({
  (mv-let (erp x1 state)
          (f1 state)
          (cond (erp (mv erp x1 state))
                (t (mv-let (erp x2 state)
                           (f2 x1 state)
                           (cond (erp (mv erp x2 state))
                                 (t (value (cons x1 x2))))))))
 })

 <p>As suggested by the example above, @('er-let*') has the same syntax as
 @('let*'), except that declarations are not supported.  (But note that
 @('ignore') declarations are not needed; all variables that are bound are also
 used, at least in the error case.  Consider replacing @('(cons x1 x2)') by
 @('nil') in the example displayed immediately above, and note that @('x1') and
 @('x2') are still used.)  However, unlike @('let*'), @('er-let*') requires
 that for each binding @('(var expr)'), the expression @('expr') must evaluate
 to an error triple and, moreover, it requires that the second argument (the
 ``body'') of @('er-let*') must evaluate to an error triple.  If one of the
 variable expressions (e.g., the @('f1') and @('f2') calls above) signals an
 error, its error triple is returned as the value of the @('er-let*').</p>

 <p>Of course, soft errors can be ``caught'' by using @(tsee mv-let) instead of
 @('er-let*') and simply ignoring the error flag or, more generally, by
 returning a non-erroneous error triple even if the error flag was on.</p>

 <p>BINDING STATE GLOBAL VARIABLES</p>

 <p>In this section we introduce a utility, @(tsee state-global-let*), that is
 an analogue of @('let*') for state global variables.  Consider the following
 example.</p>

 @({
  (state-global-let*
   ((inhibit-output-lst (add-to-set-eq 'summary (@ inhibit-output-lst))))
   (thm (equal x x)))
 })

 <p>This form binds state global variable @('inhibit-output-lst') to the result
 of adding the symbol, @('summary'), to the current value of that state global.
 Thus (see @(see set-inhibit-output-lst)), the usual summary is not printed
 when evaluating this call of @(tsee thm).</p>

 <p>See @(see state-global-let*) for more complete @(see documentation).</p>

 <p>INPUT AND OUTPUT</p>

 <p>In ACL2, most input and output involves the ACL2 state.  See @(see io).</p>

 <p>TIMINGS</p>

 <p>For how to obtain the time elapsed since the start of the ACL2 session, see
 @(see read-run-time).</p>

 <p>For a utility for saving times into the ACL2 state and for printing those
 saved times, see the community book @('misc/save-time.lisp').</p>

 <p>To time an evaluation (though this really isn't about state), see @(see
 time$).</p>

 <p>ENVIRONMENT AND SYSTEM</p>

 <p>Next, we mention briefly some ways in which ACL2 interacts with its
 environment using the ACL2 state.</p>

 <p>For how to read and write environment variables, see @(see getenv$) and see
 @(see setenv$).</p>

 <p>For how to run a command in the host operating system, see @(see
 sys-call), @(see sys-call+), and @(see sys-call*).</p>

 <p>REMARKS ON EVENTS AND LD</p>

 <p>In general, undefined or surprising behavior may occur when using ACL2
 @(see events) or calling @(see ld) in your programs.  In some cases ACL2
 enforces restrictions against these uses.  We strongly discourage using @(tsee
 ld) in programs, as it has been designed to be called only at the top level of
 a read-eval-print loop.  However, you may wish to read or write @(tsee ld)
 specials in your programs; see @(see ld).</p>

 <p>There is also a restriction on contexts in which @(tsee make-event) may be
 called: it may only be called in a context where an event is expected, such as
 the top level, in a book, or as an argument of @(tsee encapsulate) or @(tsee
 progn).  The reason is that ACL2 does very subtle and careful tracking of
 @(tsee make-event) expansions; and it is only able to do this in event
 contexts, where it is able to carry out such tracking accurately.</p>

 <p>ADVANCED TOPICS</p>

 <p>ACL2 provides the function @('trans-eval') to evaluate an arbitrary form
 (after translating it to a @(see term), i.e., into internal form).  For more
 information, we refer to reader to comments in the definition of
 @('trans-eval') in the ACL2 source code.  There are also many examples of its
 use in the ACL2 sources.</p>

 <p>For a function that provides the true absolute filename, with soft links
 resolved, see @(see canonical-pathname).</p>

 <p>For a function that returns a checksum on the characters in a channel, see
 @(see checksum).</p>

 <p>To obtain a random number, see @(see random$).</p>

 <p>If you are programming in raw-mode (see @(see set-raw-mode)) or in raw
 Lisp, use the variable @('*the-live-state*') in place of the variable
 @('state').</p>

 <p>We invite suggestions for additional advanced topics.</p>")

(defxdoc prompt
  :parents (ld)
  :short "The prompt printed by @(tsee ld)"
  :long "<p>The prompt printed by ACL2 conveys information about various
 ``modes.''  See @(see default-print-prompt) and see @(see ld-prompt) for
 details.</p>

 <p>The prompt during raw Lisp breaks is, with most Common Lisp
 implementations, adjusted by ACL2 to include the string @('\"[RAW LISP')\"],
 in order to reminder users not to submit ACL2 forms there; see @(see breaks).
 For Lisps that seem to use the same code for printing prompts at the top-level
 as in @(see breaks), the top-level prompt is similarly adjusted.  For Lisps
 with the above prompt adjustment, The following forms may be executed in raw
 Lisp (i.e., after typing @(':q')).</p>

 @({
  (install-new-raw-prompt) ; install prompt with [RAW LISP] as described above
  (install-old-raw-prompt) ; revert to original prompt from host Common Lisp
 })")

(defxdoc proof-builder
  :parents (acl2 debugging)
  :short "An interactive tool for controlling ACL2's proof processes."
  :long "<p>Call this up with @('(verify ...)').</p>

 <p>The <i>interactive proof-builder</i> provides a way to explore the
 development of ACL2 proofs below the level of the ACL2 prover (as typically
 used by @(tsee thm) and @(see events) such as @(tsee defthm)).  To use this
 tool, invoke the @(tsee verify) command, for example as follows.</p>

 @({
 ACL2 !>(verify (equal (append (append x y) z)
                       (append x (append y z))))
 ->:
 })

 <p>Then at the @('\"->:\"') prompt, one submits commands that operate on a
 stack of goals, starting with the single goal that was supplied to @('VERIFY')
 as shown above.  The final command (or ``instruction'') can be an @('exit')
 command, which can print out a @(tsee defthm) event if the goal stack is
 empty; see @(see proof-builder-commands), in particular the @('exit') command.
 That resulting @('defthm') event includes an @(':')@(tsee instructions)
 parameter, which directs replay of the interactive proof-builder commands (for
 example during certification of a book containing that event; see @(see
 books)).</p>

 <p>If you exit the interactive proof-builder's loop, you may re-enter that
 session at the same point using the command @('(verify)'), i.e., with no
 arguments.  The commands @('save') and @('retrieve') may be invoked to manage
 more than one session.</p>

 <p>The interactive proof-builder can be invoked on a specific subgoal, and the
 resulting @(':instructions') can be given as a hint to the theorem prover for
 that subgoal.  See @(see instructions).</p>

 <p>A tutorial is available <a
 href='http://www.cs.utexas.edu/users/kaufmann/tutorial/rev3.html'>here</a>.
 That tutorial illustrates more than just the interactive proof-builder.  The
 portion relevant to the proof-builder may be accessed directly <a
 href='http://www.cs.utexas.edu/users/kaufmann/tutorial/rev3.html#slide29'>here</a>.</p>

 <p>See @(see set-evisc-tuple) for how to arrange that output is printed in
 abbreviated form.  In general, the interactive proof-builder uses the
 @(':TERM') @(see evisc-tuple) described in that documentation.</p>

 <p>Individual proof-builder commands are documented in subsection @(see
 proof-builder-commands).  For a list of perhaps the most commonly used
 commands, see @(see proof-builder-commands-short-list).</p>")

(defxdoc proof-builder-commands
  :parents (proof-builder)
  :short "List of commands for the interactive proof-builder"
  :long "<p>This documentation section contains documentation for individual
 commands that can be given inside the interactive @(see proof-builder) loop
 that is entered using @(tsee verify).  For a summary of (arguably) the most
 useful commands, see @(see proof-builder-commands-short-list).</p>")

(defxdoc proof-builder-commands-short-list
  :parents (proof-builder proof-builder-commands)
  :short "Perhaps the most commonly used @(see proof-builder) commands"
  :long "<p>The list of subtopics below includes what are arguably the most
  useful, and most commonly used, @(see proof-builder) commands.</p>")

(defxdoc proof-checker
  :parents (proof-builder)
  :short "Old name for @(see proof-builder)"
  :long "<p>See @(see proof-builder).  Historically, this tool was misnamed the
 ``proof-checker'', but since the tool is used for building and exploring (what
 could be called) proofs rather than for checking them, its name was changed to
 ``proof-builder'' in 2016.</p>")

(defxdoc proof-of-well-foundedness
  :parents (ordinals)
  :short "A proof that @(tsee o<) is well-founded on @(tsee o-p)s"
  :long "<p>The soundness of ACL2 rests in part on the well-foundedness of
 @(tsee o<) on @(tsee o-p)s.  This can be taken as obvious if one is willing to
 grant that those concepts are simply encodings of the standard mathematical
 notions of the ordinals below @('epsilon-0') and its natural ordering
 relation.  But it is possible to prove that @(tsee o<) is well-founded on
 @(tsee o-p)s without having to assert any connection to the ordinals and that
 is what we do here.  The community book
 @('books/ordinals/proof-of-well-foundedness') carries out the proof outlined
 below in ACL2, using only that the natural numbers are well-founded.</p>

 <p>Before outlining the above mentioned proof, we note that in the analogous
 documentation page of ACL2 Version_2.7, there is a proof of the
 well-foundedness of @('e0-ord-<') on @('e0-ordinalp')s, the less-than relation
 and recognizer for the old ordinals (that is, for the ordinals appearing in
 ACL2 up through that version).  Manolios and Vroon have given a proof in ACL2
 Version_2.7 that the current ordinals (based on @(tsee o<) and @(tsee o-p))
 are order-isomorphic to the old ordinals (based on @('e0-ord-<') and
 @('e0-ordinalp')).  Their proof establishes that switching from the old
 ordinals to the current ordinals preserves the soundness of ACL2.  For details
 see their paper:</p>

 <code>
 Manolios, Panagiotis &amp; Vroon, Daron.
 Ordinal arithmetic in ACL2.
 Kaufmann, Matt, &amp; Moore, J Strother (eds).
 Fourth International Workshop on the ACL2 Theorem
 Prover and Its Applications (ACL2-2003),
 July, 2003.
 See <a href='http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/'>http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/</a>.
 </code>

 <p>We now give an outline of the above mentioned proof of well-foundedness.
 We first observe three facts about @(tsee o<) on ordinals that have been
 proved by ACL2 using only structural induction on lists.  These theorems can
 be proved by hand.</p>

 @({
  (defthm transitivity-of-o<
    (implies (and (o< x y)
                  (o< y z))
             (o< x z))
    :rule-classes nil)

  (defthm non-circularity-of-o<
    (implies (o< x y)
             (not (o< y x)))
    :rule-classes nil)

  (defthm trichotomy-of-o<
    (implies (and (o-p x)
                  (o-p y))
             (or (equal x y)
                 (o< x y)
                 (o< y x)))
    :rule-classes nil)
 })

 <p>These three properties establish that @(tsee o<) orders the @(tsee o-p)s.
 To put such a statement in the most standard mathematical nomenclature, we can
 define the macro:</p>

 @({
  (defmacro o<= (x y)
    `(not (o< ,y ,x)))
 })

 <p>and then establish that @('o<=') is a relation that is a simple, complete
 (i.e., total) order on ordinals by the following three lemmas, which have been
 proved:</p>

 @({
  (defthm antisymmetry-of-o<=
    (implies (and (o-p x)
                  (o-p y)
                  (o<= x y)
                  (o<= y x))
             (equal x y))
    :rule-classes nil
    :hints ((\"Goal\" :use non-circularity-of-o<)))

  (defthm transitivity-of-o<=
    (implies (and (o-p x)
                  (o-p y)
                  (o<= x y)
                  (o<= y z))
             (o<= x z))
    :rule-classes nil
    :hints ((\"Goal\" :use transitivity-of-o<)))

  (defthm trichotomy-of-o<=
    (implies (and (o-p x)
                  (o-p y))
             (or (o<= x y)
                 (o<= y x)))
    :rule-classes nil
    :hints ((\"Goal\" :use trichotomy-of-o<)))
 })

 <p>Crucially important to the proof of the well-foundedness of @(tsee o<) on
 @(tsee o-p)s is the concept of ordinal-depth, abbreviated @('od'):</p>

 @({
  (defun od (l)
    (if (o-finp l)
        0
      (1+ (od (o-first-expt l)))))
 })

 <p>If the @('od') of an @(tsee o-p) @('x') is smaller than that of an @(tsee
 o-p) @('y'), then @('x') is @(tsee o<) @('y'):</p>

 @({
  (defun od-1 (x y)
    (if (o-finp x)
        (list x y)
      (od-1 (o-first-expt x) (o-first-expt y))))

  (defthm od-implies-ordlessp
    (implies (and (o-p x)
                  (< (od x) (od y)))
             (o< x y))
    :hints ((\"Goal\"
             :induct (od-1 x y))))
 })

 <p>Remark.  A consequence of this lemma is the fact that if @('s = s(1)'),
 @('s(2)'), ... is an infinite, @(tsee o<) descending sequence of @(tsee o-p)s,
 then @('od(s(1))'), @('od(s(2))'), ... is a ``weakly'' descending sequence of
 non-negative integers: @('od(s(i))') is greater than or equal to
 @('od(s(i+1))').</p>

 <p><i>Lemma Main.</i> For each non-negative integer @('n'), @(tsee o<)
 well-orders the set of @(tsee o-p)s with @('od') less than or equal to @('n')
 .</p>

 @({
   Base Case.  n = 0.  The o-ps with 0 od are the non-negative
   integers.  On the non-negative integers, o< is the same as <.

   Induction Step.  n > 0.  We assume that o< well-orders the
   o-ps with od less than n.

     If o< does not well-order the o-ps with od less than or equal to n,
     consider, D, the set of infinite, o< descending sequences of o-ps of od
     less than or equal to n.  The first element of a sequence in D has od n.
     Therefore, the o-first-expt of the first element of a sequence in D has od
     n-1.  Since o<, by IH, well-orders the o-ps with od less than n, the set
     of o-first-expts of first elements of the sequences in D has a minimal
     element, which we denote by B and which has od of n-1.

     Let k be the minimum integer such that for some infinite, o< descending
     sequence s of o-ps with od less than or equal to n, the first element of s
     has an o-first-expt of B and an o-first-coeff of k.  Notice that k is
     positive.

     Having fixed B and k, let s = s(1), s(2), ... be an infinite, o<
     descending sequence of o-ps with od less than or equal to n such that s(1)
     has a o-first-expt of B and an o-first-coeff of k.

     We show that each s(i) has a o-first-expt of B and an o-first-coeff of
     k. For suppose that s(j) is the first member of s either with o-first-expt
     B and o-first-coeff m (m neq k) or with o-first-expt B' and o-first-coeff
     B' (B' neq B). If (o-first-expt s(j)) = B', then B' has od n-1 (otherwise,
     by IH, s would not be infinite) and B' is o< B, contradicting the
     minimality of B. If 0 < m < k, then the fact that the sequence beginning
     at s(j) is infinitely descending contradicts the minimality of k. If m >
     k, then s(j) is greater than its predecessor; but this contradicts the
     fact that s is descending.

     Thus, by the definition of o<, for s to be a decreasing sequence of o-ps,
     (o-rst s(1)), (o-rst s(2)), ... must be a decreasing sequence. We end by
     showing this cannot be the case. Let t = t(1), t(2), ... be an infinite
     sequence of o-ps such that t(i) = (o-rst s(i)). Then t is infinitely
     descending. Furthermore, t(1) begins with an o-p B' that is o< B. Since t
     is in D, t(1) has od n, therefore, B' has od n-1. But this contradicts the
     minimality of B. Q.E.D.
 })

 <p>Theorem.  @(tsee o<) well-orders the @(tsee o-p)s.  Proof.  Every
 infinite,@(' o<') descending sequence of @(tsee o-p)s has the property that
 each member has @('od') less than or equal to the @('od'), @('n'), of the
 first member of the sequence.  This contradicts Lemma Main.  Q.E.D.</p>")

(defxdoc proof-tree
  :parents (debugging)
  :short "Proof tree displays"
  :long "<p>A view of ACL2 proofs may be obtained by way of ``proof tree
 displays,'' which appear in proof output (see @(see proofs-co)) when
 proof-tree output is enabled (see below) When ACL2 starts a proof and
 proof-tree output is enabled, the proof output begins with the following
 string.</p>

 @({
  << Starting proof tree logging >>
 })

 <p>Then for each goal encountered during the proof, a corresponding proof tree
 display (as described below) is printed into the proof output: first the
 characters in the constant string @('*proof-tree-start-delimiter*') are
 printed, then the proof tree display, and finally the characters in the
 constant string @('*proof-tree-end-delimiter*').</p>

 <p>External tools may present proof tree displays in a separate window.  In
 particular, a tool distributed with the ACL2 community books customizes the
 emacs environment to provide window-based proof tree displays together with
 commands for traversing the proof transcript; see the discussion of ``ACL2
 proof-tree support'' in file @('emacs/emacs-acl2.el') distributed with
 ACL2.</p>

 <p>The command @(':start-proof-tree') enables proof-tree output, while
 @(':stop-proof-tree') disables proof-tree output; see @(see start-proof-tree)
 and see @(see stop-proof-tree).</p>

 <p>Here is an example of a proof tree display, with comments.  Lines marked
 with ``c'' are considered ``checkpoints,'' i.e., goals whose scrutiny may be
 of particular value.</p>

 @({
  ( DEFTHM PLUS-TREE-DEL ...)    ;currently proving PLUS-TREE-DEL
     1 Goal preprocess   ;\"Goal\" creates 1 subgoal by preprocessing
     2 |  Goal' simp     ;\"Goal'\" creates 2 subgoals by simplification
  c  0 |  |  Subgoal 2 PUSH *1   ;\"Subgoal 2\" pushes \"*1\" for INDUCT
  ++++++++++++++++++++++++++++++ ;first pass thru waterfall completed
  c  6 *1 INDUCT                 ;Proof by induction of \"*1\" has
       |  <5 more subgoals>      ; created 6 top-level subgoals.  At
                                 ; this point, one of those 6 has been
                                 ; proved, and 5 remain to be proved.
                                 ; We are currently working on the
                                 ; first of those 5 remaining goals.
 })

 <p>See @(see proof-tree-examples) for many examples that contain proof tree
 displays.  But first, we summarize the kinds of lines that may appear in a
 proof tree display.  The simplest form of a proof tree display is a header
 showing the current event, followed by list of lines, each having one of the
 following forms.</p>

 @({
      n <goal> <process> ...
 })

 <p>Says that the indicated goal created @('n') subgoals using the indicated
 process.  Here ``...'' refers to possible additional information.</p>

 @({
  c   n <goal> <process> ...
 })

 <p>As above, but calls attention to the fact that this goal is a
 ``checkpoint'' in the sense that it may be of particular interest.  Some
 displays may overwrite ``c'' with ``&gt;'' to indicate the current checkpoint
 being shown in the proof transcript.</p>

 @({
       |  <goal> ...
       |  |  <k subgoals>
 })

 <p>Indicates that the goal just above this line, which is pointed to by the
 rightmost vertical bar (``|''), has @('k') subgoals, none of which have yet
 been processed.</p>

 @({
       |  <goal> ...
       |  |  <k more subgoals>
 })

 <p>As above, except that some subgoals have already been processed.</p>

 @({
  ++++++++++++++++++++++++++++++
 })

 <p>Separates successive passes through the ``waterfall''.  Thus, this
 ``fencepost'' mark indicates the start of a new proof by induction or of a new
 forcing round.</p>

 <p>See @(see proof-tree-examples) for detailed examples.  See @(see
 checkpoint-forced-goals) to learn how to mark goals as checkpoints that @(see
 force) the creation of goals in forcing rounds.  Finally, see @(see
 proof-tree-details) for some points not covered elsewhere.</p>")

(defxdoc proof-tree-details
  :parents (proof-tree)
  :short "Proof tree details not covered elsewhere"
  :long "<p>See @(see proof-tree) for an introduction to proof trees, and for a
 list of related topics.  Here we present some details not covered
 elsewhere.</p>

 <p>1.  When proof tree display is enabled (because the command @(':')@(tsee
 stop-proof-tree) has not been executed, or has been superseded by a later
 @(':')@(tsee start-proof-tree) command), then time summaries will include the
 time for proof tree display.  This time includes the time spent computing with
 proof trees, such as the pruning process described briefly above.  Even when
 proof trees are not displayed, such as when their display is turned off in the
 middle of a proof, this time will be printed if it is not 0.</p>

 <p>2.  When a goal is given a @(':bye') in a proof (see @(see hints)), it is
 treated for the purpose of proof tree display just as though it had been
 proved.</p>

 <p>3.  Several @(see state) global variables affect proof tree display.  @('(@
 proof-tree-indent)') is initially the string @('\"| \"'): it is the string
 that is laid down the appropriate number of times to effect indentation.
 @('(@ proof-tree-buffer-width)') is initially the value of
 @('(fmt-soft-right-margin state)'), and is used to prevent printing of the
 annotation ``(@(see force)d ...)'' in any greater column than this value.
 However, @('(assign proof-tree-buffer-width nil)') to avoid any such
 suppression.  Finally, @('(@ checkpoint-processors)') is a list of processors
 from the constant list @('*preprocess-clause-ledge*'), together with
 @(':induct').  You may remove elements of @('(@ checkpoint-processors)') to
 limit which processes are considered checkpoints, but note that this can
 affect what is printed by gag-mode (see @(see set-gag-mode)).</p>

 <p>4.  When @(':')@(tsee otf-flg) is not set to @('t') in a proof, and the
 prover then decides to revert to the original goal and prove it by induction,
 the proof tree display will reflect this fact as shown here:</p>

 @({
  c  0 |  |  Subgoal 2 PUSH (reverting)
 })

 <p>5. The usual @(see failure) message is printed as part of the prooftree
 display when a proof has failed.</p>")

(defxdoc proof-tree-examples
  :parents (proof-tree)
  :short "Proof tree example"
  :long "<p>See @(see proof-tree) for an introduction to proof trees, and for a
 list of related topics.  Here we present a detailed example followed by a
 shorter example that illustrates proof by induction.</p>

 <p>Consider the @(see guard) proof for the definition of a function
 @('cancel_equal_plus'); the body of this definition is of no importance here.
 The first proof tree display is:</p>

 @({
  ( DEFUN CANCEL_EQUAL_PLUS ...)
    18 Goal preprocess
       |  <18 subgoals>
 })

 <p>This is to be read as follows.</p>

 <blockquote><p>At this stage of the proof we have encountered the top-level
  goal, named \"Goal\", which generated 18 subgoals using the ``preprocess''
  process.  We have not yet begun to work on those subgoals.</p></blockquote>

 <p>The corresponding message from the ordinary prover output is:</p>

 <blockquote><p>By case analysis we reduce the conjecture to the following 18
  conjectures.</p></blockquote>

 <p>Note that the field just before the name of the goal (@('\"Goal\"')), which
 here contains the number 18, indicates the number of cases (children) created
 by the goal using the indicated process.  This number will remain unchanged as
 long as this goal is displayed.</p>

 <p>The next proof tree display is:</p>

 @({
  ( DEFUN CANCEL_EQUAL_PLUS ...)
    18 Goal preprocess
     1 |  Subgoal 18 simp
       |  |  <1 subgoal>
       |  <17 more subgoals>
 })

 <p>which indicates that at this point, the prover has used the simplification
 (``simp'') process on Subgoal 18 to create one subgoal (``&lt;1
 subgoal&gt;'').  The vertical bar (``|'') below ``Subgoal 18'', accompanied by
 the line below it, signifies that there are 17 siblings of Subgoal 18 that
 remain to be processed.</p>

 <p>The next proof tree displayed is:</p>

 @({
  ( DEFUN CANCEL_EQUAL_PLUS ...)
    18 Goal preprocess
     1 |  Subgoal 18 simp
  c  2 |  |  Subgoal 18' ELIM
       |  |  |  <2 subgoals>
       |  <17 more subgoals>
 })

 <p>Let us focus on the fourth line of this display:</p>

 @({
  c  2 |  |  Subgoal 18' ELIM
 })

 <p>The ``c'' field marks this goal as a ``checkpoint'', i.e., a goal worthy of
 careful scrutiny.  In fact, any goal that creates children by a process other
 than ``preprocess'' or ``simp'' is marked as a checkpoint.  In this case, the
 destructor-elimination (``@(see ELIM)'') process has been used to create
 subgoals of this goal.  The indentation shows that this goal, Subgoal 18', is
 a child of Subgoal 18.  The number ``2'' indicates that 2 subgoals have been
 created (by @(see ELIM)).  Note that this information is consistent with the
 line just below it, which says ``&lt;2 subgoals&gt;''.</p>

 <p>Finally, the last line of this proof tree display,</p>

 @({
       |  <17 more subgoals>
 })

 <p>is connected by vertical bars (``|'') up to the string @('\"Subgoal 18\"'),
 which suggests that there are 17 immediate subgoals of Goal remaining to
 process after Subgoal 18.  Note that this line is indented one level from the
 second line, which is the line for the goal named @('\"Goal\"').  The display
 is intended to suggest that the subgoals of Goal that remain to be proved
 consist of Subgoal 18 together with 17 more subgoals.</p>

 <p>The next proof tree display differs from the previous one only in that now,
 Subgoal 18' has only one more subgoal to be processed.</p>

 @({
  ( DEFUN CANCEL_EQUAL_PLUS ...)
    18 Goal preprocess
     1 |  Subgoal 18 simp
  c  2 |  |  Subgoal 18' ELIM
       |  |  |  <1 more subgoal>
       |  <17 more subgoals>
 })

 <p>Note that the word ``more'' in ``&lt;1 more subgoal&gt;'' tells us that
 there was originally more than one subgoal of Subgoal 18.  In fact that
 information already follows from the line above, which (as previously
 explained) says that Subgoal 18' originally created 2 subgoals.</p>

 <p>The next proof tree display occurs when the prover completes the proof of
 that ``1 more subgoal'' referred to above.</p>

 @({
  ( DEFUN CANCEL_EQUAL_PLUS ...)
    18 Goal preprocess
       |  <17 more subgoals>
 })

 <p>Then, Subgoal 17 is processed and creates one subgoal, by
 simplification:</p>

 @({
  ( DEFUN CANCEL_EQUAL_PLUS ...)
    18 Goal preprocess
     1 |  Subgoal 17 simp
       |  |  <1 subgoal>
       |  <16 more subgoals>
 })

 <p>... and so on.</p>

 <p>Later in the proof one might find the following successive proof tree
 displays.</p>

 @({
  ( DEFUN CANCEL_EQUAL_PLUS ...)
    18 Goal preprocess
       |  <9 more subgoals>

  ( DEFUN CANCEL_EQUAL_PLUS ...)

    18 Goal preprocess
     0 |  Subgoal 9 simp (FORCED)
       |  <8 more subgoals>
 })

 <p>These displays tell us that Subgoal 9 simplified to @('t') (note that the
 ``0'' shows clearly that no subgoals were created), but that some rule's
 hypotheses were @(see force)d.  Although this goal is not checkpointed (i.e.,
 no ``c'' appears on the left margin), one can cause such goals to be
 checkpointed; see @(see checkpoint-forced-goals).</p>

 <p>In fact, the proof tree displayed at the end of the ``main proof''(the 0-th
 forcing round) is as follows.</p>

 @({
  ( DEFUN CANCEL_EQUAL_PLUS ...)
    18 Goal preprocess
     0 |  Subgoal 9 simp (FORCED)
     0 |  Subgoal 8 simp (FORCED)
     0 |  Subgoal 7 simp (FORCED)
     0 |  Subgoal 6 simp (FORCED)
     0 |  Subgoal 4 simp (FORCED)
     0 |  Subgoal 3 simp (FORCED)
 })

 <p>This is followed by the following proof tree display at the start of the
 forcing round.</p>

 @({
    18 Goal preprocess
     0 |  Subgoal 9 simp (FORCED [1]Subgoal 4)
     0 |  Subgoal 8 simp (FORCED [1]Subgoal 6)
     0 |  Subgoal 7 simp (FORCED [1]Subgoal 1)
     0 |  Subgoal 6 simp (FORCED [1]Subgoal 3)
     0 |  Subgoal 4 simp (FORCED [1]Subgoal 5)
     0 |  Subgoal 3 simp (FORCED [1]Subgoal 2)
  ++++++++++++++++++++++++++++++
     6 [1]Goal FORCING-ROUND
     2 |  [1]Subgoal 6 preprocess
       |  |  <2 subgoals>
       |  <5 more subgoals>
 })

 <p>This display shows which goals to ``blame'' for the existence of each goal
 in the forcing round.  For example, Subgoal 9 is to blame for the creation of
 [1]Subgoal 4.</p>

 <p>Actually, there is no real goal named @('\"[1]Goal\"').  However, the
 line</p>

 @({
     6 [1]Goal FORCING-ROUND
 })

 <p>appears in the proof tree display to suggest a ``parent'' of the six
 top-level goals in that forcing round.  As usual, the numeric field before the
 goal name contains the original number of children of that (virtual, in this
 case) goal &mdash; in this case, 6.</p>

 <p>In our example proof, Subgoal 6 eventually gets proved, without doing any
 further forcing.  At that point, the proof tree display looks as follows.</p>

 @({
  ( DEFUN CANCEL_EQUAL_PLUS ...)
    18 Goal preprocess
     0 |  Subgoal 9 simp (FORCED [1]Subgoal 4)
     0 |  Subgoal 7 simp (FORCED [1]Subgoal 1)
     0 |  Subgoal 6 simp (FORCED [1]Subgoal 3)
     0 |  Subgoal 4 simp (FORCED [1]Subgoal 5)
     0 |  Subgoal 3 simp (FORCED [1]Subgoal 2)
  ++++++++++++++++++++++++++++++
     6 [1]Goal FORCING-ROUND
       |  <5 more subgoals>
 })

 <p>Notice that the line for Subgoal 8,</p>

 @({
     0 |  Subgoal 8 simp (FORCED [1]Subgoal 6)
 })

 <p>no longer appears.  That is because the goal [1]Subgoal 6 has been proved,
 along with all its children; and hence, the proof of Subgoal 8 no longer
 depends on any further reasoning.</p>

 <p>The final two proof tree displays in our example are as follows.</p>

 @({
  ( DEFUN CANCEL_EQUAL_PLUS ...)
    18 Goal preprocess
     0 |  Subgoal 7 simp (FORCED [1]Subgoal 1)
  ++++++++++++++++++++++++++++++
     6 [1]Goal FORCING-ROUND
     2 |  [1]Subgoal 1 preprocess
     1 |  |  [1]Subgoal 1.1 preprocess
     1 |  |  |  [1]Subgoal 1.1' simp
  c  3 |  |  |  |  [1]Subgoal 1.1'' ELIM
       |  |  |  |  |  <1 more subgoal>

  ( DEFUN CANCEL_EQUAL_PLUS ...)
  <<PROOF TREE IS EMPTY>>
 })

 <p>The explanation for the empty proof tree is simple: once [1]Subgoal 1.1.1
 was proved, nothing further remained to be proved.  In fact, the much
 sought-after ``Q.E.D.'' appeared shortly after the final proof tree was
 displayed.</p>

 <p>Let us conclude with a final, brief example that illustrates proof by
 induction.  Partway through the proof one might come across the following
 proof tree display.</p>

 @({
  ( DEFTHM PLUS-TREE-DEL ...)
     1 Goal preprocess
     2 |  Goal' simp
  c  0 |  |  Subgoal 2 PUSH *1
       |  |  <1 more subgoal>
 })

 <p>This display says that in the attempt to prove a theorem called
 @('plus-tree-del'), preprocessing created the only child Goal' from Goal, and
 Goal' simplified to two subgoals.  Subgoal 2 is immediately pushed for proof
 by induction, under the name ``*1''.  In fact if Subgoal 1 simplifies to
 @('t'), then we see the following successive proof tree displays after the one
 shown above.</p>

 @({
  ( DEFTHM PLUS-TREE-DEL ...)
     1 Goal preprocess
     2 |  Goal' simp
  c  0 |  |  Subgoal 2 PUSH *1

  ( DEFTHM PLUS-TREE-DEL ...)
     1 Goal preprocess
     2 |  Goal' simp
  c  0 |  |  Subgoal 2 PUSH *1
  ++++++++++++++++++++++++++++++
  c  6 *1 INDUCT
       |  <5 more subgoals>
 })

 <p>The separator ``+++++...'' says that we are beginning another trip through
 the waterfall.  In fact this trip is for a proof by induction (as opposed to a
 forcing round), as indicated by the word ``INDUCT''.  Apparently *1.6 was
 proved immediately, because it was not even displayed; a goal is only
 displayed when there is some work left to do either on it or on some goal that
 it brought (perhaps indirectly) into existence.</p>

 <p>Once a proof by induction is completed, the ``PUSH'' line that refers to
 that proof is eliminated (``pruned'').  So for example, when the present proof
 by induction is completed, the line</p>

 @({
  c  0 |  |  Subgoal 2 PUSH *1
 })

 <p>is eliminated, which in fact causes the lines above it to be eliminated
 (since they no longer refer to unproved children).  Hence, at that point one
 might expect to see:</p>

 @({
  ( DEFTHM PLUS-TREE-DEL ...)
  <<PROOF TREE IS EMPTY>>
 })

 <p>However, if the proof by induction of *1 necessitates further proofs by
 induction or a forcing round, then this ``pruning'' will not yet be
 done.</p>")

(defxdoc proofs-co
  :parents (io acl2-built-ins)
  :short "The proofs character output channel"
  :long "<p>@('Proofs-co') is an @(tsee ld) special (see @(see ld)).  The
 accessor is @('(proofs-co state)') and the updater is @('(set-proofs-co val
 state)').  @('Proofs-co') must be an open character output channel.  It is to
 this channel that @(tsee defun), @(tsee defthm), and the other event @(see
 command)s print their commentary.</p>

 <p>``Proofs-co'' stands for ``proofs character output.'' The initial value of
 @('proofs-co') is the same as the value of @(tsee *standard-co*) (see @(see
 *standard-co*)).</p>")

(defxdoc proper-consp
  :parents (lists acl2-built-ins)
  :short "Recognizer for proper (null-terminated) non-empty lists"
  :long "<p>@('Proper-consp') is the function that checks whether its argument
 is a non-empty list that ends in @('nil').  Also see @(see true-listp).</p>

 @(def proper-consp)")

(defxdoc props
  :parents (world)
  :short "Print the ACL2 properties on a symbol"
  :long "@({
  Example:
  :props assoc-eq
 })

 <p>@('Props') takes one argument, a symbol, and prints all of the properties
 that are on that symbol in the ACL2 @(see world).</p>")

(defxdoc protect-memoize-statistics
  :parents (memoize)
  :short "Ensure the integrity of memoization statistics even upon aborts"

  :long "<p>Example Forms:</p>

 @({
  (f-put-global 'protect-memoize-statistics t state)
  (assign protect-memoize-statistics t) ; same effect as above
 })

 <p>By default, if calls of @(tsee memoize)d functions are aborted, then
 statistics reported by @(see memsum) for those calls will often be incorrect.
 Since aborts are relatively rare, this seems a reasonable default, since
 avoiding such inaccuracy incurs some additional computation time.  However,
 evaluation of either of the forms above will arrange that for functions
 memoized <i>after</i> such evaluation, the accuracy of the statistics will not
 be adversely affected by aborts (again, at the expense of some additional
 computation time).</p>

 <p>Once again: evaluation of a form displayed above only affects behavior for
 future calls of @(tsee memoize), not for functions already memoized at the
 time of that form's evaluation (unless the function is subsequently @(see
 unmemoize)d and then once again @(see memoize)d).</p>

 <p>To revert to the default state in which performance is preferred to
 accuracy of memoization statistics after aborts, evaluate either of the
 following forms.</p>

 @({
  (f-put-global 'protect-memoize-statistics nil state)
  (assign protect-memoize-statistics nil) ; same effect as above
 })

 <p>The following demo illustrates the effect of assigning to
 protect-memoize-statistics.</p>

 @({
 (defun foo (n)
   (declare (xargs :guard (natp n)))
   (progn$
    (sleep n)
    n))

 ; OPTIONALLY:
 (assign protect-memoize-statistics t)

 (memoize 'foo)

 (clear-memoize-statistics) ; for good measure
 (memsum) ; should have nothing to report
 (foo 1)
 (memsum) ; reports 1 call, 1 second

 ; Now: submit this and then abort with an interrupt it after about 3 seconds.
 (foo 15)

 ; See explanation below.
 (memsum)
 })

 <p>If the ``OPTIONAL'' form above is omitted, we get the default behavior:
 the statistics from @(tsee memsum) will show 2 calls of @('foo') taking only
 took 1 second total, for an average of only 0.5 seconds, because no time was
 recorded for the aborted call.  However, if the ``OPTIONAL'' form above is
 included, then you will see statistics that look accurate.</p>")

(defxdoc prover-output
  :parents (acl2 io)
  :short "Methods for controlling the output produced by the ACL2 prover"
  :long "<p>This topic pertains primarily to processing of @(see events), often
 involving the prover.  For a general discussion about redirection of ACL2
 output to a file, see @(see output-to-file).</p>")

(defxdoc provisional-certification

; Here we put random remarks about provisional certification that are not fully
; covered in the :doc topic (which serves as a prerequisite for these remarks).

; Let us consider the :pcert-info field of a cert-obj, which comes from the
; :pcert-info field of a .pcert0 file.  The value is :PROVED when the .pcert0
; file was created by the Pcertify+ procedure, but now we consider the value
; when the .pcert0 file was created by the Pcertify procedure.  The value is an
; expansion-alist that associates indices with full expansions, before applying
; elide-locals or elide-locals-rec.  When there is no such elision in the
; regular :expansion-alist, no entry is made in the :pcert-info field.  We do
; not elide locals during the Pcertify procedure; then when writing out the
; .pcert0 file, we use a strong version of
; elide-locals-and-split-expansion-alist (essentially, a strong version of
; elide-locals-from-expansion-alist) that dives inside encapsulates to elide
; locals.  Note that the :pcert-info field does not contribute to the book-hash
; or cert-hash values, the reason being that we want those values not to change
; between a .pcert0 file and the .pcert1 file derived from it.

; Next, we discuss issues related to include-book and provisionally certified
; books.

; ACL2 users sometimes arrange to include books to build a certification world,
; as a precursor to a call of certify-book.  When using provisional
; certification, the .cert files might not exist for those books.  Of course,
; we allow .pcert0 and .pcert1 files to serve as certificate files when inside
; a call of certify-book with a :pcert argument of :create or :convert.  But
; the include-book forms mentioned above are executed before calling
; certify-book.  How can we support the use of .pcert0 and .pcert1 files in
; such cases?

; Our solution is to allow .pcert0 and .pcert1 files to serve as certificate
; files in all circumstances, with the following two kinds of special handling.
; First, and most important, we do the following two things: (a) we make a note
; in the world (in world global pcert-books) when cert-op is not :create-pcert,
; :create+convert-pcert or :convert-pcert, and an include-book has taken place
; that uses a .pcert0 or .pcert1 file as a certificate, and (b) we disallow
; certify-book in any such world unless the :pcert argument has value :create,
; t, or :convert (where this argument might, of course, come from environment
; variable ACL2_PCERT_ARG).  Second, we print a warning when using a .pcert0 or
; .pcert1 file unless we are in an environment with ACL2_PCERT set to a
; non-empty string.  (Of course, that warning may also be inhibited by
; set-inhibit-warnings or set-inhibit-output-lst.)

  :parents (books-certification)
  :short "Certify a book in stages for improved book-level parallelism"
  :long "<p>Provisional certification is a process that can increase
 parallelism when certifying books in parallel, typically using `make', when
 certifying a collection of @(see books).  We got this idea from Jared Davis,
 who developed rudimentary provisional certification schemes first at Rockwell
 Collins and later for his `Milawa' project.  Our design has also benefited
 from conversations with Sol Swords.</p>

 <p>Warning: as of November 2014, enabling provision certification via the
 @('ACL2_PCERT') flag can not be reliably enabled at the Makefile level (as is
 shown below).  See <a href='https://github.com/acl2/acl2/issues/255'>Github
 Issue 255</a> for more information.</p>

 <p>To invoke provisional certification, see @(see books-certification).  For
 example, you could issue the following command.</p>

 @({
  ACL2_PCERT=t cert.pl -j 4 `find . -name '*.lisp'`
 })

 <p>Alternatively, see @(see books-certification-classic) for a discussion of
 classic ACL2 `make'-based certification (which may disappear in a future ACL2
 release); here we extend those instructions to show how to use provisional
 certification.  (Also, you may wish to look at community books file
 @('books/system/pcert/Makefile') for an example.)  We begin by describing a
 few ways to do that.  A simple way is to add the line `@('ACL2_PCERT=t')' to a
 `make' command that you use for book certification, for example as
 follows.</p>

 @({
  make -j 4 ACL2_PCERT=t
 })

 <p>The following works too, in a bash shell.</p>

 @({
  (export ACL2_PCERT=t ; time make -j 4)
 })

 <p>Alternatively, add the line</p>

 @({
  ACL2_PCERT ?= t
 })

 <p>to the @('Makefile') residing in the directory, placed above the line that
 specifies the `@('include')' of file @('Makefile-generic').  A successful
 `make' will result in creating the desired @(see certificate) (@('.cert'))
 files.</p>

 <p>Warning: If you put the line ``@('ACL2_PCERT ?= t')'' below the include of
 @('Makefile-generic'), it might have no effect.  For example, try editing
 community books file @('books/system/pcert/Makefile') by moving the line
 ``@('ACL2_PCERT ?= t')'' to the bottom of the file, and watch ``@('make
 top.cert')'' fail to invoke provisional certification.</p>

 <p>The description above may be sufficient for you to use provisional
 certification.  We provide additional documentation below for the reader who
 wants to understand more about this process, for example when not using
 `make'.  Below we assume prior familiarity with @(see books), in particular
 @(tsee certify-book) and @(tsee include-book).  The remainder of this @(see
 documentation) topic is divided into sections: Summary, Correctness Claim and
 Issues, Combining Pcertify and Convert into Pcertify+, and Further
 Information.</p>

 <p><b>Summary</b></p>

 <p>Recall that certification of a book, @('bk'), produces a @(see certificate)
 file @('bk.cert').  The provisional certification process produces this file
 as well, but as the last of the following three steps.  All of these steps are
 carried out by calls of @(tsee certify-book) using its @(':pcert') keyword
 argument.  We typically call these steps ``procedures'', to distinguish them
 from the steps of an individual call of @(tsee certify-book).</p>

 <ul>

 <li>The ``Pcertify'' procedure (sometimes called the ``Create''
 procedure) is invoked by calling @(tsee certify-book) with keyword argument
 @(':pcert :create').  It produces a file @('bk.pcert0'), sometimes called the
 ``@('.pcert0')'' file (pronounced ``dot pee cert zero'').  Proofs are skipped
 during this procedure, which can be viewed as an elaborate syntax check,
 augmented by compilation if specified (as it is by default).</li>

 <li>The ``Convert'' procedure is invoked by calling @(tsee certify-book) with
 keyword argument @(':pcert :convert').  It creates file @('bk.pcert1') from
 @('bk.pcert0'), by doing proofs for all events in @('bk.lisp').  Note that the
 third argument (the `@('compile-flg')' argument) is ignored by such a call of
 @('certify-book') unless its value is @(':all') (either explicitly or by way
 of environment variable @('ACL2_COMPILE_FLG')).  A subtlety is that if there
 is a compiled file at least as recent as the corresponding @('.pcert0') file,
 then that compiled file's write date will be updated to the current time at
 the end of this procedure.  The usual @(see local-incompatibility) check at
 the end of @(tsee certify-book) is omitted for the Convert procedure, since it
 was performed towards the end of the Create procedure.</li>

 <li>The ``Complete'' procedure is invoked by calling @(tsee certify-book)
 with keyword argument @(':pcert :complete').  It checks that every included
 book (including every one that is @(tsee local)ly included) has a @('.cert')
 file that is at least as recent as the corresponding book.  The effect is to
 move @('bk.pcert1') to @('bk.cert').  Note that all arguments of
 @('certify-book') other than the @(':pcert') argument are ignored for this
 procedure, other than for some trivial argument checking.</li>

 </ul>

 <p>You can combine the Pcertify and Convert procedures into a single
 procedure, Pcertify+, which may be useful for books that contain expensive
 @(tsee include-book) @(see events) but do few proofs.  We defer discussion of
 that feature to the section below, ``Combining Pcertify and Convert into
 Pcertify+''.</p>

 <p>The main idea of provisional certification is to break sequential
 dependencies caused by @(tsee include-book), that is, so that a book's proofs
 are carried out even when it includes books (sometimes called ``sub-books'')
 that have not themselves been fully certified.  For example, suppose that a
 proof development consists of books @('A.lisp'), @('B.lisp'), and @('C.lisp'),
 where file @('A.lisp') contains the form @('(include-book \"B\")') and file
 @('B.lisp') contains the form @('(include-book \"C\")').  Normally one would
 first certify @('C'), then @('B'), and finally, @('A').  However, the
 provisional certification process can speed up the process on a multi-core
 machine, as follows: the Pcertify (pronounced ``pee certify'') procedure
 respects this order but (one hopes) is fast since proofs are skipped; the
 Convert procedure essentially completes the certification in parallel by doing
 proofs and creating @('.pcert1') files based on @('.pcert0') files; and the
 Complete procedure respects book order when quickly renaming @('.pcert1')
 files to @('.cert') files.  In our example, the steps would be as follows, but
 note that we need not finish all Pcertify steps before starting some Convert
 steps, nor need we finish all Convert steps before starting some Complete
 steps, as explained further below.</p>

 <ul>

 <li>Pcertify books \"C\", \"B\",and then \"A\", sequentially,
 skipping proofs but doing compilation.</li>

 <li>Do proofs in parallel for the books using the Convert procedure, where
 each book relies on the existence of its own @('.pcert0') file as well as a
 @('.cert'), @('.pcert0'), or @('.pcert1') file for each of its included
 sub-books.  Write out a @('.pcert1') file for the book when the proof
 succeeds.</li>

 <li>Rename the @('.pcert1') file to a corresponding @('.cert') file when a
 @('.cert') file exists and is up-to-date for each included
 book.</li>

 </ul>

 <p>The Convert step can begin for @('bk.lisp') any time after @('bk.pcert0')
 is built.  The Complete step can begin for this book any time after
 @('bk.pcert1') and every @('sub-bk.cert') are built, for @('sub-bk') a
 sub-book of @('bk').</p>

 <p>The new procedures &mdash; Pcertify, Convert, and Complete &mdash; are
 invoked by supplying a value for the keyword argument @(':pcert') of @(tsee
 certify-book), namely @(':create'), @(':convert'), or @(':complete'),
 respectively.  Typically, and by default, the @('compile-flg') argument of
 @(tsee certify-book) is @('t') for the Pcertify procedure, so that @(see
 compilation) can take full advantage of parallelism.  This argument is treated
 as @('nil') for the other procedures except when its value is @(':all') in the
 Convert procedure, as mentioned above.</p>

 <p>For those who use @(tsee make-event), we note that expansion is done in the
 Pcertify procedure; the later steps use the expansion resulting from that
 procedure.  The reason is that although a call of @(tsee make-event) is
 similar to a macro call, a difference is that the expansion of a
 @('make-event') form can depend on the @(see state).  Therefore, we insist on
 doing such an expansion only once, so that all books involved agree on the
 expansion.  We say more about @('make-event') below.</p>

 <p><b>Correctness Claim and Issues</b></p>

 <p>The Basic Claim for certification is the same whether or not the
 provisional certification process is employed: all books should be certified
 from scratch, with no files written to the directories of the books except by
 ACL2.  Moreover, no trust tags should be used (see @(see defttag)), or else it
 is the responsibility of the user to investigate every occurrence of ``@('TTAG
 NOTE')'' that is printed to standard output.</p>

 <p>But common practice is to certify a set of books in stages: certify a few
 books, fix some books, re-certify changed books, certify some more books, and
 so on.  In practice, we expect this process to be sound even though it does
 not meet the preconditions for the Basic Claim above.  In particular, we
 expect that the use of @(see book-hash) values in @(see certificate)s will
 make it exceedingly unlikely that a book is still treated as certified after
 any events in the book or any sub-book, or any @(see portcullis) @(see
 command)s of the book or any sub-book, have been modified.</p>

 <p>Provisional certification makes it a bit easier for a determined user to
 subvert correctness.  For example, the Complete procedure only checks write
 dates to ensure that each sub-book's @('.cert') file is no older than the
 corresponding @('.lisp') file, but it does not look inside @('.cert') files of
 sub-books; in particular it does not look at their @(see book-hash)
 information.  Of course, the automatic dependency analysis provided by classic
 ACL2 `make'-based certification avoids accidental problems of this sort.  And,
 book-hash information will indeed be applied at @(tsee include-book) time, at
 least for sub-books included non-@(see local)ly.</p>

 <p>In short: while we believe that the provisional certification process can
 be trusted, we suggest that for maximum trust, it is best for all books in a
 project to be certified from scratch without the provisional certification
 process.</p>

 <p><b>Combining Pcertify and Convert into Pcertify+</b></p>

 <p>You can combine the Pcertify and Convert procedure into a single procedure,
 Pcertify+, which may be useful for books that contain expensive @(tsee
 include-book) @(see events) but do few proofs.  If you are using `make' to do
 provisional certification as described above, just set `make' variable
 @('ACL2_BOOKS_PCERT_ARG_T') to the list of books for which you want the
 Pcertify+ procedure performed instead of separate Pcertify and Convert
 procedures.  Either of two common methods may be used to set this variable, as
 illustrated below for the case that books @('sub.lisp') and @('mid.lisp') are
 the ones on which you want Pcertify+ performed.  One method is to add the
 following to your directory's Makefile, above the @('include') of
 @('Makefile-generic').</p>

 @({
  ACL2_BOOKS_PCERT_ARG_T = sub mid
 })

 <p>Alternatively, you can specify the desired books on the command line, for
 example as follows.</p>

 @({
  make -j 4 ACL2_BOOKS_PCERT_ARG_T='sub mid'
 })

 <p>Note that the books are given without their @('.lisp') extensions.</p>

 <p>At the ACL2 level, the Pcertify+ procedure is performed when the value
 @('t') is supplied to the @(':pcert') keyword argument of @(tsee
 certify-book).  Thus, @(':pcert t') can be thought of as a combination of
 @(':pcert :create') and @(':pcert :convert').  However, what ACL2 actually
 does is to perform the Pcertify step without skipping proofs, and at the end
 of the @('certify-book') run, it writes out both the @('.pcert0') and
 @('.pcert1') file, with essentially the same contents.  (We say
 ``essentially'' because the implementation writes @(':PCERT-INFO :PROVED') to
 the end of the @('.pcert0') file, but not to the @('.pcert1') file.)</p>

 <p><b>Further Information</b></p>

 <p>Some errors during provisional certification cannot be readily solved.  For
 example, if there are circular directory dependencies (for example, some book
 in directory D1 includes some book in directory D2 and vice-versa), then
 classic ACL2 `make'-based certification will quite possibly fail.  For another
 example, perhaps your directory's Makefile is awkward to convert to one with
 suitable dependencies.  When no fix is at hand, it might be best simply to
 avoid provisional certification.  If you are using classic ACL2 `make'-based
 certification, you can simply add the following line to your directory's
 @('Makefile'), or use ``@('ACL2_PCERT= ')'' on the `make' command line, to
 avoid provisional certification.</p>

 @({
  override ACL2_PCERT =
 })

 <p>We invite anyone who has troubleshooting tips to contact the ACL2
 developers with suggestions for adding such tips to this section.</p>

 <p>Our next remark is relevant only to users of @(tsee make-event), and
 concerns the interaction of that utility with state global @(tsee
 ld-skip-proofsp).  Normally, the global value of @(tsee ld-skip-proofsp) is
 unchanged during @('make-event') expansion, except that it is bound to
 @('nil') when the @('make-event') form has a non-@('nil')
 @(':check-expansion') argument.  But during the Pcertify procedure (not the
 Pcertify+ procedure), @(tsee ld-skip-proofsp) is always bound to @('nil') at
 the start of @('make-event') expansion.  To see why, consider for example the
 community book @('books/make-event/proof-by-arith.lisp').  This book
 introduces a macro, @('proof-by-arith'), that expands to a call of @(tsee
 make-event).  This @('make-event') form expands by trying to prove a given
 theorem using a succession of included arithmetic books, until the proof
 succeeds.  Now proofs are skipped during the Pcertify procedure, and if proofs
 were also skipped during @('make-event') expansion within that procedure, the
 first arithmetic book's @(tsee include-book) form would always be saved
 because the theorem's proof ``succeeded'' (as it was skipped!).  Of course,
 the theorem's proof could then easily fail during the Convert step.  If you
 really want to inhibit proofs during @('make-event') expansion in the Pcertify
 step, consider using a form such as the following: @('(state-global-let*
 ((ld-skip-proofsp nil)) ...)').</p>

 <p>Finally, we describe what it means for there to be a valid @(see
 certificate) file for including a certified book.  Normally, this is a file
 with extension @('.cert').  However, if that @('.cert') file does not exist,
 then ACL2 looks for a @('.pcert0') file instead; and if that also does not
 exist, it looks for a @('.pcert1') file.  (To see why does the @('.pcert0')
 file take priority over the @('.pcert1') file, note that the Convert procedure
 copies a @('.pcert0') file to a @('.pcert1') file, so both might exist &mdash;
 but the @('.pcert1') file might be incomplete if copying is in progress.)
 Once the candidate certificate file is thus selected, it must be valid in
 order for the book to be considered certified (see @(see certificate)).  For
 the certificate file as chosen above, then in order for a compiled file to be
 loaded, it must be at least as recent as that certificate file.</p>

 <p>Again, as discussed above, a @('.pcert0') or @('.pcert1') file may serve as
 a valid certificate file when the @('.cert') file is missing.  But when that
 happens, a warning may be printed that a ``provisionally certified'' book has
 been included.  No such warning occurs if environment variable @('ACL2_PCERT')
 has a non-empty value, or if that warning is explicitly inhibited (see @(see
 set-inhibit-warnings) and see @(see set-inhibit-output-lst)).</p>")

(defxdoc pseudo-term-listp
  :parents (term acl2-built-ins)
  :short "A predicate for recognizing lists of term-like s-expressions"
  :long "<p>See @(see pseudo-termp) for a predicate that recognizes a term-like
  s-expression.  The predicate @('pseudo-term-listp') tests whether its
  argument is a list of those.</p>

 @(def pseudo-term-listp)")

(defxdoc pseudo-termp
  :parents (term acl2-built-ins)
  :short "A predicate for recognizing term-like s-expressions"
  :long "@({
  Example Forms:
  (pseudo-termp '(car (cons x 'nil)))      ; has value t
  (pseudo-termp '(car x y z))              ; also has value t!
  (pseudo-termp '(delta (h x)))            ; has value t
  (pseudo-termp '(delta (h x) . 7))        ; has value nil (not a true-listp)
  (pseudo-termp '((lambda (x) (car x)) b)) ; has value t
  (pseudo-termp '(if x y 123))             ; has value nil (123 is not quoted)
  (pseudo-termp '(if x y '123))            ; has value t
 })

 <p>If @('x') is the quotation of a term, then @('(pseudo-termp x)') is @('t').
 However, if @('x') is not the quotation of a term it is not necessarily the
 case that @('(pseudo-termp x)') is @('nil').</p>

 <p>See @(see term) for a discussion of the various meanings of the word
 ``term'' in ACL2.  In its most strict sense, a term is either a legal variable
 symbol, a quoted constant, or the application of an @('n')-ary function symbol
 or closed @('lambda')-expression to @('n') terms.  By ``legal variable
 symbol'' we exclude constant symbols, such as @('t'), @('nil'), and
 @('*ts-rational*').  By ``quoted constants'' we include @(''t') (aka @('(quote
 t)')), @(''nil'), @(''31'), etc., and exclude constant names such as @('t'),
 @('nil') and @('*ts-rational*'), unquoted constants such as @('31') or
 @('1/2'), and ill-formed @('quote') expressions such as @('(quote 3 4)').  By
 ``closed lambda expression'' we exclude expressions, such as @('(lambda (x)
 (cons x y))'), containing free variables in their bodies.  Terms typed by the
 user are translated into strict terms for internal use in ACL2.</p>

 <p>The predicate @('termp') checks this strict sense of ``term'' with respect
 to a given ACL2 logical world; See @(see world).  Many ACL2 functions, such as
 the rewriter, require certain of their arguments to satisfy @('termp').
 However, if regarded simply from the perspective of an effective @(see guard)
 for a term-processing function, @('termp') checks many irrelevant
 things.  (Does it really matter that the variable symbols encountered never
 start and end with an asterisk?)  We have therefore introduced the notion of a
 ``pseudo-term'' and embodied it in the predicate @('pseudo-termp'), which is
 easier to check, does not require the logical @(see world) as input, and is
 often perfectly suitable as a @(see guard) on term-processing functions.</p>

 <p>A @('pseudo-termp') is either a symbol, a true list of length 2 beginning
 with the word @('quote'), the application of an @('n')-ary pseudo-@('lambda')
 expression to a true list of @('n') pseudo-terms, or the application of a
 symbol to a true list of @('n') @('pseudo-termp')s.  By an ``@('n')-ary
 pseudo-@('lambda') expression'' we mean an expression of the form @('(lambda
 (v1 ... vn) pterm)'), where the @('vi') are symbols (but not necessarily
 distinct legal variable symbols) and @('pterm') is a @('pseudo-termp').</p>

 <p>Metafunctions may use @('pseudo-termp') as a @(see guard).</p>")

(defxdoc pso
  :parents (prover-output)
  :short "Show the most recently saved output"
  :long "<p>Evaluate @(':pso') in order to print output that was generated in
 an environment where output was being saved, as in @(see gag-mode), which is
 active when ACL2 is invoked.  See @(see set-saved-output) for details.</p>

 @({
 Example Forms:

 :pso                        ; Print saved output.

 (pso)                       ; equivalent to the above
 (pso :all)                  ; equivalent to the above
 (pso :all nil)              ; equivalent to the above

 (pso \"Subgoal *1/2''\")      ; Print saved output only for \"Subgoal *1/2''\".

 (pso '\"Subgoal *1/2'5'\"
       \"Subgoal *1/2'14'\")   ; Print saved output starting with the output
                             ; for '\"Subgoal *1/2'5'\" and ending just
                             ; before the output for \"Subgoal *1/2'14'\".

 (pso '(\"Subgoal *1/2'5'\"  \"Subgoal *1/2''\")
      '(\"Subgoal *1/2'14'\" \"Subgoal *1/2'12'\")
                             ; Print saved output
                             ; starting with the output for either
                             ; \"Subgoal *1/2'5'\" or \"Subgoal *1/2''\"
                             ; (whichever comes first)
                             ; and stopping just before the output for either
                             ; \"Subgoal *1/2'14'\" or \"Subgoal *1/2'12'\"
                             ; (whichever comes first).

 General Form:

 (pso start-goals-spec ; optional: default is :ALL
      stop-goals-spec  ; optional: default is NIL
      )
 })

 <p>where both arguments are optional and have the defaults shown above.  Thus,
 the keyword command @(':pso') is equivalent to each of @('(pso)'),
 @('(pso :all)'), and @('(pso :all nil)'); see @(see keyword-commands).  The
 optional arguments restrict the output to specified goals, as follows; but the
 examples above probably provide an easier way to understand those arguments
 than the following explanation.</p>

 <ul>

 <li>@('Start-goals-spec') represents <i>the set of start goal names</i>.  Its
 effects are described below.  The value @(':all') represents the set of all
 goal names, a string represents the set consisting of just that one goal name,
 and a list represents the set of all goal names in that list.</li>

 <li>@('Stop-goals-spec') represents <i>the set of stop goal names</i>.  Its
 effects are described below, following the same conventions as above except
 that @(':all') is not allowed.</li>

 <li>Printing begins immediately if @('start-goals-spec') is @(':all'), else
 begins with the first goal whose name is in the set of start goal names.</li>

 <li>If the set of stop goal names is empty (as is the case when the second
 optional argument is omitted), then printing takes place only for the first
 goal whose name is in the set of start goal names.  Otherwise, printing
 continues starting with that goal, stopping only when a goal in the list of
 stop goal names is encountered, without any printing for that goal.</li>

 </ul>

 <p>Note that saved prover output is cleared at every top-level prover call,
 including such calls made by: @(see events) (e.g., @(tsee defthm) and @(tsee
 defun)), @(tsee thm), and @(see proof-builder) commands that invoke the
 prover.  A single event can make more than one top-level prover call, for
 example: in the case of @(tsee defun), one call made for termination and
 another for guard verification; and in the case of @(tsee defthm), one call
 made for the proposed theorem and one for each @(see corollary). If you want
 to see more than one proof log for a single top-level form, then instead of
 using @(':pso'), first evaluate @('(set-gag-mode nil)').</p>

 <p>Also see @(see pso!), @(see psog), and @(see psof).</p>")

(defxdoc pso!
  :parents (prover-output)
  :short "Show the most recently saved output, including @(see proof-tree) output"
  :long "<p>@(':Pso!') provides output just like @(':pso'), except that @(see
 proof-tree) is included; see @(tsee pso).</p>

 <p>@('Pso!') takes the same optional arguments as @('pso'); see @(see pso),
 and also see @(see psog) and @(see psof).</p>")

(defxdoc psof
  :parents (prover-output)
  :short "Show the most recently saved output"
  :long "<p>For a similar utility, see @(see pso).  But unlike @(':pso'),
 @(':psof') takes a filename argument and writes output to that file, instead
 of printing to the terminal.  For large proofs, @(':')@(tsee psof) may
 complete much more quickly than @(':')@(tsee pso).</p>

 <p>The first line of output from @(':psof') directs the Emacs editor to use
 auto-revert mode.  You can change the frequency of auto-reverting the buffer
 connected to a file by evaluating a suitable command in Emacs.  For example,
 the command @('(setq auto-revert-interval .1)') arranges for auto-revert mode
 to update as needed every 1/10 of a second.</p>

 <p>@('Psof') takes the same optional arguments as @('pso'); see @(see pso),
 and also see @(see pso!) and @(see psog).</p>")

(defxdoc psog
  :parents (prover-output)
  :short "Show the most recently saved output with @(see gag-mode)"
  :long "<p>@(':Psog') is like @(':pso') &mdash; see @(see pso) &mdash; but
 unlike @(':pso'), @(':psog') displays the output in @(see gag-mode); more
 precisely, with gag-mode equal to @('t').</p>

 <p>@('Psog') takes the same optional arguments as @('pso'); see @(see pso),
 and also see @(see pso!) and @(see psof).</p>")

(defxdoc pstack
  :parents (debugging)
  :short "Seeing what the prover is up to"
  :long "@({
  General Forms:
  (pstack)      ; inspect break
  (pstack t)    ; inspect break, printing all calls in abbreviated form
  (pstack :all) ; as above, but only abbreviating the ACL2 world
 })

 <p>When the form @('(pstack)') is executed during a break from a proof, or at
 the end of a proof that the user has aborted, a ``process stack'' (or ``prover
 stack'') will be printed that gives some idea of what the theorem prover has
 been doing.  Moreover, by evaluating @('(verbose-pstack t)') before starting a
 proof (see @(see verbose-pstack)) one can get trace-like information about
 prover functions, including time summaries, printed to the screen during a
 proof.  This feature is currently quite raw and may be refined considerably as
 time goes on, based on user suggestions.  For example, the usual control of
 printing given by @(see set-inhibit-output-lst) is irrelevant for printing the
 pstack.</p>

 <p>The use of @('(pstack t)') or @('(pstack :all)') should only be used by
 those who are comfortable looking at functions in the ACL2 source code.
 Otherwise, simply use @('(pstack)').</p>

 <p>Entries in the pstack include the following (listed here alphabetically,
 except for the first).</p>

 <p>@('preprocess-clause'), @('simplify-clause'), etc. (in
 general,@('xxx-clause')): top-level processes in the prover ``waterfall''</p>

 <p>@('clausify'): splitting a goal into subgoals</p>

 <p>@('ev-fncall'): evaluating a function on explicit arguments</p>

 <p>@('ev-fncall-meta'): evaluating a metafunction</p>

 <p>@('forward-chain'): building a context for the current goal using @(tsee
 forward-chaining) rules</p>

 <p>@('induct'): finding an induction scheme</p>

 <p>@('pop-clause'): getting the next goal to prove by induction</p>

 <p>@('process-assumptions'): creating forcing rounds</p>

 <p>@('remove-built-in-clauses'): removing built-in clauses (see @(see
 built-in-clause))</p>

 <p>@('process-equational-polys'): deducing interesting equations</p>

 <p>@('remove-trivial-equivalences'): removing trivial equalities (and
 equivalences) from the current goal</p>

 <p>@('rewrite-atm'): rewriting a top-level term in the current goal</p>

 <p>@('setup-simplify-clause-pot-lst'): building the linear arithmetic database
 for the current goal</p>

 <p>@('strip-branches'), @('subsumption-replacement-loop'): subroutines of
 @('clausify')</p>

 <p>@('waterfall'): top-level proof control</p>")

(defxdoc puff
  :parents (history)
  :short "Replace a compound @(see command) by its immediate subevents"
  :long "@({
  Example Forms:
  ACL2 !>:puff :max
  ACL2 !>:puff :x
  ACL2 !>:puff 15
  ACL2 !>:puff \"book\"

  General Form:
  :puff cd
 })

 <p>where @('cd') is a @(see command) descriptor (see @(see
 command-descriptor)) for a ``puffable'' @(see command) (see below).  @('Puff')
 replaces the @(see command) at @('cd') by the immediate subevents of the @(see
 command), executed as @(see command)s.  @('Puff') then prints, using @(tsee
 pcs), the @('puff')ed region.</p>

 <p>We consider @('puff') to be a sort of hack; it is generally robust and
 sound, but that is not guaranteed.  If any existing ACL2 event resulted from
 @('puff'), ACL2 considers proofs to have been skipped, and thus @(tsee
 certify-book) is disallowed until such events have been undone (see @(see
 ubt)).</p>

 <p>A ``puffable'' @(see command) is an @(tsee encapsulate) @(see command), an
 @(tsee include-book) command, or any command other than those consisting of a
 single primitive event.  For example, since @(tsee defun) is a primitive
 event, a @(tsee defun) command is not puffable.  But a macro form that expands
 into one or more @(see events) is puffable.  The only primitive events that
 are puffable are calls of @(tsee encapsulate) or @(tsee include-book).  In
 this sense, @(tsee make-event) is not considered primitive &mdash; that is, it
 can be puffed &mdash; and moreover, an immediate subevent that is a call of
 @('make-event') is generally replaced by its expansion (see @(see
 make-event)).  A puffable @(see command) contains (interesting) subevents,
 namely, the events in the body of the @(tsee encapsulate), in the file of the
 book included, or in the @(see command) block.</p>

 <p>The puff @(see command) ``lifts'' the immediate subevents of the indicated
 @(see command) so that they become @(see command)s themselves.  The @(see
 command) @(tsee puff*) recursively puffs the newly introduced @(see command)s.
 See @(see puff*), which also gives an example illustrating both @('puff') and
 @(tsee puff*).  @('Puff') undoes the @(see command) at @('cd') and replaces it
 by its immediate subevents.  Thus, in general the length of the @(see history)
 grows when a puff @(see command) is executed.  If @('puff') causes an error
 (see below), the logical @(see world) remains unchanged from its initial
 configuration.</p>

 <p>The intended use of @('puff') is to allow the user access to the @(see
 events) ``hidden'' inside compound @(see command)s.  For example, while trying
 to prove some theorem, @('p'), about a constrained function, @('fn'), one
 might find that the @(tsee encapsulate), @('cd'), that introduced @('fn')
 failed to include an important @(see constraint), @('q').  Without @('puff'),
 the only way to proceed is to undo back through @('cd'), create a suitable
 @(tsee encapsulate) that proves and exports @('q') as well as the old @(see
 constraint)s, re-execute the new @(tsee encapsulate), re-execute the @(see
 events) since @('cd'), and then try @('p') again.  Unfortunately, it may be
 hard to prove @('q') and additional @(see events) may have to be inserted into
 the @(tsee encapsulate) to prove it.  It may also be hard to formulate the
 ``right'' @('q'), i.e., one that is provable in the @(tsee encapsulate) and
 provides the appropriate facts for use in the proof of @('p').</p>

 <p>Using @('puff'), the user can erase the @(tsee encapsulate) at @('cd'),
 replacing it by the @(see events) in its body.  Now the formerly constrained
 function, @('fn'), is defined as its witness.  The user can experiment with
 formulations and proofs of @('q') suitable for @('p').  Of course, to get into
 the ultimately desired @(see state) &mdash; where @('fn') is constrained
 rather than defined and @('q') is exported by an @(tsee encapsulate) at
 @('cd') &mdash; the user must ultimately undo back to @('cd') and carry out
 the more tedious program described above.  But by using @('puff') it is easier
 to experiment.</p>

 <p>Similar applications of @('puff') allow the user of a book to expose the
 top-level @(see events) in the book as though they had all been typed as @(see
 command)s.  The user might then ``partially undo'' the book, keeping only some
 of the events in it.</p>

 <p>@('Puff') operates as follows.  First, it determines the list of immediate
 subevents of the @(see command) indicated by @('cd').  It causes an error if
 there is only one subevent and that subevent is identical to the @(see
 command) &mdash; i.e., if the @(see command) at @('cd') is a primitive.  Next,
 @('puff') undoes back through the indicated @(see command).  This not only
 erases the @(see command) at @('cd') but all the @(see command)s executed
 after it.  Finally, @('puff') re-executes the subevents of (the now erased)
 @('cd') followed by all the @(see command)s that were executed afterwards.</p>

 <p>Observe that the @(see command)s executed after @('cd') will generally have
 higher @(see command) numbers than they did before the puff.  For example,
 suppose 100 @(see command)s have been executed and that @(':puff 80') is then
 executed.  Suppose @(see command) 80 contains 5 immediate subevents (i.e., is
 an encapsulation of five @(see events)).  Then, after puffing, @(see command)
 80 is the first event of the puffed @(see command), @(see command) 81 is the
 second, and so on; 104 @(see command)s appear to have been executed.</p>

 <p>When puffing an @(tsee encapsulate) or @(tsee include-book), the @(tsee
 local) @(see command)s are executed.  Note that this will replace constrained
 functions by their witnesses.</p>

 <p>Here are some details and small exceptions.</p>

 <ul>

 <li>An @(tsee encapsulate) command generated by the macro @(tsee
 define-trusted-clause-processor) is not puffable.</li>

 <li>An attempt to @('puff') an @(tsee include-book) command may fail for a
 book that has been modified, as describe late in this documentation
 topic.</li>

 <li>The @('puff') of an an @(tsee include-book) command for an uncertified
 book will simply expose the contents of the book.  However, if the book is
 certified then the @('puff') will replace each event by its @(tsee make-event)
 expansion.  Moreover, any such expansion that is @(tsee local) will be
 ignored; similarly for local @('make-event') expansions in @(tsee encapsulate)
 commands.  This will result in an error if the elided event is necessary to
 support later events in the @('puff') of the command.</li>

 </ul>

 <p>Finally, we note that it is an error to @('puff') in the presence of @(tsee
 include-book) @(see events) for certified books that have been altered since
 they were included.  (Note that this restriction only applies to @(tsee
 include-book), not to @(tsee certify-book).)  To be specific, suppose
 @('\"arith\"') is a certified book that has been included in a session.
 Suppose that after @('\"arith\"') was included, the source file is modified.
 (This might happen if the user of @('\"arith\"') is not its author and the
 author happens to be working on a new version of @('\"arith\"') during the
 same time period.)  Now suppose the user tries to @('puff') the @(see command)
 that included @('\"arith\"').  The attempt to obtain the subevents in
 @('\"arith\"') will discover that the @(see book-hash) of @('\"arith\"') has
 changed and an error will be caused.  No change is made in the logical @(see
 world).  A similar error is caused if, in this same situation, the user tries
 to puff any command that occurred before the inclusion of @('\"arith\"')!
 That is, @('puff') may cause an error and leave the @(see world) unchanged
 even if the @(see command) puffed is not one involving the modified book.
 This happens because in order to reconstruct the @(see world) after the puffed
 @(see command), @('puff') must obtain the @(see events) in the book and if the
 book's source file has changed there is no assurance that the reconstructed
 @(see world) is the one the user intends.</p>

 <p>Warning: We do not detect changes to uncertified @(see books) that have
 been included and are then puffed or re-included!  The act of including an
 uncertified book leaves no trace of the @(see book-hash) value for the book.
 Furthermore, the act prints a warning message disclaiming soundness.  In light
 of this, @(':puff') quietly ``re-''executes the current contents of the
 book.</p>")

(defxdoc puff*
  :parents (history)
  :short "Replace a compound @(see command) by its subevents"
  :long "@({
  Example Forms:
  ACL2 !>:puff* :max
  ACL2 !>:puff* :x
  ACL2 !>:puff* 15
  ACL2 !>(puff* 15) ; same as just above
  ACL2 !>(puff* 15 t) ; same as just above, but keep partial results
  ACL2 !>:puff* \"book\"

  General Forms:
  :puff* cd
  (puff* 'cd) ; argument can be any expression evaluating to cd
  (puff* 'cd b) ; where b is t or nil
 })

 <p>where @('cd') is a @(see command) descriptor (see @(see
 command-descriptor)) for a ``puffable'' @(see command).  See @(see puff) for
 the definition of ``puffable'' and for a description of the basic act of
 ``puffing'' a @(see command).  In particular, see @(see puff) for a discussion
 of a sense in which @('puff'), and hence @('puff*'), should be viewed as a
 hack.  @('Puff*') is just the recursive application of @(see puff).
 @('Puff*') prints the region @(see puff)ed, using @(tsee pcs).</p>

 <p>To @(see puff) a @(see command) is to replace it by its immediate
 subevents, each of which is executed as a @(see command).  To @('puff*') a
 @(see command) is to replace the @(see command) by each of its immediate
 subevents and then to @('puff*') each of the puffable @(see command)s among
 the newly introduced ones.</p>

 <p>For example, suppose @('\"ab\"') is a book containing the following</p>

 @({
  (in-package \"ACL2\")
  (include-book \"a\")
  (include-book \"b\")
 })

 <p>Suppose that book @('\"a\"') only contained @(tsee defun)s for the
 functions @('a1') and @('a2') and that @('\"b\"') only contained @(tsee
 defun)s for @('b1') and @('b2').</p>

 <p>Now consider an ACL2 @(see state) in which only two @(see command)s have
 been executed, the first being @('(include-book \"ab\")') and the second being
 @('(include-book \"c\")').  Thus, the relevant part of the display produced by
 @(':')@(tsee pbt) 1 would be:</p>

 @({
  1 (INCLUDE-BOOK \"ab\")
  2 (INCLUDE-BOOK \"c\")
 })

 <p>Call this @(see state) the ``starting @(see state)'' in this example,
 because we will refer to it several times.</p>

 <p>Suppose @(':puff 1') is executed in the starting @(see state).  Then the
 first @(see command) is replaced by its immediate subevents and @(':pbt 1')
 would show:</p>

 @({
  1 (INCLUDE-BOOK \"a\")
  2 (INCLUDE-BOOK \"b\")
  3 (INCLUDE-BOOK \"c\")
 })

 <p>Contrast this with the execution of @(':puff* 1') in the starting @(see
 state).  @('Puff*') would first @(see puff) @('(include-book \"ab\")') to get
 the @(see state) shown above.  But then it would recursively @('puff*') the
 puffable @(see command)s introduced by the first @(see puff).  This continues
 recursively as long as any @(see puff) introduced a puffable @(see command).
 The end result of @(':puff* 1') in the starting @(see state) is</p>

 @({
  1 (DEFUN A1 ...)
  2 (DEFUN A2 ...)
  3 (DEFUN B1 ...)
  4 (DEFUN B2 ...)
  5 (INCLUDE-BOOK \"c\")
 })

 <p>Observe that when @('puff*') is done, the originally indicated @(see
 command), @('(include-book \"ab\")'), has been replaced by the corresponding
 sequence of primitive @(see events).  Observe also that puffable @(see
 command)s elsewhere in the @(see history), for example, @(see command) 2 in
 the starting @(see state), are not affected (except that their @(see command)
 numbers grow as a result of the splicing in of earlier @(see command)s).</p>

 <p>If there is an error during execution of @('puff*'), then the logical @(see
 world) is reverted to its value before that execution, unless the optional
 Boolean second argument is @('t'), in which case the result is preserved from
 the successful @(':puff') commands executed before the erroneous one.</p>")

(defxdoc push-untouchable
  :parents (defttag)
  :short "Add name or list of names to the list of untouchable symbols"
  :long "<p>Untouchables are functions or macros that cannot be called, as well
 as @(see state) global variables (see @(see programming-with-state)) that
 cannot be modified or unbound.</p>

 @({
  Examples:
  (push-untouchable my-var nil)
  (push-untouchable set-mem t)

  General Form:
  (push-untouchable name{s} fn-p)
 })

 <p>where @('name{s}') is a non-@('nil') symbol or a non-@('nil') true list of
 symbols, and @('fn-p') is any value (but generally @('nil') or @('t')).  If
 @('name{s}') is a symbol it is treated as the singleton list containing that
 symbol.  The effect of this event is to union the given symbols into the list
 of ``untouchable variables'' in the current world if @('fn-p') is @('nil'),
 else to union the symbols into the list of ``untouchable functions''.  This
 event is redundant if every symbol listed is already a member of the
 appropriate untouchables list (variables or functions).</p>

 <p>There is a further restriction on which function names may be made
 untouchable: If a function symbol, @('g'), may be introduced into a proof by a
 metatheorem (via the metafunction or the hypothesis metafunction) or by a
 clause processor and the metatheorem or clause processor has a @(':')@(tsee
 well-formedness-guarantee) then @('g') may not be made untouchable.</p>

 <p>When a symbol is on the untouchables list it is syntactically illegal for
 any event to call a function or macro of that name, if @('fn-p') is
 non-@('nil'), or to change the value of a state global variable of that name,
 if @('fn-p') is @('nil').  Thus, the effect of pushing a function symbol,
 @('name'), onto untouchables is to prevent any future event from using that
 symbol as a function or macro, or as a state global variable (according to
 @('fn-p')).  This is generally done to ``fence off'' some primitive function
 symbol from ``users'' after the developer has used the symbol freely in the
 development of some higher level mechanism.</p>

 <p>Also see @(see remove-untouchable).</p>")

(defxdoc put-assoc
  :parents (alists acl2-built-ins)
  :short "Modify an association list by associating a value with a key"
  :long "@({
  General Forms:
  (put-assoc name val alist)
  (put-assoc name val alist :test 'eql)   ; same as above (eql as equality test)
  (put-assoc name val alist :test 'eq)    ; same, but eq is equality test
  (put-assoc name val alist :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Put-assoc name val alist)') returns an alist that is the same as the
 list @('alist'), except that the first pair in @('alist') with a @(tsee car)
 of @('name') is replaced by @('(cons name val)'), if there is one.  If there
 is no such pair, then @('(cons name val)') is added at the end.  Note that the
 order of the keys occurring in @('alist') is unchanged (though a new key may
 be added).</p>

 <p>The @(see guard) for a call of @('put-assoc') depends on the test.  In all
 cases, the last argument must satisfy @(tsee alistp).  If the test is @(tsee
 eql), then either the first argument must be suitable for @(tsee eql) (see
 @(see eqlablep)) or the last argument must satisfy @(tsee eqlable-alistp).  If
 the test is @(tsee eq), then either the first argument must be a symbol or the
 last argument must satisfy @(tsee symbol-alistp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('put-assoc') and its variants:</p>

 <blockquote><p>@('(put-assoc-eq name val alist)') is equivalent to
 @('(put-assoc name val alist :test 'eq)');</p>

 <p>@('(put-assoc-equal name val alist)') is equivalent to @('(put-assoc name
 val alist :test 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('put-assoc-equal').</p>

 @(def put-assoc-equal)")

(defxdoc putprop
  :parents (world acl2-built-ins)
  :short "Update fast property lists"
  :long "@({
  General form:
  (putprop symbol key value world-alist)
 })

 <p>See @(see world) for discussion of both utilities @(tsee getprop) and
 @('putprop').  Also see community book @('books/misc/getprop.lisp') for an
 example that illustrates the use of ACL2 utilities @('getprop') and
 @('putprop') to take advantage of under-the-hood Lisp (hashed) property
 lists.</p>

 @(def putprop)")

(defxdoc |Pages Written Especially for the Tours|
  :parents (acl2-tutorial)
  :short "Pages Written Especially for the Tours"
  :long "<p>The ACL2 Home Page is generated from ACL2's online documentation
 strings.
 (How else could we achieve the total integration of ACL2's online
 documentation with the home page?)  This page is just an artifact of the
 structure of our documentation strings: each string must belong to a ``major
 section'' of the documentation database.  This page is not structured to be
 used by a person browsing via the Web.  It contains, in an arbitrary order,
 the pages written specifically for the Web user.</p>

 <p>Furthermore, browsing the pages below as text, in particular using the
 ACL2 :DOC command, is often unsatisfying because because of the lack of
 support for displaying gif files or for going ``back'' to a node just visited.
 If you wish to look at the pages below, we strongly recommend that you do so
 via a HTML-based Web browser.  Indeed, you should simply visit ACL2's Home
 Page and take one of the Tours.</p>

 <p>Generally, the topics listed above will not be of use to the ACL2
 user.</p>")

(defxdoc |Perhaps|
  :parents (|Pages Written Especially for the Tours|)
  :short "Perhaps"
  :long "<p>The theorem prover's proof is printed in real time.  At the time it
 prints ``Perhaps'' it does not know the proof will succeed.</p>")

(defxdoc |Popping out of an Inductive Proof|
  :parents (|Pages Written Especially for the Tours|)
  :short "Popping out of an Inductive Proof"
  :long "<p>Recall that our induction scheme (click <see topic='@(url
 |The Proof of the Associativity of App|)'>here</see> to revisit it) had two
 cases, the induction step (@('Subgoal *1/2')) and the base case (@('Subgoal
 *1/1')).  Both have been proved!</p>")

(defxdoc |Proving Theorems about Models|
  :parents (|Pages Written Especially for the Tours|)
  :short "Proving Theorems about Models"
  :long "<p><see topic='@(url |What is Required of the User(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>But ACL2 is a <b>logic</b>.  We can <b>prove theorems about the
 model</b>.</p>

 <p><img src='res/tours/computing-machine-xxy.gif'></img></p>

 <code>
 <b>Theorem.  MC 'mult is a multiplier</b>
 (implies (and (natp x)
               (natp y))
          (equal (lookup 'z (mc (s 'mult x y) (mclk x)))
                 (* x y))).
 </code>

 <p>This theorem says that a certain program running on the <b>mc</b> machine
 will correctly multiply <b>any two natural numbers</b>.</p>

 <p>It is a statement about an <b>infinite</b> number of test cases!</p>

 <p>We know it is true about the model because we <b>proved</b> it.</p>

 <p>Of course, models of actual machines usually only accept a finite number of
 different inputs.  For example, engineers at Advanced Micro Devices (AMD),
 Centaur, and IBM have ACL2 models of floating point units that operate on
 double precision IEEE floating point numbers.  These are finite models.  But
 the size of their inputs is sufficiently large that they are verified by the
 same mathematical methods used to prove theorems about infinite state systems
 like our little @('mc').</p>

 <p><see topic='@(url |What is Required of the User(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc q
  :parents (lp)
  :short "Quit ACL2 (type @(':q')) &mdash; reenter with @('(lp)')"
  :long "@({
  Example:
  ACL2 !>:Q
 })

 <p>The keyword command @(':q') typed at the top-level of the ACL2 loop will
 terminate the loop and return control to the Common Lisp top-level (or, more
 precisely, to whatever program invoked @(tsee lp)).  To reenter the ACL2 loop,
 execute @('(acl2::lp)') in Common Lisp.  You will be in the same state as you
 were when you exited with @(':q'), unless during your stay in Common Lisp you
 messed with the data structures representing the ACL2 @(see state) (including
 files, property lists, and single-threaded objects).</p>

 <p>Unlike all other keyword commands, typing @(':q') is not equivalent to
 invoking the function @('q').  There is no function @('q').</p>")

(defxdoc quantifier-tutorial
  :parents (defun-sk)
  :short "A Beginner's Guide to Reasoning about Quantification in ACL2"
  :long "<p>The initial version of this tutorial was written by Sandip Ray.
 Additions and revisions are welcome.  Sandip has said:</p>

 <blockquote><p>``This is a collection of notes that I wrote to remind myself
 of how to reason about quantifiers when I just started.  Most users after they
 have gotten the hang of quantifiers probably will not need this and will be
 able to use their intuitions to guide them in the process.  But since many
 ACL2 users are not used to quantification, I am hoping that this set of notes
 might help them to think clearly while reasoning about quantifiers in
 ACL2.''</p></blockquote>

 <p>Many ACL2 papers start with the sentence ``ACL2 is a quantifier-free
 first-order logic of recursive functions.''  It is true that the <i>syntax</i>
 of ACL2 is quantifier-free; every formula is assumed to be universally
 quantified over all free variables in the formula.  But the <i>logic</i> in
 fact does afford arbitrary first-order quantification.  This is obtained in
 ACL2 using a construct called @('defun-sk').  See @(see defun-sk).</p>

 <p>Many ACL2 users do not think in terms of @(see quantifiers).  The focus is
 almost always on defining recursive functions and reasoning about them using
 induction.  That is entirely justified, in fact, since proving theorems about
 recursive functions by induction plays to the strengths of the theorem prover.
 Nevertheless there are situations where it is reasonable and often useful to
 think in terms of quantifiers.  However, reasoning about quantifiers requires
 that you get into the mindset of thinking about theorems in terms of
 quantification.  This note is about how to do this effectively given ACL2's
 implementation of quantification.  This does not discuss @(tsee defun-sk) in
 detail, but merely shows some examples.  A detailed explanation of the
 implementation is in the ACL2 @(see documentation) (see @(see defun-sk)); also
 see @(see conservativity-of-defchoose).</p>

 <p>[Note: Quantifiers can be used for some pretty cool things in ACL2.
 Perhaps the most interesting example is the way of using quantifiers to
 introduce arbitrary tail-recursive equations; see the paper ``Partial
 Functions in ACL2'' by Panagiotis Manolios and J Strother Moore.  This note
 does not address applications of quantifiers, but merely how you would reason
 about them once you think you want to use them.]</p>

 <p>Assume that you have some function @('P').  I have just left @('P') as a
 unary function stub below, since I do not care about what @('P') is.</p>

 @({
  (defstub P (*) => *)
 })

 <p>Now suppose you want to specify the concept that ``there exists some @('x')
 such that @('(P x)') holds''.  ACL2 allows you to write that directly using
 quantifiers.</p>

 @({
  (defun-sk exists-P () (exists x (P x)))
 })

 <p>If you submit the above form in ACL2 you will see that the theorem prover
 specifies two functions @('exists-p') and @('exists-p-witness'), and exports
 the following constraints:</p>

 @({
  1.  (defun exists-P () (P (exists-P-witness)))
  2.  (defthm exists-P-suff (implies (p x) (exists-p)))
 })

 <p>Here @('exists-P-witness') is a new function symbol in the current ACL2
 theory.  What do the constraints above say?  Notice the constraint
 @('exists-p-suff').  It says that if you can provide any @('x') such that
 @('(P x)') holds, then you know that @('exists-p') holds.  Think of the other
 constraint (definition of @('exists-p')) as going the other way.  That is, it
 says that if @('exists-p') holds, then there is some @('x'), call it
 @('(exists-p-witness)'), for which @('P') holds.  Notice that nothing else is
 known about @('exists-p-witness') than the two constraints above.</p>

 <p>[Note: @('exists-p-witness') above is actually defined in ACL2 using a
 special form called @('defchoose').  See @(see defchoose).  This note does not
 talk about @('defchoose').  So far as this note is concerned, think of
 @('exists-p-witness') as a new function symbol that has been generated somehow
 in ACL2, about which nothing other than the two facts above is known.]</p>

 <p>Similarly, you can talk about the concept that ``for all @('x') @('(P x)')
 holds.'' This can be specified in ACL2 by the form:</p>

 @({
  (defun-sk forall-P () (forall x (P x)))
 })

 <p>This produces the following two constraints:</p>

 @({
  1.  (defun forall-P () (P (forall-p-witness)))
  2.  (defthm forall-p-necc (implies (not (P x)) (not (forall-p))))
 })

 <p>To understand these, think of @('forall-p-witness') as producing some
 @('x') which does not satisfy @('P'), if such a thing exists.  The constraint
 @('forall-p-necc') merely says that if @('forall-p') holds then @('P') is
 satisfied for every @('x').  (To see this more clearly, just think of the
 contrapositive of the formula shown.) The other constraint (definition of
 @('forall-p')) implies that if @('forall-p') does not hold then there is some
 @('x'), call it @('(forall-p-witness)'), which does not satisfy @('P').  To
 see this, just consider the following formula which is immediately derivable
 from the definition.</p>

 @({
  (implies (not (forall-p)) (not (P (forall-witness))))
 })

 <p>The description above suggests that to reason about quantifiers, the
 following Rules of Thumb, familiar to most any student of logic, are
 useful.</p>

 <blockquote><p>RT1: To prove @('(exists-p)'), construct some object @('A')
 such that @('P') holds for @('A') and then use @('exists-P-suff').</p>

 <p>RT2: If you assume @('exists-P') in your hypothesis, use the definition of
 @('exists-p') to know that @('P') holds for @('exists-p-witness').  To use
 this to prove a theorem, you must be able to derive the theorem based on the
 hypothesis that @('P') holds for something, whatever the something is.</p>

 <p>RT3: To prove @('forall-P'), prove the theorem @('(P x)') (that is, that
 @('P') holds for an arbitrary @('x')), and then simply instantiate the
 definition of @('forall-p'), that is, show that @('P') holds for the
 witness.</p>

 <p>RT4: If you assume @('forall-p') in the hypothesis of the theorem, see how
 you can prove your conclusion if indeed you were given @('(P x)') as a
 theorem.  Possibly for the conclusion to hold, you needed that @('P') holds
 for some specific set of @('x') values.  Then use the theorem
 @('forall-p-necc') by instantiating it for the specific @('x') values you care
 about.</p></blockquote>

 <p>Perhaps the above is too terse.  In the remainder of the note, we will
 consider several examples of how this is done to prove theorems in ACL2 that
 involve quantified notions.</p>

 <p>Let us consider two trivial theorems.  Assume that for some unary function
 @('r'), you have proved @('(r x)') as a theorem.  Let us see how you can prove
 that (1) there exists some x such that @('(r x)') holds, and (2) for all
 @('x') @('(r x)') holds.</p>

 <p>We first model these things using @(tsee defun-sk).  Below, @('r') is
 simply some function for which @('(r x)') is a theorem.</p>

 @({
  (encapsulate
   (((r *) => *))
   (local (defun r (x) (declare (ignore x)) t))
   (defthm r-holds (r x)))

  (defun-sk exists-r () (exists x (r x)))
  (defun-sk forall-r () (forall x (r x)))
 })

 <p>ACL2 does not have too much reasoning support for quantifiers.  So in most
 cases, one would need @(':use') hints to reason about quantifiers.  In order
 to apply @(':use') @(see hints), it is preferable to keep the function
 definitions and theorems disabled.</p>

 @({
  (in-theory (disable exists-r exists-r-suff forall-r forall-r-necc))
 })

 <p>Let us now prove that there is some @('x') such that @('(r x)') holds.
 Since we want to prove @('exists-r'), we must use @('exists-r-suff') by RT1.
 We do not need to construct any instance here since @('r') holds for all
 @('x') by the theorem above.</p>

 @({
  (defthm exists-r-holds
    (exists-r)
    :hints ((\"Goal\" :use ((:instance exists-r-suff)))))
 })

 <p>Let us now prove the theorem that for all @('x'), @('(r x)') holds.  By
 RT3, we must be able to prove it by definition of @('forall-r').</p>

 @({
  (defthm forall-r-holds
    (forall-r)
    :hints ((\"Goal\" :use ((:instance (:definition forall-r))))))
 })

 <p>[Note: Probably no ACL2 user in his or her right mind would prove the
 theorems @('exists-r-holds') and @('forall-r-holds') above.  The theorems
 shown are only for demonstration purposes.]</p>

 <p>For the remainder of this note we will assume that we have two stubbed out
 unary functions @('M') and @('N'), and we will look at proving some quantified
 properties of these functions.</p>

 @({
  (defstub M (*) => *)
  (defstub N (*) => *)
 })

 <p>Let us now define the predicates @('all-M'), @('all-N'), @('some-M'), and
 @('some-N') specifying the various quantifications.</p>

 @({
  (defun-sk all-M () (forall x (M x)))
  (defun-sk all-N () (forall x (N x)))
  (defun-sk some-M () (exists x (M x)))
  (defun-sk some-N () (exists x (N x)))

  (in-theory (disable all-M all-N all-M-necc all-N-necc))
  (in-theory (disable some-M some-N some-M-suff some-N-suff))
 })

 <p>Let us prove the classic distributive properties of quantification: the
 distributivity of universal quantification over conjunction, and the
 distributivity of existential quantification over disjunction.  We can state
 these properties informally in ``pseudo ACL2'' notation as follows:</p>

 @({
  1.  (exists x: (M x)) or (exists x: (N x)) <=> (exists x: (M x) or (N x))
  2.  (forall x: (M x)) and (forall: x (N x)) <=> (forall x: (M x) and (N x))
 })

 <p>To make these notions formal we of course need to define the formulas at
 the right-hand sides of 1 and 2.  So we define @('some-MN') and @('all-MN') to
 capture these concepts.</p>

 @({
  (defun-sk some-MN () (exists x (or (M x) (N x))))
  (defun-sk all-MN () (forall x (and (M x) (N x))))

  (in-theory (disable all-MN all-MN-necc some-MN some-MN-suff))
 })

 <p>First consider proving property 1.  The formal statement of this theorem
 would be: @('(iff (some-MN) (or (some-M) (some-N)))').</p>

 <p>How do we prove this theorem?  Looking at RT1-RT4 above, note that they
 suggest how one should reason about quantification when one has an
 ``implication''.  But here we have an ``equivalence''.  This suggests another
 rule of thumb.</p>

 <blockquote><p>RT5: Whenever possible, prove an equivalence involving
 quantifiers by proving two implications.</p></blockquote>

 <p>Let us apply RT5 to prove the theorems above.  So we will first prove:
 @('(implies (some-MN) (or (some-M) (some-N)))')</p>

 <p>How can we prove this?  This involves assuming a quantified predicate
 @('(some-MN)'), so we must use RT2 and apply the definition of @('some-MN').
 Since the conclusion involves a disjunction of two quantified predicates, by
 RT1 we must be able to construct two objects @('A') and @('B') such that
 either @('M') holds for @('A') or @('N') holds for @('B'), so that we can then
 invoke @('some-M-suff') and @('some-N-suff') to prove the conclusion.  But now
 notice that if @('some-MN') is true, then there is already an object, in fact
 @('some-MN-witness'), such that either @('M') holds for it, or @('N') holds
 for it.  And we know this is the case from the definition of @('some-MN')! So
 we will simply prove the theorem instantiating @('some-M-suff') and
 @('some-N-suff') with this witness.  The conclusion is that the following
 event will go through with ACL2.</p>

 @({
  (defthm le1
    (implies (some-MN)
             (or (some-M) (some-N)))
    :rule-classes nil
    :hints ((\"Goal\"
              :use ((:instance (:definition some-MN))
                    (:instance some-M-suff
                               (x (some-MN-witness)))
                    (:instance some-N-suff
                               (x (some-MN-witness)))))))
 })

 <p>This also suggests the following rule of thumb:</p>

 <blockquote><p>RT6: If a conjecture involves assuming an existentially
 quantified predicate in the hypothesis from which you are trying to prove an
 existentially quantified predicate, use the witness of the existential
 quantification in the hypothesis to construct the witness for the existential
 quantification in the conclusion.</p></blockquote>

 <p>Let us now try to prove the converse of le1, that is: @('(implies (or
 (some-M) (some-N)) (some-MN))')</p>

 <p>Since the hypothesis is a disjunction, we will just prove each case
 individually instead of proving the theorem by a :@('cases') hint.  So we
 prove the following two lemmas.</p>

 @({
  (defthm le2
    (implies (some-M) (some-MN))
    :rule-classes nil
    :hints ((\"Goal\"
              :use ((:instance (:definition some-M))
                    (:instance some-MN-suff
                               (x (some-M-witness)))))))

  (defthm le3
    (implies (some-N) (some-MN))
    :rule-classes nil
    :hints ((\"Goal\"
              :use ((:instance (:definition some-N))
                    (:instance some-MN-suff
                               (x (some-N-witness)))))))
 })

 <p>Note that the hints above are simply applications of RT6 as in @('le1').
 With these lemmas, of course the main theorem is trivial.</p>

 @({
  (defthmd |some disjunction|
    (iff (some-MN) (or (some-M) (some-N)))
    :hints ((\"Goal\"
              :use ((:instance le1)
                    (:instance le2)
                    (:instance le3)))))
 })

 <p>Let us now prove the distributivity of universal quantification over
 conjunction, that is, the formula: @('(iff (all-MN) (and (all-M)
 (all-N)))')</p>

 <p>Applying RT5, we will again decompose this into two implications.  So
 consider first the one-way implication: @('(implies (and (all-M) (all-N))
 (all-MN))').</p>

 <p>Here we get to assume @('all-M') and @('all-N').  Thus by RT4 we can use
 @('all-M-necc') and @('all-N-necc') to think as if we are given the formulas
 @('(M x)') and @('(N x)') as theorems.  The conclusion here is also a
 universal quantification, namely we have to prove @('all-MN').  Then RT3 tells
 us to proceed as follows.  Take any object @('y').  Try to find an
 instantiation @('z') of the hypothesis that implies @('(and (M y) (N y))').
 Then instantiate @('y') with @('all-MN-witness').  Note that the hypothesis
 lets us assume @('(M x)') and @('(N x)') to be theorems.  Thus to justify we
 need to instantiate @('x') with @('y'), and in this case, therefore, with
 @('all-MN-witness').  To make the long story short, the following event goes
 through with ACL2:</p>

 @({
  (defthm lf1
     (implies (and (all-M) (all-N))
              (all-MN))
      :rule-classes nil
      :hints ((\"Goal\"
                :use ((:instance (:definition all-MN))
                      (:instance all-M-necc (x (all-MN-witness)))
                      (:instance all-N-necc (x (all-MN-witness)))))))
 })

 <p>This suggests the following rule of thumb which is a dual of RT6:</p>

 <blockquote><p>RT7: If a conjecture assumes some universally quantified
 predicate in the hypothesis and its conclusion asserts a universally
 quantified predicate, then instantiate the ``necessary condition''
 (@('forall-mn-necc')) of the hypothesis with the witness of the conclusion to
 prove the conjecture.</p></blockquote>

 <p>Applying RT7 now we can easily prove the other theorems that we need to
 show that universal quantification distributes over conjunction.  Let us just
 go through this motion in ACL2.</p>

 @({
  (defthm lf2
    (implies (all-MN)
             (all-M))
    :rule-classes nil
    :hints ((\"Goal\"
              :use ((:instance (:definition all-M))
                    (:instance all-MN-necc
                               (x (all-M-witness)))))))

  (defthm lf3
    (implies (all-MN)
             (all-N))
    :rule-classes nil
    :hints ((\"Goal\"
              :use ((:instance (:definition all-N))
                    (:instance all-MN-necc
                               (x (all-N-witness)))))))

  (defthmd |all conjunction|
    (iff (all-MN)
         (and (all-M) (all-N)))
   :hints ((\"Goal\" :use ((:instance lf1)
                         (:instance lf2)
                         (:instance lf3)))))
 })

 <p>The rules of thumb for universal and existential quantification should make
 you realize the duality of their use.  Every reasoning method about universal
 quantification can be cast as a way of reasoning about existential
 quantification, and vice versa.  Whether you reason using universal and
 existential quantifiers depends on what is natural in a particular context.
 But just for the sake of completeness let us prove the duality of universal
 and existential quantifiers.  So what we want to prove is the following:</p>

 @({
  3.  (forall x (not (M x))) = (not (exists x (M x)))
 })

 <p>We first formalize the notion of @('(forall x (not (M x)))') as a
 quantification.</p>

 @({
  (defun-sk none-M () (forall x (not (M x))))
  (in-theory (disable none-M none-M-necc))
 })

 <p>So we now want to prove: @('(equal (none-M) (not (some-M)))').</p>

 <p>As before, we should prove this as a pair of implications.  So let us prove
 first: @('(implies (none-M) (not (some-M)))').</p>

 <p>This may seem to assert an existential quantification in the conclusion,
 but rather, it asserts the <i>negation</i> of an existential quantification.
 We are now trying to prove that something does not exist.  How do we do that?
 We can show that nothing satisfies @('M') by just showing that
 @('(some-M-witness)') does not satisfy @('M').  This suggests the following
 rule of thumb:</p>

 <blockquote><p>RT8: When you encounter the negation of an existential
 quantification think in terms of a universal quantification, and
 vice-versa.</p></blockquote>

 <p>Ok, so now applying RT8 and RT3 you should be trying to apply the
 definition of @('some-M').  The hypothesis is just a pure (non-negated)
 universal quantification so you should apply RT4.  A blind application lets us
 prove the theorem as below.</p>

 @({
  (defthm nl1
    (implies (none-M) (not (some-M)))
    :rule-classes nil
    :hints ((\"Goal\"
              :use ((:instance (:definition some-M))
                    (:instance none-M-necc (x (some-M-witness)))))))
 })

 <p>How about the converse implication?  I have deliberately written it as
 @('(implies (not (none-M)) (some-M))') instead of switching the left-hand and
 right-hand sides of @('nl1'), which would have been equivalent.  Again, RH8
 tells us how to reason about it, in this case using RH2, and we succeed.</p>

 @({
  (defthm nl2
    (implies (not (none-M)) (some-M))
    :rule-classes nil
    :hints ((\"Goal\"
              :use ((:instance (:definition none-M))
                    (:instance some-M-suff (x (none-M-witness)))))))
 })

 <p>So finally we just go through the motions of proving the equality.</p>

 @({
  (defthmd |forall not = not exists|
    (equal (none-M) (not (some-M)))
    :hints ((\"Goal\"
              :use ((:instance nl1)
                    (:instance nl2)))))
 })

 <p>Let us now see if we can prove a slightly more advanced theorem which can
 be stated informally as: If there is a natural number @('x') which satisfies
 @('M'), then there is a least natural number @('y') that satisfies @('M').</p>

 <p>[Note: Any time I have had to reason about existential quantification I
 have had to do this particular style of reasoning and state that if there is
 an object satisfying a predicate, then there is also a ``minimal'' object
 satisfying the predicate.]</p>

 <p>Let us formalize this concept.  We first define the concept of existence of
 a natural number satisfying @('x').</p>

 @({
  (defun-sk some-nat-M () (exists x (and (natp x) (M x))))
  (in-theory (disable some-nat-M some-nat-M-suff))
 })

 <p>We now talk about what it means to say that @('x') is the least number
 satisfying @('M').</p>

 @({
  (defun-sk none-below (y)
    (forall r (implies (and (natp r) (< r y)) (not (M r))))))
  (in-theory (disable none-below none-below-necc))

  (defun-sk min-M () (exists y (and (M y) (natp y) (none-below y))))
  (in-theory (disable min-M min-M-suff))
 })

 <p>The predicate @('none-below') says that no natural number less than @('y')
 satisfies @('M').  The predicate @('min-M') says that there is some natural
 number @('y') satisfying @('M') such that @('none-below') holds for
 @('y').</p>

 <p>So the formula we want to prove is: @('(implies (some-nat-M)
 (min-M))').</p>

 <p>Since the formula requires that we prove an existential quantification, RT1
 tells us to construct some object satisfying the predicate over which we are
 quantifying.  We should then be able to instantiate @('min-M-suff') with this
 object.  That predicate says that the object must be the least natural number
 that satisfies @('M').  Since such an object is uniquely computable if we know
 that there exists some natural number satisfying @('M'), let us just write a
 recursive function to compute it.  This function is @('least-M') below.</p>

 @({
  (defun least-M-aux (i bound)
    (declare (xargs :measure (nfix (- (1+ bound) i))))
    (cond ((or (not (natp i))
               (not (natp bound))
               (> i bound))
           0)
         ((M i) i)
         (t (least-M-aux (+ i 1) bound))))

  (defun least-M (bound) (least-M-aux 0 bound))
 })

 <p>Let us now reason about this function as one does typically.  So we prove
 that this object is indeed the least natural number that satisfies @('M'),
 assuming that @('bound') is a natural number that satisfies @('M').</p>

 @({
  (defthm least-aux-produces-an-M
    (implies (and (natp i)
                  (natp bound)
                  (<= i bound)
                  (M bound))
             (M (least-M-aux i bound))))

  (defthm least-<=bound
    (implies (<= 0 bound)
             (<= (least-M-aux i bound) bound)))

  (defthm least-aux-produces-least
    (implies (and (natp i)
                  (natp j)
                  (natp bound)
                  (<= i j)
                  (<= j bound)
                  (M j))
              (<= (least-M-aux i bound) j)))

  (defthm least-aux-produces-natp
    (natp (least-M-aux i bound)))

  (defthmd least-is-minimal-satisfying-m
    (implies (and (natp bound)
                  (natp i)
                   (< i (least-M bound)))
             (not (M i)))
    :hints ((\"Goal\"
              :in-theory (disable least-aux-produces-least least-<=bound)
              :use ((:instance least-<=bound
                               (i 0))
                    (:instance least-aux-produces-least
                               (i 0)
                               (j i))))))

  (defthm least-has-m
    (implies (and (natp bound)
                  (m bound))
             (M (least-M bound))))

  (defthm least-is-natp
    (natp (least-M bound)))
 })

 <p>So we have done that, and hopefully this is all that we need about
 @('least-M').  So we disable everything.</p>

 @({
  (in-theory (disable least-M natp))
 })

 <p>Now of course we note that the statement of the conjecture we are
 interested in has two quantifiers, an inner @('forall') (from @('none-below'))
 and an outer @('exists') (from @('min-M')).  Since ACL2 is not very good with
 quantification, we hold its hands to reason with the quantifier part.  So we
 will first prove something about the @('forall') and then use it to prove what
 we need about the @('exists').</p>

 <blockquote><p>RT9: When you face nested quantifiers, reason about each
 nesting separately.</p></blockquote>

 <p>So what do we want to prove about the inner quantifier?  Looking carefully
 at the definition of @('none-below') we see that it is saying that for all
 natural numbers @('r') &lt; @('y'), @('(M r)') does not hold.  Well, how would
 we want to use this fact when we want to prove our final theorem?  We expect
 that we will instantiate @('min-M-suff') with the object @('(least-M bound)')
 where we know (via the outermost existential quantifier) that @('M') holds for
 @('bound'), and we will then want to show that @('none-below') holds for
 @('(least-M bound)').  So let us prove that for any natural number (call it
 @('bound')), @('none-below') holds for @('(least-M bound)').  For the final
 theorem we only need it for natural numbers satisfying @('M'), but note that
 from the lemma @('least-is-minimal-satisfying-m') we really do not need that
 @('bound') satisfies @('M').</p>

 <p>So we are now proving: @('(implies (natp bound) (none-below (least-M
 bound)))').</p>

 <p>Well since this is a standard case of proving a universally quantified
 predicate, we just apply RT3.  We have proved that for all naturals @('i')
 &lt; @('(least-M bound)'), @('i') does not satisfy @('M') (lemma
 @('least-is-minimal-satisfying-M')), so we merely need the instantiation of
 that lemma with @('none-below-witness') of the thing we are trying to prove,
 that is, @('(least-M bound)').  The theorem below thus goes through.</p>

 @({
  (defthm least-is-minimal
    (implies (natp bound)
             (none-below (least-M bound)))
    :hints ((\"Goal\"
              :use ((:instance (:definition none-below)
                               (y (least-M bound)))
                    (:instance least-is-minimal-satisfying-m
                               (i (none-below-witness (least-M bound))))))))
 })

 <p>Finally we are in the outermost existential quantifier, and are in the
 process of applying @('min-M-suff').  What object should we instantiate it
 with?  We must instantiate it with @('(least-M bound)') where @('bound') is an
 object which must satisfy @('M') and is a natural.  We have such an object,
 namely @('(some-nat-M-witness)') which we know have all these qualities given
 the hypothesis.  So the proof now is just RT1 and RT2.</p>

 @({
  (defthm |minimal exists|
    (implies (some-nat-M) (min-M))
    :hints ((\"Goal\"
              :use ((:instance min-M-suff
                               (y (least-M (some-nat-M-witness))))
                    (:instance (:definition some-nat-M))))))
 })

 <p>If you are comfortable with the reasoning above, then you are comfortable
 with quantifiers and probably will not need these notes any more.  In my
 opinion, the best way of dealing with ACL2 is to ask yourself why you think
 something is a theorem, and the rules of thumb above are simply guides to the
 questions that you need to ask when you are dealing with quantification.</p>

 <p>Here are a couple of simple exercises for you to test if you understand the
 reasoning process.</p>

 <p><b>Exercise 1</b>.  Formalize and prove the following theorem.  Suppose
 there exists @('x') such that @('(R x)') and suppose that all @('x') satisfy
 @('(P x)').  Then prove that there exists @('x') such that @('(P x) & (R x)').
 (See <a
 href='http://www.cs.utexas.edu/users/moore/acl2/contrib/quantifier-exercise-1-solution.html'>http://www.cs.utexas.edu/users/moore/acl2/contrib/quantifier-exercise-1-solution.html</a>
 for a solution.)</p>

 <p><b>Exercise 2</b>.  Recall the example just before the preceding exercise,
 where we showed that if there exists a natural number @('x') satisfying @('M')
 then there is another natural number @('y') such that @('y') satisfies @('M')
 and for every natural number @('z') &lt; @('y'), @('z') does not.  What would
 happen if we remove the restriction of @('x'), @('y'), and @('z') being
 naturals?  Of course, we will not talk about @('<') any more, but suppose you
 use a total order on all ACL2 objects such as @(see <<).  More concretely,
 consider the definition of @('some-M') above.  Let us now define two other
 functions:</p>

 @({
  (include-book \"misc/total-order\" :dir :system)

  (defun-sk none-below-2 (y)
    (forall r (implies (<< r y) (not (M r)))))

  (defun-sk min-M2 () (exists y (and (M y) (none-below-2 y))))
 })

 <p>The question is whether @('(implies (some-M) (min-M2))') is a theorem.  Can
 you prove it?  Can you disprove it?</p>")

(defxdoc quantifiers
  :parents (defun-sk)
  :short "Issues about quantification in ACL2"
  :long "<p>ACL2 supports first-order quantifiers @(tsee exists) and @(tsee
 forall) by way of the @(tsee defun-sk) event.  However, proof support for
 quantification is quite limited.  Therefore, you may prefer using recursion in
 place of @('defun-sk') when possible (following common ACL2 practice).</p>

 <p>For example, the notion ``every member of @('x') has property @('p')'' can
 be defined either with recursion or explicit quantification, but proofs may be
 simpler when recursion is used.  We illustrate this point with two proofs of
 the same informal claim, one of which uses recursion which the other uses
 explicit quantification.  Notice that with recursion, the proof goes through
 fully automatically; but this is far from true with explicit quantification
 (especially notable is the ugly hint).</p>

 <p>The informal claim for our examples is: If every member @('a') of each of
 two lists satisfies the predicate @('(p a)'), then this holds of their @(tsee
 append); and, conversely.</p>

 <p>See @(see quantifiers-using-recursion) for a solution to this example using
 recursion.</p>

 <p>See @(see quantifiers-using-defun-sk) for a solution to this example using
 @(tsee defun-sk).  Also See @(see quantifiers-using-defun-sk-extended) for an
 elaboration on that solution.</p>

 <p>But perhaps first, see @(see defun-sk) for an ACL2 utility to introduce
 first-order quantification in a direct way.  Examples of the use of
 @('defun-sk') are also available: see @(see defun-sk-example) and see @(see
 Tutorial4-Defun-Sk-Example) for basic examples, and see @(see
 quantifier-tutorial) for a more complete, careful beginner's introduction that
 takes you through typical kinds of quantifier-based reasoning in ACL2.</p>")

(defxdoc quantifiers-using-defun-sk
  :parents (quantifiers)
  :short "Quantification example"
  :long "<p>See @(see quantifiers) for the context of this example.  It should
 be compared to a corresponding example in which a simpler proof is attained by
 using recursion in place of explicit quantification; see @(see
 quantifiers-using-recursion).</p>

 @({
  (in-package \"ACL2\")

  ; We prove that if every member A of each of two lists satisfies the
  ; predicate (P A), then this holds of their append; and, conversely.

  ; Here is a solution using explicit quantification.

  (defstub p (x) t)

  (defun-sk forall-p (x)
    (forall a (implies (member a x)
                       (p a))))

  (defthm member-append
    (iff (member a (append x1 x2))
         (or (member a x1) (member a x2))))

  (defthm forall-p-append
    (equal (forall-p (append x1 x2))
           (and (forall-p x1) (forall-p x2)))
    :hints ((\"Goal\" ; ``should'' disable forall-p-necc, but no need
             :use
             ((:instance forall-p-necc
                         (x (append x1 x2))
                         (a (forall-p-witness x1)))
              (:instance forall-p-necc
                         (x (append x1 x2))
                         (a (forall-p-witness x2)))
              (:instance forall-p-necc
                         (x x1)
                         (a (forall-p-witness (append x1 x2))))
              (:instance forall-p-necc
                         (x x2)
                         (a (forall-p-witness (append x1 x2))))))))
 })

 <p>Also see @(see quantifiers-using-defun-sk-extended) for an elaboration on
 this example.</p>")

(defxdoc quantifiers-using-defun-sk-extended
  :parents (quantifiers)
  :short "Quantification example with details"
  :long "<p>See @(see quantifiers-using-defun-sk) for the context of this
 example.</p>

 @({
  (in-package \"ACL2\")

  ; We prove that if every member A of each of two lists satisfies the
  ; predicate (P A), then this holds of their append; and, conversely.

  ; Here is a solution using explicit quantification.

  (defstub p (x) t)

  (defun-sk forall-p (x)
    (forall a (implies (member a x)
                       (p a))))

  ; The defun-sk above introduces the following axioms.  The idea is that
  ; (FORALL-P-WITNESS X) picks a counterexample to (forall-p x) if there is one.

  ;   (DEFUN FORALL-P (X)
  ;     (LET ((A (FORALL-P-WITNESS X)))
  ;          (IMPLIES (MEMBER A X) (P A))))
  ;
  ;   (DEFTHM FORALL-P-NECC
  ;     (IMPLIES (NOT (IMPLIES (MEMBER A X) (P A)))
  ;              (NOT (FORALL-P X)))
  ;     :HINTS ((\"Goal\" :USE FORALL-P-WITNESS)))

  ; The following lemma seems critical.

  (defthm member-append
    (iff (member a (append x1 x2))
         (or (member a x1) (member a x2))))

  ; The proof of forall-p-append seems to go out to lunch, so we break into
  ; directions as shown below.

  (defthm forall-p-append-forward
    (implies (forall-p (append x1 x2))
             (and (forall-p x1) (forall-p x2)))
    :hints ((\"Goal\" ; ``should'' disable forall-p-necc, but no need
             :use
             ((:instance forall-p-necc
                         (x (append x1 x2))
                         (a (forall-p-witness x1)))
              (:instance forall-p-necc
                         (x (append x1 x2))
                         (a (forall-p-witness x2)))))))

  (defthm forall-p-append-reverse
    (implies (and (forall-p x1) (forall-p x2))
             (forall-p (append x1 x2)))
    :hints ((\"Goal\"
             :use
             ((:instance forall-p-necc
                         (x x1)
                         (a (forall-p-witness (append x1 x2))))
              (:instance forall-p-necc
                         (x x2)
                         (a (forall-p-witness (append x1 x2))))))))

  (defthm forall-p-append
    (equal (forall-p (append x1 x2))
           (and (forall-p x1) (forall-p x2)))
    :hints ((\"Goal\" :use (forall-p-append-forward
                          forall-p-append-reverse))))
 })")

(defxdoc quantifiers-using-recursion
  :parents (quantifiers)
  :short "Recursion for implementing quantification"
  :long "<p>The following example illustrates the use of recursion as a means
 of avoiding proof difficulties that can arise from the use of explicit
 quantification (via @(tsee defun-sk)).  See @(see quantifiers) for more about
 the context of this example.</p>

 @({
  (in-package \"ACL2\")

  ; We prove that if every member A of each of two lists satisfies the
  ; predicate (P A), then this holds of their append; and, conversely.

  ; Here is a solution using recursively-defined functions.

  (defstub p (x) t)

  (defun all-p (x)
    (if (atom x)
        t
      (and (p (car x))
           (all-p (cdr x)))))

  (defthm all-p-append
    (equal (all-p (append x1 x2))
           (and (all-p x1) (all-p x2))))
 })")

(defxdoc quick-and-dirty-subsumption-replacement-step
  :parents (debugging)
  :short "(advanced topic) controlling a heuristic in the prover's clausifier"
  :long "<p>This topic is probably only of interest to those who are
 undertaking particularly complex proof developments.</p>

 <p>The ACL2 prover's handling of propositional logic uses a heuristic that we
 believe might cause the prover to slow down significantly or even to trigger a
 stack overflow.  However, we believe these negative effects are only felt on
 very large formulas &mdash; formulas that are likely to cause similar
 degradation of many other parts of ACL2.</p>

 <p>The following two events turn off that heuristic (by eliminating calls to
 source function @('quick-and-dirty-subsumption-replacement-step'), after which
 this @(see documentation) topic is named).</p>

 @({
  (defun quick-and-dirty-srs-off (cl1 ac)
    (declare (ignore cl1 ac)
             (xargs :mode :logic :guard t))
    nil)

  (defattach quick-and-dirty-srs quick-and-dirty-srs-off)
 })

 <p>However, if you feel the need to try this out, please remember that the
 proof is likely to fail anyway since other parts of ACL2 will probably be
 stressed.  A more basic problem with your proof strategy may exist: the
 formulas are getting extraordinarily large.  A common approach for avoiding
 such problem include disabling functions (see @(see in-theory)).  Other less
 common approaches might help if you are sufficiently desperate, such as
 defining your own @('IF') function to use in place of the built-in
 @('IF').</p>

 <p>If you do find an example for which the above two events provide
 significant benefit, we (the ACL2 implementors) would be interested in hearing
 about it.</p>

 <p>To turn the heuristic back on:</p>

 @({
  (defattach quick-and-dirty-srs quick-and-dirty-srs-builtin)
 })")

(defxdoc quit
  :parents (good-bye)
  :short "Quit entirely out of Lisp"
  :long "<p>Same as @(tsee good-bye).</p>")

(defxdoc quote
  :parents (basics acl2-built-ins)
  :short "Create a constant"
  :long "<p>The form @('(quote x)') evaluates to @('x').  See any Common Lisp
 documentation.  Also see @(see unquote).</p>")

(defxdoc r-eqlable-alistp
  :parents (alists acl2-built-ins)
  :short "Recognizer for a true list of pairs whose @(tsee cdr)s are suitable for @(tsee eql)"
  :long "<p>The predicate @('r-eqlable-alistp') tests whether its argument is a
 @(tsee true-listp) of @(tsee consp) objects whose @(tsee cdr)s all satisfy
 @(tsee eqlablep).</p>

 @(def r-eqlable-alistp)")

(defxdoc r-symbol-alistp
  :parents (alists acl2-built-ins)
  :short "Recognizer for association lists with symbols as values"
  :long "<p>@('(R-symbol-alistp x)') is true if and only if @('x') is a list of
 pairs of the form @('(cons key val)') where @('val') is a @(tsee symbolp).</p>

 @(def r-symbol-alistp)")

(defxdoc random$
  :parents (state numbers acl2-built-ins)
  :short "Obtain a random value"
  :long "@({
  Example:
  (random$ 10 state) ==> (mv 7 <state>)
 })

 <p>@('(Random$ limit state)'), where @('limit') is a positive integer, returns
 a random non-negative integer together with a new @(tsee state).  Logically,
 it simply returns the first element of a list that is a field of the ACL2
 @(tsee state), called the @('acl2-oracle') (see @(tsee read-acl2-oracle)),
 together with the new state resulting from removing that element from that
 list.  (Except, if that element is not in range as specified above, then 0 is
 returned.)  However, @('random$') actually invokes a Common Lisp function to
 choose the integer returned.  Quoting from the Common Lisp HyperSpec(TM), <a
 href='http://www.lispworks.com/documentation/HyperSpec/Front'>http://www.lispworks.com/documentation/HyperSpec/Front</a>:
 ``An approximately uniform choice distribution is used...  each of the
 possible results occurs with (approximate) probability 1/limit.''</p>

 <p>Consider enabling rules @('natp-random$') and @('random$-linear') if you
 want to reason about @('random$').</p>

 @(def random$)")

(defxdoc rassoc
  :parents (alists acl2-built-ins)
  :short "Look up value in association list"
  :long "@({
  General Forms:
  (rassoc x alist)
  (rassoc x alist :test 'eql)   ; same as above (eql as equality test)
  (rassoc x alist :test 'eq)    ; same, but eq is equality test
  (rassoc x alist :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Rassoc x alist)') is the first member of @('alist') whose @(tsee cdr)
 is @('x'), or @('nil') if no such member exists.  @('(rassoc x alist)') is
 thus similar to @('(assoc x alist)'), the difference being that it looks for
 the first pair in the given alist whose @(tsee cdr), rather than @(tsee car),
 is @(tsee eql) to @('x').  See @(see assoc).  The optional keyword,
 @(':TEST'), has no effect logically, but provides the test (default @(tsee
 eql)) used for comparing @('x') with the @(tsee cdr)s of successive elements
 of @('lst').</p>

 <p>The @(see guard) for a call of @('rassoc') depends on the test.  In all
 cases, the second argument must satisfy @(tsee alistp).  If the test is @(tsee
 eql), then either the first argument must be suitable for @(tsee eql) (see
 @(see eqlablep)) or the second argument must satisfy @(tsee r-eqlable-alistp).
 If the test is @(tsee eq), then either the first argument must be a symbol or
 the second argument must satisfy @(tsee r-symbol-alistp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('rassoc') and its variants:</p>

 <blockquote><p>@('(rassoc-eq x lst)') is equivalent to @('(rassoc x lst :test
 'eq)');</p>

 <p>@('(rassoc-equal x lst)') is equivalent to @('(rassoc x lst :test
 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('rassoc-equal').</p>

 @(def rassoc-equal)

 <p>@('Rassoc') is defined by Common Lisp.  See any Common Lisp documentation
 for more information.</p>")

(defxdoc rational-listp
  :parents (numbers lists acl2-built-ins)
  :short "Recognizer for a true list of rational numbers"
  :long "<p>The predicate @('rational-listp') tests whether its argument is a
 true list of rational numbers.</p>

 @(def rational-listp)")

(defxdoc rationalp
  :parents (numbers acl2-built-ins)
  :short "Recognizer for rational numbers (ratios and integers)"
  :long "<p>@('(rationalp x)') is true if and only if @('x') is an rational
 number.</p>")

(defxdoc raw-lisp-error
  :parents (common-lisp)
  :short "Raw lisp errors"
  :long "<p>You may see a message about ``ABORTING from raw Lisp'' as in the
 following example.</p>

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

 Summary
 Form:  ( DEFUN FOO ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  FOO
 ACL2 !>(foo 3)

 ***********************************************
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  Fault during read of memory address #x1D
 ***********************************************

 The message above might explain the error.  If not, and
 if you didn't cause an explicit interrupt (Control-C),
 then the root cause may be call of a :program mode
 function that has the wrong guard specified, or even no
 guard specified (i.e., an implicit guard of t).
 See :DOC guards.

 To enable breaks into the debugger (also see :DOC acl2-customization):
 (SET-DEBUGGER-ENABLE T)
 ACL2 !>
 })

 <p>The ``Error:'' message, ``Fault during read of memory address #x1D'', is
 printed by the host Common Lisp implementation.  In the example above, the
 function @('foo') has an implicit @(see guard) of @('t'), which causes
 evaluation to invoke the Common Lisp function @('car') on argument @('3'),
 resulting in the error.  This sort of error may occur when calling a
 @(':')@(tsee program) mode function, because the guard hasn't been verified.
 See @(see defun-mode-caveat) for a discussion of the possibility that ACL2 is
 rendered unsound by a raw Lisp error.  For further relevant background, see
 @(see evaluation).</p>

 <p>Calls of @(':program') mode functions are not the only sources of raw Lisp
 errors.  Here is a non-exhaustive list of some such sources.</p>

 <ul>

 <li>Calls of @(':program') mode functions</li>

 <li>Calls of @(':logic') mode functions whose @(see guard)s were verified
 using @(tsee skip-proofs)</li>

 <li>Illegal calls of certain functions and macros with special ``under the
 hood'' raw Lisp code, such as @(tsee read-file-into-string) and @(tsee
 return-last)</li>

 <li>@(tsee Defattach) using argument @(':skip-checks t')</li>

 <li>Reader errors (for examples see @(see reader) and see @(see
 set-iprint))</li>

 </ul>")

(defxdoc read-acl2-oracle
  :parents (programming-with-state acl2-built-ins)
  :short "Pop the oracle field of the state"
  :long "<p>ACL2 has a mutable `state' that contains a number of fields; see
 @(see state).  One of these fields is a list, called the @('acl2-oracle')
 field.  There are no constraints on the elements of this list; thus, you will
 not be able to prove anything about those elements.  However, as a
 convenience, ACL2 permits you to evaluate the form <tt>(read-acl2-oracle
 state)</tt>, which returns the multiple value @('(mv nil nil state)').</p>

 <p>The ACL2 implementation uses @('read-acl2-oracle'), but you will likely
 find this function to be useless unless you do advanced, scurrilous things
 using trust tags (see @(tsee defttag)).</p>

 <p>The following definition is the logical definition of
 @('read-acl2-oracle'), but as explained above does not really characterize its
 behavior under the hood.</p>

 @(def read-acl2-oracle)")

(defxdoc read-file-into-string
  :parents (io)
  :short "The contents of a file (or part of it) as a string"
  :long "<p>When this macro is passed a valid filename (and the ACL2 @(see
 state)), it generally returns the contents of the file (or a specified part of
 the file) as a string.  Otherwise, it returns @('nil') or causes an error.</p>

 @({
 Example Forms:

 (read-file-into-string \"foo.lisp\")
 (read-file-into-string \"foo.lisp\" :start 0 :bytes nil) ; same as above
 (read-file-into-string \"foo.lisp\" :start 20000 :bytes 10000)

 General Form:

 (read-file-into-string filename :start s :bytes b)
 })

 <p>where @('filename') is a string, which is typically the name of a file; and
 where @(':start s') and @(':bytes b') are optional, where @('s') has default
 @('0') and @('b') has default @('nil'), @('s') is a natural number, and @('b')
 is either a natural number or @('nil').</p>

 <p>For examples, see @(see community-books) file
 @('books/system/tests/read-file-into-string.lisp').</p>

 <p>The result, when not @('nil') or an error, is a string representing the
 specified file contents.  For the default of @(':start 0') and @(':bytes
 nil'), or equivalently, when no keyword arguments are specified, then the
 entire file contents are returned as a string.  In general, @(':start s')
 specifies the part of the file starting at the @('s')-th byte, and @(':bytes
 b') specifies that only the first @('b') bytes are to be read starting at that
 position, stopping at end of file in what we call the ``truncation case'':
 where @('b+s') exceeds the length of the file.</p>

 <p>If @(':start s') is specified where @('s > 0'), then the next read must
 start where the previous read left off.  More precisely: in this case ACL2
 expects that there was an earlier call of read-file-into-string on the same
 file, where the most recent such call must not have been the ``truncation
 case'' (see above) and must have have specified @(':bytes') such that the
 first unread byte position is @('s').  Otherwise, an error occurs.  Note that
 if @('s') is @('0') then there is no such restriction; the read is viewed as a
 new ``first'' read of the file.</p>

 <p>WARNING: A Lisp stream is created for the specified file, and is left open
 until a call of @('read-file-into-string') is either made with @(':bytes')
 having value @('nil') (the default) or is in the ``truncation case'' described
 above.  Operating systems can complain when too many streams are open at the
 same time.  In particular, consider the case that @(':start s') and @(':bytes
 b') are specified where @('s > 0'), and where @('s+b') is exactly the length
 of the file.  Thus we are barely not in the ``truncation case'' described
 above, so one more read will be necessary in order to close that stream.  Your
 code might thus include code such as the following (for example) after a call
 of @('read-file-into-string') with non-@('nil') @(':bytes'):</p>

 @({
 (prog2$
  (and (= (+ position bytes) file-length)

 ; Then close the stream:

       (read-file-into-string
        filename
        :start file-length
        :bytes 1))
  <more_code>)
 })

 <p>End of warning.</p>

 <p>This macro provides functionality that can be obtained through the usual
 @(see IO) routines provided by ACL2, as shown by the sequence of definitions
 below.  However, under-the-hood raw Lisp code provides an implementation that
 not only is efficient, but also does not return @(tsee state), although the
 expansion of a call of this macro takes @('state') as an argument.  (Technical
 remark: the use of @(tsee with-local-state) in the logical definition of key
 subroutine @('read-file-into-string2') does not require a trust tag (see @(see
 defttag)), because that function is defined by ACL2, not in a book.)</p>

 <p>The value of the constant @('*read-file-into-string-bound*')
 (see the definition below) is a strict upper bound on the size of the string
 returned.  If the file (or portion thereof) contains more bytes than this,
 then @('nil') is returned.</p>

 <p>There are two checks to guarantee that @('read-file-into-string') is truly
 a function &mdash; that is, it returns the same value for two calls with the
 same inputs.  One check ensures that the write date of the file has not
 changed between two such calls; otherwise ACL2 will cause a raw Lisp error of
 the following form.</p>

 @({
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  Illegal consecutive reads from file \"MY-FILE\".
 See :DOC read-file-into-string.
 ***********************************************
 })

 <p>The other check ensures that the write date of the file has not changed
 while the second call is in progress.  For simplicity, ACL2 actually makes
 this check even for the first call.  When the check fails the corresponding
 raw Lisp error is of the following form.</p>

 @({
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  Illegal attempt to call READ-FILE-INTO-STRING concurrently with some write to that file!
 See :DOC read-file-into-string.
 ***********************************************
 })

 <p>The first of these errors can actually occur when the second read is
 performed by @(tsee open-input-channel) of type @(':character').  But we
 expect all such errors to be rare, since they only occur when there are two
 reads to the same file with an intervening external write, in the case that
 the two ACL2 states have the same @('file-clock') field (see @(see state)).
 That field is updated any time a channel is opened or closed.</p>

 <p>We close by showing the relevant ACL2 definitions in the logic, that is,
 not including the special raw Lisp (under the hood) code in the definition of
 @('read-file-into-string2').</p>

 @(def read-file-into-string1)

 @(def *read-file-into-string-bound*)

 @(def read-file-into-string2)

 @(def read-file-into-string)")

(defxdoc read-run-time
  :parents (programming-with-state acl2-built-ins)
  :short "Read elapsed runtime"
  :long "<p>By default, @('(read-run-time state)') returns @('(mv runtime
 state)'), where runtime is the elapsed runtime in seconds since the start of
 the current ACL2 session and @('state') is the resulting ACL2 @(see state).
 But @('read-run-time') can be made to return elapsed realtime (wall clock
 time) instead; see @(see get-internal-time).  In both cases, the precision
 depends on the host Common Lisp; for example, in CCL as of this writing, the
 result is accurate to the microsecond.</p>

 <p>The logical definition probably won't concern many users, but for
 completeness, we say a word about it here.  That definition uses the function
 @(tsee read-acl2-oracle), which modifies state by popping the value to return
 from its acl2-oracle field.</p>

 @(def read-run-time)")

(defxdoc reader
  :parents (miscellaneous)
  :short "Reading expressions in the ACL2 read-eval-print loop"
  :long "<p>The ACL2 read-eval-print loop reads expressions much like they are
 read in any Common Lisp read-eval-print loop.  For example, you may use the
 single tick symbol (<tt>'</tt>) for @('quote') and also the backquote symbol
 (<tt>`</tt>) with its escapes, comma (<tt>,</tt>) and
 comma-atsign (<tt>,@</tt>).  See any Common Lisp reference or tutorial.</p>

 <p>ACL2-specific reader macros include its reading of expressions in a
 specified package (using @('#!') &mdash; see @(see sharp-bang-reader)), its
 restriction of read-time evaluation to constants introduced by @(tsee
 defconst) (using @('#.') &mdash; see @(see sharp-dot-reader)), and the ability
 to put underscores in numeric constants (using @('#u') &mdash; see @(see
 sharp-u-reader)).</p>

 <p>See @(see set-iprint) for how to make ACL2 print expressions like
 @('#@2#') that can be read back in.</p>

 <p>Strictly speaking, there is nothing special about how the reader handles
 @(see keyword)s in the input.  But see @(see keyword-commands) for how ACL2
 may interpret a top-level keyword command.</p>

 <p>We conclude this topic with a log that illustrates features discussed
 above.  Comments of the form <tt>{{..}}</tt> have been inserted manually.</p>

 @({
 ACL2 !>(defconst *c* (+ 3 4))

 Summary
 Form:  ( DEFCONST *C* ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  *C*
 ACL2 !>'(a #.*c* 17)
 ;{{See :doc sharp-dot-reader.
 ;  Notice that #.*c* is read as the value of *c*, thus,
 ;  as 7 rather than as (+ 3 4).}}
 (A 7 17)
 ACL2 !>'(a #.(+ 5 6) 17)
 ;{{But this is not legal in ACL2, as #. must be followed by
 ;  a known constant symbol.}}

 ***********************************************
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  ACL2 supports #. syntax only for #.*a*, where *a* has been
 defined by DEFCONST.  Thus the form #.(+ 5 6) is illegal.
 ***********************************************

 ;{{Additional output here has been omitted in this log.}}
 ACL2 !>(defpkg \"FOO\" nil)

 Summary
 Form:  ( DEFPKG \"FOO\" ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  \"FOO\"
 ACL2 !>#!foo'(a b c)
 ;{{See :doc sharp-bang-reader.  The prefix \"#!foo\" causes
 ;  the s-expression after it to be read into the \"FOO\" package.}}
 (FOO::A FOO::B FOO::C)
 ACL2 !>#x100a
 ;{{As in Common Lisp, \"#x\" causes the digits after it to be read in hex.}}
 4106
 ACL2 !>#ux10_0a
 ;{{The \"#u\" prefix allows underscores in the numeral after it.  Those
 ;  underscores are ignored, but can improve readability.}}
 4106
 ACL2 !>(set-iprint t)
 ;{{See :DOC set-print.  This causes \"#@1#\" below to be printed.}}

 ACL2 Observation in SET-IPRINT:  Iprinting has been enabled.
 ACL2 !>(set-evisc-tuple (evisc-tuple 3   ; print-level
                                      4   ; print-length
                                      nil ; alist
                                      nil ; hiding-cars
                                      )
                         :sites :ld)
 ;{{Abbreviate the printing of top-level evaluation results.
 ;  See :doc set-evisc-tuple.}}
  (:LD)
 ACL2 !>(make-list 10)
 (NIL NIL NIL NIL . #@1#)
 ACL2 !>'#@1#
 ;{{Note that the reader replaces #@1# with the value that was stored there.}}
 (NIL NIL NIL NIL . #@2#)
 ACL2 !>(without-evisc '(NIL NIL NIL NIL . #@1#))
 ;{{See :doc without-evisc.}}
 (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
 ACL2 !>(set-evisc-tuple nil :sites :ld)
  (:LD)
 ACL2 !>(let ((x '(3 4)))
          `(a b ,x c))
 ;{{As in Common Lisp, backquote can be escaped by comma.}}
 (A B (3 4) C)
 ACL2 !>(let ((x '(3 4)))
          `(a b ,@x c))
 ;{{As in Common Lisp, backquote can be escaped by comma-atsign, which
 ;  splices its value into the list.}}
 (A B 3 4 C)
 ACL2 !>

 })")

(defxdoc real
  :parents (acl2)
  :short "ACL2(r) support for real numbers"
  :long "<p>ACL2 supports rational numbers but not real numbers.  However,
 starting with Version 2.5, a variant of ACL2 called ``ACL2(r)'' supports the
 real numbers by way of non-standard analysis.  ACL2(r) was conceived and first
 implemented by Ruben Gamboa in his Ph.D.  dissertation work, supervised by Bob
 Boyer with active participation by Matt Kaufmann.</p>

 <p>ACL2(r) has the same source files as ACL2.  After you download ACL2, you
 can build ACL2(r) by executing the following command on the command line in
 your acl2-sources directory, replacing @('<your_lisp>') with a path to your
 Lisp executable:</p>

 @({
  make large-acl2r LISP=<your_lisp>
 })

 <p>This will create an executable in your acl2-sources directory named
 @('saved_acl2r').</p>

 <p>Note that if you download @(see community-books) as tarfiles, then you will
 automatically be obtaining the books to be certified with ACL2(r).  They can
 be certified from your acl2-sources directory, shown here as @('<DIR>'):</p>

 @({
  make regression ACL2=<DIR>/saved_acl2r
 })

 <p>To check that you are running ACL2(r), see if the prompt includes the
 string ``@('(r)')'', e.g.:</p>

 @({
  ACL2(r) !>
 })

 <p>Or, look at @('(@ acl2-version)') and see if ``@('(r)')'' is a
 substring.</p>

 <p>In ACL2 (as opposed to ACL2(r)), when we say ``real'' we mean
 ``rational.''</p>

 <p>Caution: ACL2(r) should be considered experimental: although we (Kaufmann
 and Moore) have carefully completed Gamboa's integration of the reals into the
 ACL2 source code, our primary concern has been to ensure unchanged behavior
 when ACL2 is compiled in the default manner, i.e., without the non-standard
 extensions.  As for every release of ACL2, at the time of a release we are
 unaware of soundness bugs in ACL2 or ACL2(r).</p>

 <p>There is only limited documentation on the non-standard features of
 ACL2(r).  We hope to provide more documentation for such features in future
 releases.  Please feel free to query the authors if you are interested in
 learning more about ACL2(r).  Gamboa's dissertation may also be helpful.</p>")

(defxdoc real-listp

; Warning: Do not try to add @(def real-listp), since it's defined only in
; ACL2(r), not ACL2, and we expect the manual always to be built with ACL2, not
; ACL2(r).

  :parents (real lists acl2-built-ins)
  :short "ACL2(r) recognizer for a true list of real numbers"
  :long "<p>The predicate @('real-listp') tests whether its argument is a true
 list of real numbers.  This predicate is only defined in ACL2(r)
 (see @(see real)).</p>")

(defxdoc real/rationalp
  :parents (numbers acl2-built-ins)
  :short "Recognizer for rational numbers (including real number in ACL2(r))"
  :long "<p>For most ACL2 users, this is a macro abbreviating @(tsee
 rationalp).  In ACL2(r) (see @(see real)), this macro abbreviates the
 predicate @('realp'), which holds for real numbers as well (including
 rationals).  Most ACL2 users can ignore this macro and use @(tsee rationalp)
 instead, but many community books use @('real/rationalp') so that these books
 will be suitable for ACL2(r) as well.</p>")

(defxdoc realfix
  :parents (numbers acl2-built-ins)
  :short "Coerce to a real number"
  :long "<p>@('Realfix') simply returns any real number argument unchanged,
 returning @('0') on a non-real argument.  Also see @(see nfix), see @(see
 ifix), see @(see rfix), and see @(see fix) for analogous functions that coerce
 to a natural number, an integer, a rational, and a number, respectively.</p>

 <p>@('Realfix') has a @(see guard) of @('t').</p>

 @(def realfix)")

(defxdoc realpart
  :parents (numbers acl2-built-ins)
  :short "Real part of a complex number"
  :long "<p>Completion Axiom (@('completion-of-realpart')):</p>

 @({
  (equal (realpart x)
         (if (acl2-numberp x)
             (realpart x)
           0))
 })

 <p>@(see Guard) for @('(realpart x)'):</p>

 @({
  (acl2-numberp x)
 })")

(defxdoc rebuild
  :parents (ld)
  :short "A convenient way to reconstruct your old @(see state)"
  :long "@({
  Examples:
  ACL2 !>(rebuild \"project.lisp\")
  ACL2 !>(rebuild \"project.lisp\" t)
  ACL2 !>(rebuild \"project.lisp\" t :dir :system)
  ACL2 !>(rebuild \"project.lisp\" :all)
  ACL2 !>(rebuild \"project.lisp\" :query)
  ACL2 !>(rebuild \"project.lisp\" 'lemma-22)
 })

 <p>@('Rebuild') allows you to assume all the @(see command)s in a given file
 or list, supplied in the first argument.  Because @('rebuild') processes an
 arbitrary sequence of @(see command)s with @(tsee ld-skip-proofsp) @('t'), it
 is unsound!  However, if each of these @(see command)s is in fact admissible,
 then processing them with @('rebuild') will construct the same logical @(see
 state) that you would be in if you typed each @(see command) and waited
 through the proofs again.  Thus, @('rebuild') is a way to reconstruct a @(see
 state) previously obtained by proving your way through the @(see
 command)s.</p>

 <p>The second, optional argument to @('rebuild') is a ``filter'' (see @(see
 ld-pre-eval-filter)) that lets you specify which @(see command)s to process.
 You may specify @('t'), @(':all'), @(':query'), or a new logical name.  @('t')
 and @(':all') both mean that you expect the entire file or list to be
 processed.  @(':query') means that you will be asked about each @(see command)
 in turn.  A new name means that all @(see command)s will be processed as long
 as the name is new, i.e., @('rebuild') will stop processing @(see command)s
 immediately after executing a @(see command) that introduces name.
 @('Rebuild') will also stop if any @(see command) causes an error.  You may
 therefore wish to plant an erroneous form in the file, e.g., @('(mv t nil
 state)'), (see @(see ld-error-triples)), to cause @('rebuild') to stop there.
 The form @('(i-am-here)') is such a pre-defined form.  If you do not specify a
 filter, @('rebuild') will query you for one.</p>

 <p>Inspection of the definition of @('rebuild'), e.g., via @(':')@(tsee pc)
 @('rebuild-fn'), will reveal that it is just a glorified call to the function
 @(tsee ld).  See @(see ld) if you find yourself wishing that @('rebuild') had
 additional functionality.</p>

 <p>If you supply the above ``filter'' argument, then you may also supply the
 keyword argument @(':dir'), which is then passed to @('ld'); see @(see
 ld).</p>")

(defxdoc redef
  :parents (ld)
  :short "A common way to set @(see ld-redefinition-action)"
  :long "@({
  Example and General Form:
  ACL2 !>:redef
 })

 <p>This command sets @(tsee ld-redefinition-action) to @(''(:query
 . :overwrite)').</p>

 <p>This command allows redefinition of functions and other @(see events)
 without undoing, but with a query that requires the user to acknowledge that
 the redefinition is intentional.  To avoid that query, see @(see redef!).  For
 more options and an important warning about the danger of using redefinition,
 including possible unsoundness, see @(see ld-redefinition-action).</p>")

(defxdoc redef!
  :parents (ld)
  :short "A common way to set @(see ld-redefinition-action)"
  :long "@({
  Example and General Form:
  ACL2 !>:redef!
 })

 <p>This command sets @(tsee ld-redefinition-action) to @(''(:warn!
 . :overwrite)').</p>

 <p>This command allows redefinition of functions and other @(see events)
 without undoing, but with a warning.  The command @(':')@(tsee redef) is
 similar, but queries the user first before doing the redefinition.  For more
 options and an important warning about the danger of using redefinition,
 including possible unsoundness, see @(see ld-redefinition-action).</p>")

(defxdoc redef+
  :parents (ld)
  :short "System hacker's redefinition @(see command)"
  :long "@({
  Example and General Form:
  ACL2 !>:redef+
  ACL2 p!>
 })

 <p>This @(see command) is intended only for system hackers, not typical users.
 It sets @(tsee ld-redefinition-action) to @(''(:warn! . :overwrite)'), sets
 the default @(see defun-mode) to @(':')@(tsee program), and invokes @(tsee
 set-state-ok) with value @('t').  It also introduces @('(defttag :redef+)'),
 so that redefinition of system functions will be permitted; see @(see
 defttag).  Finally, it removes as untouchable (see @(see push-untouchable))
 all variables and functions.</p>

 <p>WARNING: This command is potentially unsafe and even unsound!  For a
 relevant warning about redefinition, see @(see ld-redefinition-action).
 Moreover, if the form @('(redef+)') is used in a book, then including the book
 can leave you in a state in which dangerous actions are allowed, specifically:
 redefinition, and access to functions and variables normally prohibited
 because they are untouchable.  To avoid this problem, insert the form
 @('(')@(tsee redef-)@(')') into your book after @('(redef+)').</p>

 <p>To see the code for @('redef+'), evaluate @(':trans1 (redef+)').  This
 @(see command) is intended for those who are modifying ACL2 source code
 definitions.  Thus, note that even system functions can be redefined with a
 mere warning.  Be careful!</p>")

(defxdoc redef-
  :parents (ld)
  :short "Turn off system hacker's redefinition @(see command)"
  :long "@({
  Example and General Form:
  ACL2 !>:redef-
  ACL2 p!>
 })

 <p>This macro, for system hackers only, is a convenient way to reverse the
 effects of @(':redef+').  See @(see redef+).  We do not guarantee that
 @(':redef-') will restore everything one might expect to its state before the
 earlier @(':redef+').  To see exactly what @(':redef-') does, look at its
 code, for example by evaluating @(':trans1 (redef-)')</p>")

(defxdoc redefined-names
  :parents (world)
  :short "To collect the names that have been redefined"
  :long "@({
  Example and General Forms:
  (redefined-names state)
 })

 <p>This function collects names that have been redefined in the current ACL2
 @(see state).  @(':')@(tsee Program) mode functions that were reclassified to
 @(':')@(tsee logic) functions are not collected, since such reclassification
 cannot imperil soundness because it is allowed only when the new and old
 definitions are identical.</p>

 <p>Thus, if @('(redefined-names state)') returns @('nil') then no unsafe
 definitions have been made, regardless of @(tsee ld-redefinition-action).  See
 @(see ld-redefinition-action).</p>

 <p>WARNING: This function does not report names that are not explicitly
 redefined in the current logical @(see world).  Consider for example:</p>

 @({
  (encapsulate
   ()
   (defun foo () t)
   (local (defun foo () nil))
   (defthm foo-prop
     (equal (foo) nil)
     :rule-classes nil))
 })

 <p>If you attempt to call @(tsee certify-book) in the resulting world, ACL2
 will appropriately refuse to do the certification:</p>

 @({
  ACL2 Error in (CERTIFY-BOOK \"foo\" ...):  At least one command in the
  current ACL2 world was executed while the value of state global variable
  'LD-REDEFINITION-ACTION was not nil:

    (DEFUN FOO NIL T)

  Certification is therefore not allowed in this world.  You can use
  :ubt to undo back through this command; see :DOC ubt.
 })

 <p>However, since the local redefinition of @('foo') is gone in the
 certification world, @('(redefined-names state)') will return @('nil').
 (Technical aside, to be ignored except for those interested in implementation
 details: ACL2 inhibits @('certify-book') in this example because the
 definition of @('foo') is the value of @('(global-val 'redef-seen (w
 state))').)</p>")

(defxdoc redefining-programs
  :parents (programming)
  :short "An explanation of why we restrict redefinitions"
  :long "<p>ACL2 does not in general allow the redefinition of functions
 because logical inconsistency can result: previously stored theorems can be
 rendered invalid if the axioms defining the functions involved are changed.
 However, to permit prototyping of both @(':')@(tsee program) and @(':')@(tsee
 logic) mode systems, ACL2 permits redefinition if the user has accepted
 logical responsibility for the consequences by setting @(tsee
 ld-redefinition-action) to an appropriate non-@('nil') value.  The refusal of
 ACL2 to support the unrestricted redefinition of @(':')@(tsee program) mode
 functions may appear somewhat capricious.  After all, what are the logical
 consequences of changing a definition if no axioms are involved?</p>

 <p>Three important points should be made before we discuss redefinition
 further.</p>

 <p>The first is that ACL2 does support redefinition (of both @(':')@(tsee
 program) and @(':')@(tsee logic) functions) when @(tsee
 ld-redefinition-action) is non-@('nil').</p>

 <p>The second is that a ``redefinition'' that does not change the mode,
 formals, guards, type declarations, stobjs, or body of a function is
 considered redundant and is permitted even when @(tsee ld-redefinition-action)
 is @('nil').  We recognize and permit redundant definitions because it is not
 uncommon for two distinct @(see books) to share identical function
 definitions.  When determining whether the body of a function is changed by a
 proposed redefinition, we actually compare the untranslated versions of the
 two bodies.  See @(see term).  For example, redundancy is not recognized if
 the old body is @('(list a b)') and the new body is @('(cons a (cons b
 nil))').  We use the untranslated bodies because of the difficulty of
 translating the new body in the presence of the old syntactic information,
 given the possibility that the redefinition might attempt to change the @(see
 signature) of the function, i.e., the number of formals, the number of
 results, or the position of single-threaded objects in either.</p>

 <p>The third important point is that a ``redefinition'' that preserves the
 formals, guard, types, stobjs, and body but changes the mode from @(':')@(tsee
 program) to @(':')@(tsee logic) is permitted even when @(tsee
 ld-redefinition-action) is @('nil').  That is what @(tsee verify-termination)
 does.</p>

 <p>This note addresses the temptation to allow redefinition of @(':')@(tsee
 program) functions in situations other than the three described above.
 Therefore, suppose @(tsee ld-redefinition-action) is @('nil') and consider the
 cases.</p>

 <p>Case 1.  Suppose the new definition attempts to change the formals or more
 generally the @(see signature) of the function.  Accepting such a redefinition
 would render ill-formed other @(':')@(tsee program) functions which call the
 redefined function.  Subsequent attempts to evaluate those callers could
 arbitrarily damage the Common Lisp image.  Thus, redefinition of @(':')@(tsee
 program) functions under these circumstances requires the user's active
 approval, as would be sought with @(tsee ld-redefinition-action) @(''(:query
 . :overwrite)').</p>

 <p>Case 2.  Suppose the new definition attempts to change the body (even
 though it preserves the @(see signature)).  At one time we believed this was
 acceptable and ACL2 supported the quiet redefinition of @(':')@(tsee program)
 mode functions in this circumstance.  However, because such functions can be
 used in macros and redundancy checking is based on untranslated bodies, this
 turns out to be unsound!  (Aside: Perhaps this is not an issue if the function
 takes @(tsee state) or a user-defined @(see stobj) argument; but we do not
 further consider this distinction.)  Such redefinition is therefore now
 prohibited.  We illustrate such an unsoundness below.  Let @('foo-thm1.lisp')
 be a book with the following contents.</p>

 @({
  (in-package \"ACL2\")
  (defun p1 (x) (declare (xargs :mode :program)) (list 'if x 't 'nil))
  (defmacro p (x) (p1 x))
  (defun foo (x) (p x))
  (defthm foo-thm1 (iff (foo x) x) :rule-classes nil)
 })

 <p>Note that the macro form @('(p x)') translates to @('(if x t nil)').  The
 @(':')@(tsee program) function @('p1') is used to generate this translation.
 The function @('foo') is defined so that @('(foo x)') is @('(p x)') and a
 theorem about @('foo') is proved, namely, that @('(foo x)') is true iff @('x')
 is true.</p>

 <p>Now let @('foo-thm2.lisp') be a book with the following contents.</p>

 @({
  (in-package \"ACL2\")
  (defun p1 (x) (declare (xargs :mode :program)) (list 'if x 'nil 't))
  (defmacro p (x) (p1 x))
  (defun foo (x) (p x))
  (defthm foo-thm2 (iff (foo x) (not x)) :rule-classes nil)
 })

 <p>In this book, the @(':')@(tsee program) function @('p1') is defined so that
 @('(p x)') means just the negation of what it meant in the first book, namely,
 @('(if x nil t)').  The function @('foo') is defined identically &mdash; more
 precisely, the <i>untranslated</i> body of @('foo') is identical in the two
 @(see books), but because of the difference between the two versions of the
 @(':')@(tsee program) function @('p1') the axioms defining the two @('foo')s
 are different.  In the second book we prove the theorem that @('(foo x)') is
 true iff @('x') is nil.</p>

 <p>Now consider what would happen if the @(see signature)-preserving
 redefinition of @(':')@(tsee program) functions were permitted and these two
 @(see books) were included.  When the second book is included the redefinition
 of @('p1') would be permitted since the @(see signature) is preserved and
 @('p1') is just a @(':')@(tsee program).  But then when the redefinition of
 @('foo') is processed it would be considered redundant and thus be permitted.
 The result would be a logic in which it was possible to prove that @('(foo
 x)') is equivalent to both @('x') and @('(not x)').  In particular, the
 following sequence leads to a proof of nil:</p>

 @({
  (include-book \"foo-thm1\")
  (include-book \"foo-thm2\")
  (thm nil :hints ((\"Goal\" :use (foo-thm1 foo-thm2))))
 })

 <p>It might be possible to loosen the restrictions on the redefinition of
 @(':')@(tsee program) functions by allowing @(see signature)-preserving
 redefinition of @(':')@(tsee program) functions not involved in macro
 definitions.  Alternatively, we could implement definition redundancy checking
 based on the translated bodies of functions (though that is quite
 problematic).  Barring those two changes, we believe it is necessary simply to
 impose the same restrictions on the redefinition of @(':')@(tsee program) mode
 functions as we do on @(':')@(tsee logic) mode functions.</p>")

(defxdoc redo-flat
  :parents (debugging)
  :short "Redo on failure of a @(tsee progn), @(tsee encapsulate), or @(tsee certify-book)"
  :long "<p>When one submits an @(tsee encapsulate), @(tsee progn), or @(tsee
 certify-book) command and there is a failure, ACL2 restores its logical @(see
 world) as though the command had not been run.  But sometimes one would like
 to debug the failure by re-executing all sub-events that succeeded up to the
 point of failure, and then re-executing the failed sub-event.  Said
 differently, imagine that the @(see events) under an @('encapsulate'),
 @('progn'), or @('certify-book') form were flattened into a list of events
 that were then submitted to ACL2 up to the point of failure.  This would put
 us in the state in which the original failed event had failed, so we could now
 replay that failed event and try modifying it, or first proving additional
 events, in order to get it admitted.</p>

 <p>@('Redo-flat') is provided for this purpose.  Consider the following
 (rather nonsensical) example, in which the @(tsee defun) of @('f3') fails (the
 body is @('y') but the formal parameter list is @('(x)')).</p>

 @({
  (encapsulate
   ()
   (defun f1 (x) x)
   (encapsulate ()
                (local (defthm hack (equal (car (cons x y)) x))))
   (encapsulate ()
                (local (defthm hack (equal (+ x y) (+ y x)))))
   (encapsulate ()
                (make-event '(defun f2 (x) x))
                (progn (defthm foo (equal x x) :rule-classes nil)
                       (defun f3 (x) y)))
   (defun f4 (x) x)
   (defun f5 (x) y))
 })

 <p>After this attempt fails, you can evaluate the following form.</p>

 @({
  (redo-flat)
 })

 <p>This will first lay down a @(tsee deflabel) event, @('(deflabel r)'), so
 that you can eventually remove your debugging work with @('(:ubt! r)').  Then
 the successful sub-events that preceded the failure will be executed with
 proofs skipped (so that this execution is fast).  Then, the failed event will
 be executed.  Finally, a @(':')@(tsee pbt) command is executed so that you can
 see a summary of the events that executed successfully.</p>

 <p>You can eliminate some of the steps above by supplying keyword values, as
 follows.</p>

 @({
  (redo-flat
   :succ  succ ; Skip the successful sub-events if val is nil.
   :fail  fail ; Skip the failed sub-event if val is nil.
   :label lab  ; Skip deflabel if lab or succ is nil, else use (deflabel lab).
   :pbt   val  ; Skip the final :pbt if val, lab, or succ is nil.
   )
 })

 <p>Also, you can avoid skipping proofs for the successful sub-events by
 supplying keyword @(':succ-ld-skip-proofsp') with a valid value for
 @('ld-skip-proofsp'); see @(see ld-skip-proofsp).  For example, you might want
 to execute @('(redo-flat :succ-ld-skip-proofsp nil)') if you use the
 @('must-fail') utility from community book @('make-event/eval.lisp'), since
 for example @('(must-fail (thm (equal x y)))') normally succeeds but would
 cause an error if proofs are skipped.  For another example: you may wish to do
 proofs when re-running certain @(tsee make-event) forms, for example, when the
 expansion is @('(:OR expr1 expr2)') and the proof initially succeeds for
 @('expr2') rather than @('expr1') (see @(see make-event)).</p>

 <p>If you prefer only to see the successful and failed sub-events, without any
 events being re-executed, you may evaluate the following form instead.</p>

 @({
  (redo-flat :show t)
 })

 <p>For the example above, this command produces the following output.</p>

 @({
  List of events preceding the failure:

  ((DEFUN F1 (X) X)
   (ENCAPSULATE NIL
                (LOCAL (DEFTHM HACK (EQUAL (CAR (CONS X Y)) X))))
   (ENCAPSULATE NIL
                (LOCAL (DEFTHM HACK (EQUAL (+ X Y) (+ Y X)))))
   (MAKE-EVENT '(DEFUN F2 (X) X))
   (DEFTHM FOO (EQUAL X X)
           :RULE-CLASSES NIL))

  Failed event:

  (DEFUN F3 (X) Y)
  ACL2 !>
 })

 <p>@('Redo-flat') uses a scheme that should not cause spurious name conflicts
 for @(tsee local) events.  Above, it is mentioned that events are
 ``flattened''; now we clarify this notion.  Each sub-event that succeeds and
 is an @(tsee encapsulate) or @(tsee progn) is left intact.  Only such events
 that fail are replaced by their component events.  Thus, in the example above,
 there is no conflict between the two @(tsee local) sub-events named
 ``@('hack'),'' because these are contained in successful @('encapsulate')
 sub-events, which are therefore not flattened.  The @(tsee progn) and two
 @(tsee encapsulate) events surrounding the definition of @('f3') are, however,
 flattened, because that definition failed to be admitted.</p>

 <p>Normally, @('redo-flat') will have the desired effect even if you
 interrupted a proof (with control-c).  However, @('redo-flat') will not
 produce the desired result after an interrupt if you have enabled the debugger
 using @('(set-debugger-enable t)'),</p>")

(defxdoc redundant-encapsulate
  :parents (encapsulate)
  :short "Redundancy of @(tsee encapsulate) @(see events)"
  :long "<p>For this @(see documentation) topic we assume familiarity with
 @('encapsulate') events and the notion of redundancy for @(see events); see
 @(see encapsulate) and see @(see redundant-events).  Until the final remark,
 we also assume that redefinition is off (see @(see
 ld-redefinition-action)).</p>

 <p>The typical way for an @('encapsulate') event to be redundant is when a
 syntactically identical @('encapsulate') has already been executed under the
 same @(tsee default-defun-mode), @(tsee default-ruler-extenders), and @(tsee
 default-verify-guards-eagerness).  But more generally, the @('encapsulate')
 events need not be syntactically identical; for example, it suffices that they
 agree when the contents of @(tsee local) sub-events are ignored.  Detailed
 criteria for redundancy are given below, but let us first look at a
 consequence of the point just made about ignoring the contents of @(tsee
 local) sub-events.  Consider the following sequence of two events.</p>

 @({
  (encapsulate
   ()
   (defun f (x) x)
   (local (defthm f-identity
            (equal (f x) x))))

  (encapsulate
   ()
   (defun f (x) x)
   (local (defthm false-claim
            (equal (f x) (not x)))))
 })

 <p>You might be surprised to learn that the second is actually redundant, even
 though @('false-claim') is clearly not a theorem; indeed, its negation is a
 theorem!  The following two points may soften the blow.  First, this behavior
 is as specified above (and is specified more precisely below): the contents of
 @(see local) events are ignored when checking redundancy of @(tsee
 encapsulate) events.  Second, this behavior is sound, because the logical
 meaning of an @(tsee encapsulate) event is taken from the events that it
 exports, which do not include events that are @(see local) to the
 @('encapsulate') event.</p>

 <p>Some users, however, want to use @(tsee encapsulate) events for testing in
 a way that is thwarted by this ignoring of @(see local) sub-events.  Consider
 the following sort of example.</p>

 @({
  (encapsulate ()
               (local (defthm test1 ...)))

  (encapsulate ()
               (local (defthm test2 ...)))
 })

 <p>Fortunately, in this case both @('test1') and @('test2') will be evaluated.
 To see why, first note that when a completed @(see encapsulate) event with
 empty @(see signature) has introduced no sub-@(see events), then it has no
 effect at all on the logical @(see world).  Thus, the first @('encapsulate')
 event is not stored in the world; so, the second @('encapsulate') event is not
 redundant, since it is executed in a world that contains no trace of the first
 @('encapsulate') event.</p>

 <p>Also see community books @('misc/eval.lisp'),
 @('make-event/eval-check.lisp'), and @('make-event/eval-tests.lisp') for more
 ways to test in books.</p>

 <p>Here are detailed criteria for redundancy of @(tsee encapsulate) @(see
 events).  First, based on a heuristic (but rather thorough) check, the
 proposed (new) @('encapsulate') event must be seen as <i>possibly</i>
 introducing a new name, for example because one of its sub-events, perhaps
 after some macroexpansion, is an invocation of @(tsee defun), of @(tsee
 defthm), or of certain other events that <i>might</i> introduce a name,
 including @(tsee make-event).  Second, the two @(see world)s in which each
 @('encapsulate') event is evaluated must have the same @(see
 default-defun-mode)s, the same @(see default-ruler-extenders), and the same
 @(see default-verify-guards-eagerness).  Third, the existing and proposed
 @('encapsulate') @(see events) must contain the same @(see signature)s and the
 same number of top-level sub-events; let @('k') be that number.  Finally: for
 each @('i < k'), the @('i')th top-level events @('E1') and @('E2') from the
 earlier and proposed @('encapsulate')s must be related in one of the following
 ways.</p>

 <ul>

 <li>@('E1') and @('E2') are equal; or</li>

 <li>@('E1') is of the form @('(record-expansion E2 ...)'); or else</li>

 <li>@('E1') and @('E2') are equal after replacing each sub-event of @('E1')
 with its @(tsee make-event) expansion and replacing each @(tsee local)
 sub-event of @('E1') or @('E2') by @('(local (value-triple :elided))').  Here,
 a sub-event of an event @('E') is defined to be either @('E') itself, or a
 sub-event of a constituent event of @('E') in the case that @('E') is a call
 of @(tsee skip-proofs), @(tsee with-output), @(tsee with-prover-time-limit),
 @(tsee with-prover-step-limit), @('record-expansion'), @(tsee time$), @(tsee
 progn), @(tsee progn!), or @(tsee encapsulate) itself.</li>

 </ul>

 <p><b>Remark</b>.  We conclude with some discussion of redundancy of
 @('encapsulate') events in the presence of redefinition (see @(see
 ld-redefinition-action)).  Consider the following sequence of events.</p>

 @({
 (encapsulate () (defun foo (x) x))

 (redef!) ; Turn on redefinition.

 ; not redundant
 (encapsulate () (defun foo (x) (cons x x)))

 ; not redundant
 (encapsulate () (defun foo (x) x))
 })

 <p>Note that the last @('encapsulate') call is identical to an earlier event,
 namely the first one.  However, ACL2 never sees that first event when
 determining whether the last event is redundant.  The reason is that when ACL2
 searches the world for a corresponding @('encapsulate') event, it does not
 look back past the most recent definition of @('foo').</p>

 <p>By contrast, consider what happens when, in a fresh ACL2 session, we
 evaluate the following sequence instead, obtained by wrapping a @(tsee
 make-event) call around each @(tsee defun) event.</p>

 @({
 (encapsulate () (make-event '(defun foo (x) x)))

 (redef!) ; Turn on redefinition.

 ; not redundant
 (encapsulate () (make-event '(defun foo (x) (cons x x))))

 ; redundant!
 (encapsulate () (make-event '(defun foo (x) x)))
 })

 <p>It may be surprising that the last @('encapsulate') call is redundant.  The
 reason is that it is identical to an earlier @('encapsulate') event.  Because
 of the use of @('make-event') in the final event, ACL2 does not determine that
 the last event is attempting to define @('foo'), so ACL2 does not limit its
 search backward through the world as it did in the previous example (where
 there were no uses of @('make-event')).  The moral of the story: when
 redefinition is involved, it may be best not to rely on one's intuition about
 redundancy for @('encapsulate') events.</p>")

(defxdoc redundant-events
  :parents (events)
  :short "Allowing a name to be introduced ``twice''"
  :long "<p>Sometimes an event will announce that it is ``redundant'', meaning
 that the the form is not evaluated because ACL2 determines that its effect is
 already incorporated into the logical @(see world).  Thus, when this happens,
 no change to the logical @(see world) takes place.  This feature permits two
 independent @(see books), each of which defines some name, to be included
 sequentially provided they use exactly the same definition.</p>

 <p>Note that by the definition above, a form can have no effect on the logical
 @(see world) yet not be considered to be redundant.  Here is an example of
 such a form.</p>

 @({
    (value-triple (cw \"Hello world.~%\"))
 })

 <p>When are two @(see logical-name) definitions considered ``the same''?  It
 depends upon the kind of event that introduces that name.  We consider these
 below in alphabetical order, followed by ``Note About'' comments.  Macros in
 the @(see community-books) may also support redundancy; see their
 documentation for details, since below we only discuss ACL2 @(see events) that
 are built into ACL2.</p>

 <p>A @(tsee defabsstobj) is redundant if there is already an identical
 @('defabsstobj') event in the logical @(see world).</p>

 <p>A @(tsee defattach) event is never redundant.  Note that it doesn't define
 any name.</p>

 <p>A @(tsee defaxiom) or @(tsee defthm) event is redundant if there is already
 an axiom or theorem of the given name and either the two @(see events) are
 syntactically identical, or both the formula (after macroexpansion) and the
 resulting @(see rule-classes) are syntactically identical.  Note that because
 of the second of these two criteria, a @(tsee defaxiom) can make a subsequent
 @(tsee defthm) redundant, and a @(tsee defthm) can make a subsequent @(tsee
 defaxiom) redundant as well.</p>

 <p>A @(tsee defconst) is redundant if the name is already defined either with
 a syntactically identical @('defconst') event or one that defines it to have
 the same value.</p>

 <p>A @(tsee deflabel) event is never redundant.  This means that if you have a
 @(tsee deflabel) in a book and that book has been included (without error),
 then references to that label denote the point in @(see history) at which the
 book introduced the label.  See the note about shifting logical names,
 below.</p>

 <p>A @(tsee defmacro) event is redundant if there is already a macro defined
 with the same name and syntactically identical arguments, @(see guard), and
 body.</p>

 <p>A @(tsee defpkg) event is redundant if a package of the same name with
 exactly the same imports has been defined.</p>

 <p>A @(tsee defstobj) event is redundant if there is already a @('defstobj')
 event with the same name that has exactly the same field descriptors (see
 @(see defstobj)), in the same order, and with the same @(':renaming') value if
 @(':renaming') is supplied for either event.</p>

 <p>A @(tsee defthm) event is redundant according to the criteria given above
 in the discussion of @('defaxiom').</p>

 <p>A @(tsee deftheory) event is redundant if keyword argument
 @(':redundant-okp') is not @('nil') and the theory is unchanged from the one
 already associated with the name.  More precisely, the runic theory computed
 from the theory expression must be equal to the runic theory already
 associated with the name.  (See @(see theories) for a discussion of runic
 theories.  Also see @(see defthy) for a variant of @('deftheory') that
 supports redundancy by default.)  Equality of runic theories is a rather
 severe restriction, since most theory expressions are sensitive to the context
 in which they occur.  Consider the following example.</p>

 @({
 (deftheory foo (disable append revappend) :redundant-okp t)
 (defthm my-car-cons (equal (car (cons x y)) x))
 (deftheory foo (disable revappend append) :redundant-okp t)
 })

 <p>The second @('deftheory') event above is not redundant, because its
 computed runic theory includes the @(see rune) @('(:rewrite my-car-cons)'),
 which is not in the runic theory previously associated with @('foo').  If we
 change the example either to eliminate the @(tsee defthm) above or to change
 it to call @(tsee defthmd) instead, then the second @('deftheory') event is
 redundant, because the runic theories are ordered, and hence the order of
 runic designators (here, @('revappend') and @('append')) is irrelevant.</p>

 <p>A @(tsee defun), @(tsee defuns), or @(tsee mutual-recursion) event is
 redundant if for each function to be introduced, there has already been
 introduced a function with the same name, formals, and body (before
 macroexpansion), and with the same values @(see declare)d for the @(':')@(tsee
 guard), @(':')@(tsee measure), types, @(':')@(tsee ruler-extenders),
 @(':non-executable'), @(':')@(tsee stobj)@('s'), and @(':')@(tsee
 split-types), provided that the @(see defun-mode)s are appropriate (see the
 ``Note About Appropriate Modes'' below).  Moreover, the order of the combined
 @(':')@(tsee guard) and type declarations must be the same in both cases.
 Exceptions and clarifications:</p>

 <ol>

 <li>If the new and existing function events have no explicit @(see
 ruler-extenders) (which are therefore syntactically equal), the @(see
 default-ruler-extenders) for the new and existing function events must be the
 same.</li>

 <li>It is permissible for one definition to have a @(':')@(see guard) of
 @('t') and the other to have no explicit guard (hence, the guard is implicitly
 @('t')).</li>

 <li>The @(':measure') check is avoided if the old definition is non-recursive
 (and not defined within a @(tsee mutual-recursion)) or we are skipping proofs
 (for example, during @(tsee include-book)).  Otherwise, the new definition may
 have a @(':measure') of @('(:? v1 ... vk)'), where @('(v1 ... vk)') enumerates
 the variables occurring in the measure stored for the old definition.</li>

 <li>If either the old or new event is a @(tsee mutual-recursion) event, then
 redundancy requires that both are @(tsee mutual-recursion) events that define
 the same set of function symbols.</li>

 </ol>

 <p>An @(tsee encapsulate) event is most commonly redundant when a
 syntactically identical @(tsee encapsulate) has already been executed under
 the same @(tsee default-defun-mode), @(tsee default-ruler-extenders), and
 @(tsee default-verify-guards-eagerness).  The full criterion for redundancy of
 @('encapsulate') events is more complex, for example ignoring contents of
 @(tsee local) @(see events); see @(see redundant-encapsulate).</p>

 <p>An @(tsee in-theory) event is never redundant.  Note that it doesn't define
 any name.</p>

 <p>An @(tsee include-book) event is redundant if the book has already been
 included.</p>

 <p>A call of @(tsee make-event) is never redundant, as its argument is always
 evaluated to obtain the make-event expansion.  However, that expansion may of
 course be redundant.</p>

 <p>A @(tsee mutual-recursion) event is redundant according to the criteria in
 the discussion above for the case of a @('defun') event.</p>

 <p>A @(tsee progn) event is never redundant: its subsidiary @(see events) are
 always considered.  Of course, its sub-events may themselves be redundant.  If
 all of its sub-events are redundant &mdash; or more generally, if none of the
 sub-events changes the logical @(see world) &mdash; then the @('progn') event
 also won't change the world.</p>

 <p>A @(tsee push-untouchable) event is redundant if every name supplied is
 already a member of the corresponding list of untouchable symbols.</p>

 <p>A @(tsee regenerate-tau-database) event is never redundant.  Note that it
 doesn't define any name.</p>

 <p>A @(tsee remove-untouchable) event is redundant if no name supplied is a
 member of the corresponding list of untouchable symbols.</p>

 <p>A @(tsee reset-prehistory) event is redundant if it does not cause any
 change.</p>

 <p>A @(tsee set-body) event is redundant if the indicated body is already the
 current body.</p>

 <p>A @(tsee table) event not define any name.  It is redundant when it sets
 the value already associated with a key of the table, or when it sets an
 entire table (using keyword @(':clear')) to its existing value; see @(see
 table).</p>

 <p>A @(tsee verify-guards) event is redundant if the function has already had
 its @(see guard)s verified.</p>

 <p><i>Note About Built-in (Predefined) Functions and Macros:</i></p>

 <p>Redundancy is restricted for built-in macros and functions that have
 special raw Lisp code.  Such redundancy is only legal in the context of @(tsee
 LOCAL).  This restriction is needed for soundness, for technical reasons
 omitted here (details may be found in a long comment about redundant-events in
 source function @('chk-acceptable-defuns-redundancy')).</p>

 <p><i>Note About Appropriate Modes:</i></p>

 <p>Suppose a function is being redefined and that the formals, guards, types,
 stobjs, and bodies are identical.  When are the modes (@(':')@(tsee program)
 or @(':')@(tsee logic)) ``appropriate?''  Identical modes are appropriate.
 But what if the old mode was @(':program') and the new mode is @(':logic')?
 This is appropriate, provided the definition meets the requirements of the
 logical definitional principle.  That is, you may redefine ``redundantly'' a
 @(':program') mode function as a @(':logic') mode function provide the measure
 conjectures can be proved.  This is what @(tsee verify-termination) does.  Now
 consider the reverse style of redefinition.  Suppose the function was defined
 in @(':logic') mode and is being identically redefined in @(':program') mode.
 ACL2 will treat the redefinition as redundant, provided the appropriate
 criteria are met (as though it were in :logic mode).</p>

 <p><i>Note About Shifting Logical Names:</i></p>

 <p>Suppose a book defines a function @('fn') and later uses @('fn') as a
 logical name in a theory expression.  Consider the value of that theory
 expression in two different sessions.  In session A, the book is included in a
 @(see world) in which @('fn') is not already defined, i.e., in a @(see world)
 in which the book's definition of @('fn') is not redundant.  In session B, the
 book is included in a @(see world) in which @('fn') is already identically
 defined.  In session B, the book's definition of @('fn') is redundant.  When
 @('fn') is used as a logical name in a theory expression, it denotes the point
 in @(see history) at which @('fn') was introduced.  Observe that those points
 are different in the two sessions.  Hence, it is likely that theory
 expressions involving @('fn') will have different values in session A than in
 session B.</p>

 <p>This may adversely affect the user of your book.  For example, suppose your
 book creates a theory via @(tsee deftheory) that is advertised just to contain
 the names generated by the book.  But suppose you compute the theory as the
 very last event in the book using:</p>

 @({
    (set-difference-theories (universal-theory :here)
                             (universal-theory fn))
 })

 <p>where @('fn') is the very first event in the book and happens to be a
 @(tsee defun) event.  This expression returns the advertised set if @('fn') is
 not already defined when the book is included.  But if @('fn') were previously
 (identically) defined, the theory is larger than advertised.</p>

 <p>The moral of this is simple: when building @(see books) that other people
 will use, it is best to describe your @(see theories) in terms of logical
 names that will not shift around when the @(see books) are included.  The best
 such names are those created by @(tsee deflabel).</p>

 <p><i>Note About Unfortunate Redundancies.</i></p>

 <p>Notice that our syntactic criterion for redundancy of @(tsee defun) @(see
 events) may not allow redefinition to take effect unless there is a syntactic
 change in the definition.  The following example shows how an attempt to
 redefine a function can fail to make any change.</p>

 @({
    (set-ld-redefinition-action '(:warn . :overwrite) state)
    (defmacro mac (x) x)
    (defun foo (x) (mac x))
    (defmacro mac (x) (list 'car x))
    (set-ld-redefinition-action nil state)
    (defun foo (x) (mac x)) ; redundant, unfortunately; foo does not change
    (thm (equal (foo 3) 3)) ; succeeds, showing that redef of foo didn't happen
 })

 <p>The call of macro @('mac') was expanded away before storing the first
 definition of @('foo') for the theorem prover.  Therefore, the new definition
 of @('mac') does not affect the expansion of @('foo') by the theorem prover,
 because the new definition of @('foo') is ignored.</p>

 <p>One workaround is first to supply a different definition of @('foo'), just
 before the last definition of @('foo') above.  Then that final definition will
 no longer be redundant.  However, as a courtesy to users, we strengthen the
 redundancy check for function definitions when redefinition is active.  If in
 the example above we remove the form @('(set-ld-redefinition-action nil
 state)'), then the problem goes away:</p>

 @({
    (set-ld-redefinition-action '(:warn . :overwrite) state)
    (defmacro mac (x) x)
    (defun foo (x) (mac x))
    (defmacro mac (x) (list 'car x))
    (defun foo (x) (mac x)) ; no longer redundant
    (thm (equal (foo 3) 3)) ; fails, as we would like
 })

 <p>To summarize: If a @(tsee defun) form is submitted that meets the usual
 redundancy criteria, then it may be considered redundant even if a macro
 called in the definition has since been redefined.  The analogous problem
 applies to constants, i.e., symbols defined by @(tsee defconst) that occur in
 the definition body.  However, if redefinition is currently active the problem
 goes away: that is, the redundancy check is strengthened to check the
 ``translated'' body, in which macro calls and constants defined by @(tsee
 defconst) are expanded away.</p>

 <p>The above discussion for @(tsee defun) forms applies to @(tsee defconst)
 forms as well.  However, for @(tsee defmacro) forms ACL2 always checks
 translated bodies, so such bogus redundancy does not occur.</p>

 <p>Here is more complex example illustrating the limits of redefinition, based
 on one supplied by Grant Passmore.</p>

 @({
    (defun n3 () 0)
    (defun n4 () 1)
    (defun n5 () (> (n3) (n4))) ; body is see normalized to nil
    (thm (equal (n5) nil)) ; succeeds, trivially
    (set-ld-redefinition-action '(:warn . :overwrite) state)
    (defun n3 () 2)
    (thm (equal (n5) nil)) ; still succeeds, sadly
 })

 <p>We may expect the final @(tsee thm) call to fail because of the following
 reasoning: @('(n5)') = @('(> (n3) (n4))') = @('(> 2 1)') = @('t').
 Unfortunately, the body of @('n5') was simplified to @('nil') when @('n5') was
 admitted (see @(see normalize)), so the redefinition of @('n3') is ignored
 during the final @('thm') call.  (Such normalization can be avoided; see @(see
 xargs) for discussion of the @(':normalize') keyword.)  So, given this
 unfortunate situation, one might expect at this point simply to redefine
 @('n5') using the same definition as before, in order to pick up the new
 definition of @('n3').  Such ``redefinition'' would, however, be redundant,
 for the same reason as in the previous example: no syntactic change was made
 to the definition.  Even with redefinition active, there is no change in the
 body of @('n5'), even with macros and constants (defined by @(tsee defconst))
 expanded; there are none such!  The same workaround applies as before:
 redefine @('n5') to be something different, and then redefine @('n5') again to
 be as desired.</p>

 <p>A related phenomenon can occur for @(tsee encapsulate).  As explained
 above, an @('encapsulate') event is redundant if it is identical to one
 already in the database.  (But a weaker condition applies in general; see
 @(see redundant-encapsulate).)  Consider then the following contrived
 example.</p>

 @({
    (defmacro mac (x) x)
    (encapsulate () (defun foo (x) (mac x)))
    (set-ld-redefinition-action '(:warn . :overwrite) state)
    (defmacro mac (x) (list 'car x))
    (encapsulate () (defun foo (x) (mac x)))
 })

 <p>The last @('encapsulate') event is redundant because it meets the criterion
 for redundancy: it is identical to the earlier @('encapsulate') event.  Even
 though redefinition is active, and hence ACL2 ``should'' be able to see that
 the new @(tsee defun) of @('foo') is not truly redundant, nevertheless the
 criterion for redundancy of @(tsee encapsulate) allows the new
 @('encapsulate') form to be redundant.</p>

 <p>A workaround can be to add something trivial to the @('encapsulate'), for
 example:</p>

 @({
    (encapsulate ()
      (deflabel try2) ; ``Increment'' to try3 next time, and so on.
      (defun foo (x) x))
 })")

(defxdoc refinement
  :parents (rule-classes)
  :short "Record that one equivalence relation refines another"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 @({
  Example:
  (defthm bag-equal-refines-set-equal
    (implies (bag-equal x y)
             (set-equal y x))
    :rule-classes :refinement)
 })

 <p>Also see @(see defrefinement).</p>

 @({
  General Form:
  (implies (equiv1 x y) (equiv2 x y))
 })

 <p>@('Equiv1') and @('equiv2') must be known equivalence relations.  The
 effect of such a rule is to record that @('equiv1') is a refinement of
 @('equiv2').  This means that @('equiv1') @(':')@(tsee rewrite) rules may be
 used while trying to maintain @('equiv2').  See @(see equivalence) for a
 general discussion of the issues.</p>

 <p>The macro form @('(defrefinement equiv1 equiv2)') is an abbreviation for a
 @(tsee defthm) of rule-class @(':refinement') that establishes that
 @('equiv1') is a refinement of @('equiv2').  See @(see defrefinement).</p>

 <p>Suppose we have the @(':')@(tsee rewrite) rule</p>

 @({
  (bag-equal (append a b) (append b a))
 })

 <p>which states that @(tsee append) is commutative modulo bag-equality.
 Suppose further we have established that bag-equality refines set-equality.
 Then when we are simplifying @(tsee append) expressions while maintaining
 set-equality we use @(tsee append)'s commutativity property, even though it
 was proved for bag-equality.</p>

 <p>Equality is known to be a refinement of all equivalence relations.  The
 transitive closure of the refinement relation is maintained, so if
 @('set-equality'), say, is shown to be a refinement of some third sense of
 equivalence, then @('bag-equality') will automatically be known as a refinement
 of that third equivalence.</p>

 <p>@(':refinement') lemmas cannot be disabled.  That is, once one equivalence
 relation has been shown to be a refinement of another, there is no way to
 prevent the system from using that information.  Of course, individual
 @(':')@(tsee rewrite) rules can be disabled.</p>

 <p>More will be written about this as we develop the techniques.</p>")

(defxdoc regenerate-tau-database
  :parents (events introduction-to-the-tau-system)
  :short "Regenerate the tau database relative to the current enabled theory"
  :long "@({
  General Form:
  (regenerate-tau-database)
 })

 <p>The tau database is regenerated by scanning the current logical world and
 re-processing every rule-generating event in it relative to the current
 enabled theory and current tau auto mode settings.  See @(see
 introduction-to-the-tau-system) for background details.</p>

 <p>This command was intended to allow the user to remove a fact from the tau
 database, by regenerating the database without the fact.  But as the following
 discussion highlights, @('regenerate-tau-database') does not really solve the
 problem.  We regard it as a placeholder for a more sophisticated mechanism.
 However, we have trouble understanding why a user might wish to remove a fact
 from the database and are awaiting further user experiences before designing
 the more sophisticated mechanism.</p>

 <p>Suppose, for example, that you wanted to remove a signature rule provided
 by some rule with name <i>rune</i>.  You could disable <i>rune</i> and
 regenerate the database.  We discuss why you might &mdash; or might not
 &mdash; want to do this later.  But suppose you did it.  Unfortunately, the
 database you get will not be just like the one you started with minus the
 signature rule.  The reason is that the database you started with was
 generated incrementally and the current theory might have evolved.  To take a
 simple example, your starting database might have included a rule that has
 been disabled since it was first added.  Thus, the part of your starting
 database built before the disabling was constructed with the rule enabled and
 the part built afterwards has the rule disabled.  You are unlikely to get the
 same database whether you enable or disable that rule now.</p>

 <p>You might hope that the avoidance of @('in-theory') events would eliminate
 the problem but it does not because even the @(tsee ground-zero) theory is
 constructed incrementally from the ``pre-history'' commands used to boot up
 ACL2.  Those pre-history commands include some global @('in-theory') commands.
 Since every session starts from the @('ground-zero') state, the starting
 database is already ``infected'' with global @('in-theory') commands.</p>

 <p>The reason we hope that it will not be necessary to remove tau facts is
 that the tau system is designed merely to be fast and benign (see <i>Design
 Philosophy</i> in @(see introduction-to-the-tau-system)).  The tau system's
 coverage should grows monotonically with the addition of rules.  According to
 this understanding of tau, adding a signature rule, for example, may allow tau
 to prove some additional goals but will not prevent it from proving goals it
 could prove previously.  If this is understanding of tau is accurate, we see
 no fundamental reason to support the removal of a fact.  This, of course,
 ignores the possibility that the user wishes to explore alternative proof
 strategies or measure performance.</p>

 <p>We welcome user observations and experience on this issue.</p>")

(defxdoc release-notes
  :parents (about-acl2)
  :short "Pointers to what has changed"
  :long "<p>This section of the online @(see documentation) contains notes on
 the changes that distinguish successive released versions of ACL2.</p>

 <p>Each topic @('note-x-y') is a note describing what in ACL2 version X.Y was
 new in comparison to the preceding version of ACL2.</p>

 <p>The current version of ACL2 is the value of the constant @('(@
 acl2-version)').</p>")

(defxdoc rem
  :parents (numbers acl2-built-ins)
  :short "Remainder using @(tsee truncate)"
  :long "@({
  ACL2 !>(rem 14 3)
  2
  ACL2 !>(rem -14 3)
  -2
  ACL2 !>(rem 14 -3)
  2
  ACL2 !>(rem -14 -3)
  -2
  ACL2 !>(rem -15 -3)
  0
  ACL2 !>
 })

 <p>@('(Rem i j)') is that number @('k') for which @('(* j (truncate i j))')
 added to @('k') equals @('i').</p>

 <p>The @(see guard) for @('(rem i j)') requires that @('i') and @('j') are
 rational (@(see real), in ACL2(r)) numbers and @('j') is non-zero.</p>

 <p>@('Rem') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def rem)")

(defxdoc remove
  :parents (lists acl2-built-ins)
  :short "Remove all occurrences"
  :long "@({
  General Forms:
  (remove x lst)
  (remove x lst :test 'eql)   ; same as above (eql as equality test)
  (remove x lst :test 'eq)    ; same, but eq is equality test
  (remove x lst :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Remove x lst)') is equal to @('lst') if @('x') is not a member of
 @('lst'), else is the result of removing all occurrences of @('x') from
 @('lst').  The optional keyword, @(':TEST'), has no effect logically, but
 provides the test (default @(tsee eql)) used for comparing @('x') with
 successive elements of @('lst').</p>

 <p>Also see @(see remove1).</p>

 <p>The @(see guard) for a call of @('remove') depends on the test.  In all
 cases, the second argument must satisfy @(tsee true-listp).  If the test is
 @(tsee eql), then either the first argument must be suitable for @(tsee eql)
 (see @(see eqlablep)) or the second argument must satisfy @(tsee
 eqlable-listp).  If the test is @(tsee eq), then either the first argument
 must be a symbol or the second argument must satisfy @(tsee symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('remove') and its variants:</p>

 <blockquote><p>@('(remove-eq x lst)') is equivalent to @('(remove x lst :test
 'eq)');</p>

 <p>@('(remove-equal x lst)') is equivalent to @('(remove x lst :test
 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('remove-equal').</p>

 @(def remove-equal)

 <p>@('Remove') is defined by Common Lisp.  See any Common Lisp documentation
 for more information.</p>")

(defxdoc remove-binop
  :parents (macros)
  :short "Remove the association of a function name with a macro name"
  :long "<p>The form @('(remove-binop macro-fn)') is an abbreviation for the
 form @('(remove-macro-fn macro-fn)').  See @(see remove-macro-fn).</p>")

(defxdoc remove-custom-keyword-hint
  :parents (events)
  :short "Remove a custom keyword hint"
  :long "@({
  Example Forms:
  (remove-custom-keyword-hint :my-hint)

  General Form:
  (remove-custom-keyword-hint keyword)
 })

 <p>where @('keyword') is a @(tsee keywordp).</p>

 <p>For an explanation of how custom keyword hints are processed, see @(see
 custom-keyword-hints); also see @(see add-custom-keyword-hint).</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>")

(defxdoc remove-default-hints
  :parents (default-hints)
  :short "Remove from the default hints"
  :long "@({
  Examples:
  (remove-default-hints '((computed-hint-1 clause)
                          (computed-hint-2 clause
                                           stable-under-simplificationp)))
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.  It is
 @(tsee local) to the book or @(tsee encapsulate) form in which it occurs (see
 @(see remove-default-hints!) for a corresponding non-@(tsee local) event).</p>

 @({
  General Form:
  (remove-default-hints lst)
 })

 <p>where @('lst') is a list.  Generally speaking, the elements of @('lst')
 should be suitable for use as @(tsee computed-hints).  Also see @(see
 add-default-hints).</p>

 <p>If some elements of the given list do not belong to the existing default
 hints, they will simply be ignored by this event.</p>

 <p>Also See @(see set-default-hints), see @(see add-default-hints), and see
 @(see default-hints).</p>

 <p>Finally, note that the effects of @('set-default-hints'), @(tsee
 add-default-hints), and @(tsee remove-default-hints) are @(tsee local) to the
 book in which they appear.  Thus, users who include a book with such forms
 will not have their default hints affected by such forms.  In order to export
 the effect of setting the default hints, use @(tsee set-default-hints!),
 @(tsee add-default-hints!), or @(tsee remove-default-hints!).</p>")

(defxdoc remove-default-hints!
  :parents (default-hints)
  :short "Remove from the default hints non-@(tsee local)ly"
  :long "<p>Please see @(see remove-default-hints), which is the same as
 @('remove-default-hints!')  except that the latter is not @(tsee local) to the
 @(tsee encapsulate) or the book in which it occurs.  Probably @(see
 remove-default-hints) is to be preferred unless you have a good reason for
 wanting to export the effect of this event outside the enclosing @(tsee
 encapsulate) or book.</p>")

(defxdoc remove-dive-into-macro
  :parents (dive-into-macros-table)
  :short "Removes association of @(see proof-builder) diving function with macro name"
  :long "@({
  Example:
  (remove-dive-into-macro logand)
 })

 <p>This feature undoes the effect of @(tsee add-dive-into-macro), which is
 used so that the interactive @(see proof-builder)'s @('DV') command and
 numeric diving commands (e.g., @('3')) will dive properly into subterms.
 Please see @(see add-dive-into-macro) and especially see @(see
 dive-into-macros-table).</p>")

(defxdoc remove-duplicates
  :parents (lists strings acl2-built-ins)
  :short "Remove duplicates from a string or a list"
  :long "@({
  General Forms:
  (remove-duplicates x)
  (remove-duplicates x :test 'eql)   ; same as above (eql as equality test)
  (remove-duplicates x :test 'eq)    ; same, but eq is equality test
  (remove-duplicates x :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Remove-duplicates x)') returns the result of deleting duplicate
 elements from the beginning of the list or string @('x').  For example,
 @('(remove-duplicates '(1 2 3 2 4))') is equal to @(''(1 3 2 4)').  The
 optional keyword, @(':TEST'), has no effect logically, but provides the test
 (default @(tsee eql)) used for comparing @('x') with successive elements of
 @('lst').</p>

 <p>The @(see guard) for a call of @('remove-duplicates') depends on the test.
 In all cases, the argument must satisfy @(tsee stringp) or @(tsee true-listp).
 If the test is @(tsee eql), then the argument must satisfy either @(tsee
 stringp) or @(tsee eqlable-listp).  If the test is @(tsee eq), then the
 argument must satisfy @(tsee symbol-listp).</p>

 <p>The relation between @('remove-duplicates') and its variants is related to
 the usual pattern for equality variants; see @(see equality-variants).
 However, the possibility of a string argument changes the usual pattern a bit.
 As one might expect:</p>

 <blockquote><p>@('(remove-duplicates-eq lst)') is equivalent to
 @('(remove-duplicates lst :test 'eq)').</p></blockquote>

 <p>However, @('remove-duplicates-equal') is defined without consideration of
 strings, for backward compatibility with versions of ACL2 through Version_4.2.
 The macro @('remove-duplicates-logic') has been introduced to model the
 behavior of @('remove-duplicates') even on strings; use @(':')@(tsee pe) if
 you wish to see its definition.  So we can say the following.</p>

 <blockquote><p>@('(remove-duplicates-logic lst)') is equivalent to
 @('(remove-duplicates lst :test 'equal)'); and</p>

 <p>@('(remove-duplicates-logic lst)') is equal to @('(remove-duplicates-equal
 lst)') when @('lst') is not a string.</p></blockquote>

 <p>In particular, when the argument is not a string, reasoning about any of
 these primitives reduces to reasoning about the function
 @('remove-duplicates-equal').</p>

 @(def remove-duplicates-equal)

 <p>@('Remove-duplicates') is defined by Common Lisp.  See any Common Lisp
 documentation for more information.</p>")

(defxdoc remove-invisible-fns
  :parents (loop-stopper)
  :short "Make some unary functions no longer invisible"
  :long "@({
  Examples:
  (remove-invisible-fns (binary-+ unary-- foo)
  (remove-invisible-fns (+ unary-- foo)
 })

 <p>The setting above has makes unary functions @(tsee unary--) and @('foo') no
 longer ``invisible'' for the purposes of applying permutative @(':')@(tsee
 rewrite) rules to @(tsee binary-+) trees.</p>

 @({
  General Form:
  (remove-invisible-fns top-fn unary-fn1 ... unary-fnk)
 })

 <p>where @('top-fn') is a function symbol and the @('unary-fni') are unary
 function symbols, or more generally, these are all macro aliases for function
 symbols (see @(see macro-aliases-table)).</p>

 <p>See @(see add-invisible-fns) and also see @(see invisible-fns-table) and
 see @(see set-invisible-fns-table).</p>")

(defxdoc remove-macro-alias
  :parents (macros)
  :short "Remove the association of a function name with a macro name"
  :long "@({
  Example:
  (remove-macro-alias append)

  General Form:
  (remove-macro-alias macro-name)
 })

 <p>See @(see macro-aliases-table) for a discussion of macro aliases; also see
 @(see add-macro-alias).  This form sets @(tsee macro-aliases-table) to the
 result of deleting the key @('macro-name') from that @(see table).  If the
 name does not occur in the @(see table), then this form still generates an
 event, but the event has no real effect.</p>")

(defxdoc remove-macro-fn
  :parents (macros)
  :short "Remove the association of a function name with a macro name"
  :long "@({
  Example:
  (remove-macro-fn binary-append)

  General Form:
  (remove-macro-fn macro-fn)
 })

 <p>See @(see add-macro-fn) for a discussion of how to associate a macro name
 with a function name.  This form sets @(tsee untrans-table) to the result of
 deleting the association of a macro name with the given binary function name.
 If the function name has no such association, then this form still generates
 an event, but the event has no real effect.</p>")

(defxdoc remove-nth-alias
  :parents (nth-aliases-table)
  :short "Remove a symbol alias for printing of @(tsee nth)/@(tsee update-nth) terms"
  :long "@({
  Example:
  (remove-nth-alias append)

  General Form:
  (remove-nth-alias alias-name)
 })

 <p>See @(see nth-aliases-table) for further discussion; also see @(see
 add-nth-alias).  This form sets @(tsee nth-aliases-table) to the result of
 deleting the key @('alias-name') from that @(see table).  If the name does not
 occur in the @(see table), then this form still generates an event, but the
 event has no real effect.</p>")

(defxdoc remove-override-hints
  :parents (override-hints)
  :short "Delete from the list of @(see override-hints)"
  :long "<p>See @(see override-hints) for a discussion of override-hints.  Here
 we describe how to delete from the list of override-hints.  Note that the
 effects of @('remove-override-hints') @(see events) are @(see local) to the
 @(see books) or @('encapsulate') @(see events) in which they reside; see @(see
 remove-override-hints!)  to avoid that restriction.  Also see @(see
 add-override-hints) and see @(see set-override-hints).</p>

 @({
  General Form:
  (remove-override-hints form)
 })

 <p>where @('form') should evaluate to a list of computed hint forms.  The
 effect of this event is to set the list of @(see override-hints) to the result
 of deleting each element of the evaluation result from the @(see
 override-hints), if that element indeed belongs to the override-hints; no
 check is made that these elements are actually elements of the existing
 override-hints.</p>")

(defxdoc remove-override-hints!
  :parents (override-hints)
  :short "Delete non-@(see local)ly from the list of @(see override-hints)"
  :long "<p>@('Remove-override-hints!') is the same as @(tsee
 remove-override-hints), except that the former is not @(see local) to @(see
 books) or @(tsee encapsulate) @(see events) in which it occurs.  See @(see
 remove-override-hints); also see @(see add-override-hints) and see @(see
 set-override-hints).</p>")

(defxdoc remove-raw-arity
  :parents (set-raw-mode)
  :short "Remove arity information for raw mode"
  :long "<p>Technical note: This macro is a no-op, and is not necessary, when
 ACL2 is built with #-acl2-mv-as-values.</p>

 <p>The form @('(remove-raw-arity fn)') undoes the effect of an earlier
 @('(remove-raw-arity fn val)').  See @(see add-raw-arity).</p>")

(defxdoc remove-untouchable
  :parents (defttag)
  :short "Remove names from lists of untouchable symbols"
  :long "<p>Untouchables are functions or macros that cannot be called, as well
 as @(see state) global variables (see @(see programming-with-state)) that
 cannot be modified or unbound.</p>

 @({
  Example Forms:
  (remove-untouchable my-var nil) ; then state global my-var is not untouchable
  (remove-untouchable set-mem t)  ; then function set-mem is not untouchable
 })

 <p>Also see @(see push-untouchable).</p>

 <p>This documentation topic is directed at those who build systems on top of
 ACL2.  We first describe a means for modifying @(see state) to remove some
 untouchables.  Then we describe the @('remove-untouchable') event.  Both
 require an active trust tag (see @(see defttag)).</p>

 <p>We begin by discussing untouchable state global variables
 @('temp-touchable-vars') and @('temp-touchable-fns'), which initially have
 value @('nil').  These can often be used in place of @('remove-untouchable').
 When the value is @('t'), no variable (respectively, no function or macro) is
 treated as untouchable, regardless of the set of initial untouchables or the
 @('remove-untouchable') or @(tsee push-untouchable) @(see events) that have
 been admitted.  Otherwise the value of each of these two variables is a @(tsee
 symbol-listp), and no member of this list is treated as an untouchable
 variable (in the case of @('temp-touchable-vars')) or as an untouchable
 function or macro (in the case of @('temp-touchable-fns')).  These two state
 global variables can be set by @('set-temp-touchable-vars') and
 @('set-temp-touchable-fns'), respectively, provided there is an active trust
 tag (see @(see defttag)).  Here is an illustrative example.  This macro
 executes the indicated forms in a context where there are no untouchable
 variables, but requires an active trust tag when invoked.</p>

 @({
  (defmacro with-all-touchable (&rest forms)
    `(progn!
      :state-global-bindings
      ((temp-touchable-vars t set-temp-touchable-vars))
      (progn! ,@forms)))
 })

 <p>An equivalent version, which however is not recommended since @(tsee
 state-global-let*) may have surprising behavior in raw Lisp, is as
 follows.</p>

 @({
  (defmacro with-all-touchable (&rest forms)
    `(progn!
      (state-global-let*
       ((temp-touchable-vars t set-temp-touchable-vars))
       (progn! ,@forms))))
 })

 <p>Finally, the value @('t') for @('temp-touchable-vars') removes the
 requirement that built-in state globals cannot be made unbound (with
 @('makunbound-global')).</p>

 <p>We now turn to the @('remove-untouchable') event, in case the approach
 above is for some reason not adequate.  This event is illegal by default,
 since it can be used to provide access to ACL2 internal functions and data
 structures that are intentionally made untouchable for the user.  If you want
 to call it, you must first create an active trust tag; see @(see defttag).</p>

 @({
  General Form:
  (remove-untouchable name{s} fn-p)
 })

 <p>where @('name{s}') is a non-@('nil') symbol or a non-@('nil') true list of
 symbols, and @('fn-p') is any value (but generally @('nil') or @('t')).  If
 @('name{s}') is a symbol it is treated as the singleton list containing that
 symbol.  The effect of this event is to remove the given symbols from the list
 of ``untouchable variables'' in the current world if @('fn-p') is @('nil'),
 else to remove the symbols into the list of ``untouchable functions''.  This
 event is redundant if no symbol listed is a member of the appropriate
 untouchables list (variables or functions).</p>")

(defxdoc remove1
  :parents (lists acl2-built-ins)
  :short "Remove first occurrences, testing using @(tsee eql)"
  :long "@({
  General Forms:
  (remove1 x lst)
  (remove1 x lst :test 'eql)   ; same as above (eql as equality test)
  (remove1 x lst :test 'eq)    ; same, but eq is equality test
  (remove1 x lst :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Remove1 x lst)') is equal to @('lst') if @('x') is not a member of
 @('lst'), else is the result of removing the first occurrences of @('x') from
 @('lst').  The optional keyword, @(':TEST'), has no effect logically, but
 provides the test (default @(tsee eql)) used for comparing @('x') with
 successive elements of @('lst').</p>

 <p>Also see @(see remove).</p>

 <p>The @(see guard) for a call of @('remove1') depends on the test.  In all
 cases, the second argument must satisfy @(tsee true-listp).  If the test is
 @(tsee eql), then either the first argument must be suitable for @(tsee eql)
 (see @(see eqlablep)) or the second argument must satisfy @(tsee
 eqlable-listp).  If the test is @(tsee eq), then either the first argument
 must be a symbol or the second argument must satisfy @(tsee symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('remove1') and its variants:</p>

 <blockquote><p>@('(remove1-eq x lst)') is equivalent to @('(remove1 x lst
 :test 'eq)');</p>

 <p>@('(remove1-equal x lst)') is equivalent to @('(remove1 x lst :test
 'equal)').</p></blockquote>

 @(def remove1-equal)

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('remove1-equal').</p>")

(defxdoc reset-fc-reporting
  :parents (forward-chaining-reports)
  :short "Reset the forward-chaining tracking state to its initial configuration"
  :long "@({
  Example:  (reset-fc-reporting)
 })

 <p>This function erases all forward chaining tracking criteria and sets the
 on-the-fly reporting flag to @('nil.')  The next time you set the criteria
 (see @(see set-fc-criteria)) the short form of reports, in which only the
 caller and the fc-report number is printed, will appear in your proof
 logs.</p>

 <p>See @(see forward-chaining-reports) for details.</p>")

(defxdoc reset-kill-ring
  :parents (history)
  :short "Save memory by resetting and perhaps resizing the kill ring used by @(tsee oops)"
  :long "<p>By default, ACL2 holds on to old logical @(see world)s when you
 undo @(see command)s (see @(see ubt)), as documented elsewhere; see @(see
 oops).  You can free up memory by deleting those old worlds using
 @('reset-kill-ring').</p>

 @({
  Examples:
  (reset-kill-ring t state)   ; replace each element of the kill ring by nil
  (reset-kill-ring 2 state)   ; create a new kill ring of '(nil nil)
  (reset-kill-ring 0 state)   ; create a new kill ring that is empty
  (reset-kill-ring nil state) ; just return the length of the kill ring

  General form:
  (reset-kill-ring n state)
 })

 <p>where @('n') evaluates either to @('t'), to @('nil'), or to a nonnegative
 integer (a @(tsee natp)).  If @('n') evaluates to @('t'), it is treated as the
 length of the current kill ring.  If @('n') is @('nil'), then the length
 @('k') of the current kill ring is returned as a value triple @('(mv nil k
 state)').  If @('n') is a @(tsee natp), then the kill ring is replaced with a
 list of @('n') @('nil')s.</p>

 <p>In particular, use @('(reset-kill-ring 0 state)') to avoid saving any old
 logical @(see world)s, at the cost of disabling the effect of the @(tsee oops)
 @(see command).</p>")

(defxdoc reset-ld-specials
  :parents (ld)
  :short "Restores initial settings of the @(tsee ld) specials"
  :long "@({
  Examples:
  (reset-ld-specials t)
  (reset-ld-specials nil)
 })

 <p>Roughly speaking, the @(tsee ld) specials are certain @(see state) global
 variables, such as @(tsee current-package), @(tsee ld-prompt), and @(tsee
 ld-pre-eval-filter), which are managed by @(tsee ld) as though they were local
 variables.  These variables determine the channels on which @(tsee ld) reads
 and prints and control many options of @(tsee ld).  See @(see ld) for the
 details on what the @(tsee ld) specials are.</p>

 <p>This function, @('reset-ld-specials'), takes one Boolean argument,
 @('flg').  The function resets all of the @(tsee ld) specials to their
 initial, top-level values, except for the three channel variables, @(tsee
 standard-oi), @(tsee standard-co), and @(tsee proofs-co), which are reset to
 their initial values only if @('flg') is non-@('nil').  Of course, if you are
 in a recursive call of @(tsee ld), then when you exit that call, the @(tsee
 ld) specials will be restored to the values they had at the time @(tsee ld)
 was called recursively.  To see what the initial values are, inspect the value
 of the constant @('*initial-ld-special-bindings*').</p>")

(defxdoc reset-prehistory
  :parents (history)
  :short "Reset the prehistory"
  :long "@({
  Examples:
  (reset-prehistory)     ; restart command numbering at 0
  (reset-prehistory nil) ; same as above
  (reset-prehistory t)   ; as above except also disable ubt-prehistory

  General Forms:
  (reset-prehistory)
  (reset-prehistory permanent-p)
 })

 <p>where @('permanent-p') is @('t') or @('nil').  After execution of this
 command, ACL2 will change the numbering provided by its @(see history)
 utilities so that this @('reset-prehistory') command (or the top-level
 compound @(see command) containing it, which for example might be an @(tsee
 include-book)) is assigned the number 0.  The only way to undo this command is
 with command @(tsee ubt-prehistory).  However, even that is disallowed if
 @('permanent-p') is @('t').</p>

 <p>Note that the second argument of @(tsee certify-book), which specifies the
 number of commands in the certification world (i.e., since ground-zero), is
 not sensitive to @('reset-prehistory'); rather, it expects the number of
 commands since ground-zero.  To see such commands, @(':')@(tsee pbt)@('
 :start').</p>

 <p>A @('reset-prehistory') event for which parameter @('permanent-p') has the
 default value of @('nil') is always skipped when any of the following
 conditions holds: during @(tsee certify-book); during @(tsee include-book) or
 the second pass of @(tsee encapsulate) (indeed, whenever @(see ld) special
 <tt>'</tt>@(tsee ld-skip-proofsp) has value @(''include-book')); or when
 @('state') global @(''skip-reset-prehistory') has a non-@('nil') value.  Thus,
 we avoid resetting the history numbering to 0 when including or certifying a
 book, since that would probably not be what was intended.</p>

 <p>See @(see ubt-prehistory) for how to undo a @('reset-prehistory') command
 that does not have a @('permanent-p') of @('t').</p>")

(defxdoc resize-list
  :parents (stobj acl2-built-ins)
  :short "List resizer in support of stobjs"
  :long "<p>@('(Resize-list lst n default-value)') takes a list, @('lst'), and
 a desired length, @('n'), for the result list, as well as a @('default-value')
 to use for the extra elements if @('n') is greater than the length of
 @('lst').</p>

 <p>@('Resize-list') has a guard of @('t').  This function is called in the
 body of function, @('resize-<a>') where @('<a>') is an array field of a @(see
 stobj).  See @(see stobj) and see @(see defstobj).</p>

 @(def resize-list)")

(defxdoc rest
  :parents (nth acl2-built-ins)
  :short "Rest (@(tsee cdr)) of the list"
  :long "<p>In the logic, @('rest') is just a macro for @(tsee cdr).</p>

 <p>@('Rest') is a Common Lisp function.  See any Common Lisp documentation for
 more information.</p>

 @(def rest)")

(defxdoc restore-memoization-settings
  :parents (memoize)
  :short "Restore the saved memoization settings"
  :long "<p>For background on memoization, see @(see memoize).</p>

 @({
  General Form:
  (restore-memoization-settings)
 })

 <p>Calls of this macro restore the memoization settings saved by @(tsee
 save-and-clear-memoization-settings).</p>")

(defxdoc retract-world
  :parents (world)
  :short "Install an initial segment (retraction) of a given ACL2 @(see world)"
  :long "<p>See @(see world) for relevant background on ACL2 property list
 worlds.  Here we discuss how to install an initial segment (retraction) of a
 user-defined world, that is, a world other than the one named
 @(''current-acl2-world'), which is maintained by the ACL2 system.  Also see
 @(see retract-world) for a similar utility that instead extends a named
 world.</p>

 @({
 General Form:

 (retract-world name wrld)
 })

 <p>where @('name') is a symbol intended to name the given ACL2 property list
 world, @('world').  Consider the following example.</p>

 @({
 ACL2 !>(let* ((wrld0 nil)
               (wrld1 (putprop 'my-sym1 'my-key1 'my-val1-old wrld0))
               (wrld2 (putprop 'my-sym2 'my-key2 'my-val2 wrld1))
               (wrld3 (putprop 'my-sym1 'my-key1 'my-val1 wrld2)))
          (pprogn (f-put-global 'my-w1 wrld1 state)
                  (f-put-global 'my-w3 (extend-world 'my-world wrld3) state)))
 <state>
 ACL2 !>(retract-world 'my-world (@ my-w1))
 ((MY-SYM1 MY-KEY1 . MY-VAL1-OLD))
 ACL2 !>(getprop 'my-sym1 'my-key1 nil 'my-world (@ my-w1))
 MY-VAL1-OLD
 ACL2 !>
 })

 <p>The first top-level form sets the values of @(tsee state) globals
 @('my-w1') and @('my-w3') to to the worlds obtained by extending the empty
 world one or three times, respectively, as shown.  The second top-level form
 <i>installs</i> the value of @('my-w1') as the world that is current for the
 name @(''my-world').  The third top-level form returns the @(''my-key1')
 property for the symbol @(''my-sym1') in the installed world @('(@ my-w1)'),
 and it does so efficiently because that world is installed.  See @(see
 world).</p>")

(defxdoc retrieve
  :parents (proof-builder)
  :short "Re-enter a (specified) @(see proof-builder) state"
  :long "@({
  Examples:
  (retrieve associativity-of-permutationp)
  retrieve

  General Form:
  (retrieve &optional name)
 })

 <p>See @(see acl2-pc::retrieve), or use @('(help retrieve)') inside the
 interactive @(see proof-builder) loop.  Also see @(see unsave).</p>")

(defxdoc return-last
  :parents (basics acl2-built-ins)
  :short "Return the last argument, perhaps with side effects"
  :long "<p>@('Return-last') is an ACL2 function that returns its last
 argument.  It is used to implement common utilities such as @(tsee prog2$) and
 @(tsee time$).  For most users, this may already be more than one needs to
 know about @('return-last'); for example, ACL2 tends to avoid printing calls
 of @('return-last') in its output, printing calls of @(tsee prog2$) or @(tsee
 time$) (or other such utilities) instead.</p>

 <p>If you encounter a call of @('return-last') during a proof, then you may
 find it most useful to consider @('return-last') simply as a function defined
 by the following equation.</p>

 @({
  (equal (return-last x y z) z)
 })

 <p>It may also be useful to know that unlike other ACL2 functions,
 @('return-last') can take a multiple value as its last argument, in which case
 this multiple value is returned.  The following contrived definition
 illustrates this point.</p>

 @({
  ACL2 !>(defun foo (fn x y z)
           (return-last fn x (mv y z)))

  Since FOO is non-recursive, its admission is trivial.  We observe that
  the type of FOO is described by the theorem
  (AND (CONSP (FOO FN X Y Z)) (TRUE-LISTP (FOO FN X Y Z))).  We used
  primitive type reasoning.

  (FOO * * * *) => (MV * *).

  Summary
  Form:  ( DEFUN FOO ...)
  Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
   FOO
  ACL2 !>(foo 'bar 3 4 5)
  (4 5)
  ACL2 !>(mv-let (a b)
                 (foo 'bar 3 4 5)
                 (cons b a))
  (5 . 4)
  ACL2 !>
 })

 <p>Most readers would be well served to avoid reading the rest of this
 documentation of @('return-last').  For reference, however, below we document
 it in some detail.  We include some discussion of its evaluation, in
 particular its behavior in raw Lisp, because we expect that most who read
 further are working with raw Lisp code (and trust tags).</p>

 <p>@('Return-last') is an ACL2 function that can arise from macroexpansion of
 certain utilities that return their last argument, which may be a multiple
 value.  Consider for example the simplest of these, @(tsee prog2$):</p>

 @({
  ACL2 !>:trans1 (prog2$ (cw \"Some CW printing...~%\") (+ 3 4))
   (RETURN-LAST 'PROGN
                (CW \"Some CW printing...~%\")
                (+ 3 4))
  ACL2 !>
 })

 <p>Notice that a call of @('prog2$') macroexpands to a call of
 @('return-last') in which the first argument is @('(quote progn)').  Although
 @('return-last') is a function in the ACL2 world, it is implemented ``under
 the hood'' as a macro in raw Lisp, as the following log (continuing the
 example above) illustrates.</p>

 @({
  ACL2 !>:q

  Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
  ? (macroexpand-1 '(RETURN-LAST 'PROGN
                                  (CW \"Some CW printing...~%\")
                                  (+ 3 4)))
  (PROGN (LET ((*AOKP* T)) (CW \"Some CW printing...~%\")) (+ 3 4))
  T
  ?
 })

 <p>Thus, the original @('prog2$') call generates a corresponding call of
 @('progn') in raw Lisp, which in turn causes evaluation of each argument and
 returns whatever is returned by evaluation of the last (second) argument.</p>

 <p>Remark for those who use @(tsee defattach).  The binding of @('*aokp*') to
 @('t') is included for the second argument as shown when the first argument is
 of the form @('(QUOTE S)') for @('S') a symbol and the second argument is not
 a symbol or a quoted constant.  This binding allows ACL2 to use attachments in
 the second argument of @('return-last') (hence, in the first argument of
 @(tsee prog2$)), even in contexts such as proofs in which attachments are
 normally not allowed.</p>

 <p>In general, a form @('(return-last (quote F) X Y)') macroexpands to @('(F X
 Y)'), where @('F') is defined in raw Lisp to return its last argument.  The
 case that @('F') is @('progn') is a bit misleading, because it is so simple.
 More commonly, macroexpansion produces a call of a macro defined in raw Lisp
 that may produce side effects.  Consider for example the ACL2 utility @(tsee
 with-guard-checking), which is intended to change the @(see guard)-checking
 mode to the indicated value (see @(see with-guard-checking)).</p>

 @({
  ACL2 !>(with-guard-checking :none (car 3)) ; no guard violation
  NIL
  ACL2 !>:trans1 (with-guard-checking :none (car 3))
   (WITH-GUARD-CHECKING1 (CHK-WITH-GUARD-CHECKING-ARG :NONE)
                         (CAR 3))
  ACL2 !>:trans1 (WITH-GUARD-CHECKING1 (CHK-WITH-GUARD-CHECKING-ARG :NONE)
                                       (CAR 3))
   (RETURN-LAST 'WITH-GUARD-CHECKING1-RAW
                (CHK-WITH-GUARD-CHECKING-ARG :NONE)
                (CAR 3))
  ACL2 !>:q

  Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
  ? [RAW LISP] (macroexpand-1
                '(RETURN-LAST 'WITH-GUARD-CHECKING1-RAW
                               (CHK-WITH-GUARD-CHECKING-ARG :NONE)
                               (CAR 3)))
  (WITH-GUARD-CHECKING1-RAW (CHK-WITH-GUARD-CHECKING-ARG :NONE) (CAR 3))
  T
  ? [RAW LISP] (pprint
                (macroexpand-1
                 '(WITH-GUARD-CHECKING1-RAW
                   (CHK-WITH-GUARD-CHECKING-ARG :NONE)
                   (CAR 3))))

  (LET ((ACL2_GLOBAL_ACL2::GUARD-CHECKING-ON
         (CHK-WITH-GUARD-CHECKING-ARG :NONE)))
    (DECLARE (SPECIAL ACL2_GLOBAL_ACL2::GUARD-CHECKING-ON))
    (CAR 3))
  ? [RAW LISP]
 })

 <p>The above raw Lisp code binds the state global variable
 @('guard-checking-on') to @(':none'), as @('chk-with-guard-checking-arg') is
 just the identity function except for causing a hard error for an illegal
 input.</p>

 <p>The intended use of @('return-last') is that the second argument is
 evaluated first in a normal manner, and then the third argument is evaluated
 in an environment that may depend on the value of the second argument.  (For
 example, the macro @(tsee with-prover-time-limit) macroexpands to a call of
 @('return-last') with a first argument of @(''WITH-PROVER-TIME-LIMIT1-RAW'), a
 second argument that evaluates to a numeric time limit, and a third argument
 that is evaluated in an environment where the theorem prover is restricted to
 avoid running longer than that time limit.)  Although this intended usage
 model is not strictly enforced, it is useful to keep in mind in the following
 description of how calls of @('return-last') are handled by the ACL2
 evaluator.</p>

 <p>When a form is submitted in the top-level loop, it is handled by ACL2's
 custom evaluator.  That evaluator is specified to respect the semantics of the
 expression supplied to it: briefly put, if an expression @('E') evaluates to a
 value @('V'), then the equality @('(equal E (quote V))') should be a theorem.
 Notice that this specification does not discuss the side-effects that may
 occur when evaluating a call of @('return-last'), so we discuss that now.
 Suppose that the ACL2 evaluator encounters the call @('(return-last 'fn expr1
 expr2)').  First it evaluates @('expr1').  If this evaluation succeeds without
 error, then it constructs an expression of the form @('(fn *x* ev-form)'),
 where *x* is a Lisp variable bound to the result of evaluating @('expr1') and
 @('ev-form') is a call of the evaluator for @('expr2').  (Those who want
 implementation details are invited to look at function @('ev-rec-return-last')
 in ACL2 source file @('translate.lisp').)  There are exceptions if @('fn') is
 @('progn'), @('ec-call1-raw'), @('with-guard-checking1-raw'), or
 @('mbe1-raw'), but the main idea is the same: do a reasonable job emulating
 the behavior of a raw-Lisp call of @('return-last').</p>

 <p>The following log shows how a @(tsee time$) call can generate a call of the
 evaluator for the last argument of @('return-last') (argument @('expr2'),
 above).  We use @(':')@(tsee trans1) to show single-step macroexpansions,
 which indicate how a call of @(tsee time$) expands to a call of
 @('return-last').  The implementation actually binds the Lisp variable
 @('*RETURN-LAST-ARG3*') to @('expr2') before calling the ACL2 evaluator,
 @('ev-rec').</p>

 @({
  ACL2 !>:trans1 (time$ (+ 3 4))
   (TIME$1 (LIST 0 NIL NIL NIL NIL)
           (+ 3 4))
  ACL2 !>:trans1 (TIME$1 (LIST 0 NIL NIL NIL NIL)
                         (+ 3 4))
   (RETURN-LAST 'TIME$1-RAW
                (LIST 0 NIL NIL NIL NIL)
                (+ 3 4))
  ACL2 !>(time$ (+ 3 4))
  ; (EV-REC *RETURN-LAST-ARG3* ...) took
  ; 0.00 seconds realtime, 0.00 seconds runtime
  ; (1,120 bytes allocated).
  7
  ACL2 !>
 })

 <p>We now show how things can go wrong in other than the ``intended use'' case
 described above.  In the example below, the macro @('mac-raw') is operating
 directly on the syntactic representation of its first argument, which it
 obtains of course as the second argument of a @('return-last') call.  Again
 this ``intended use'' of @('return-last') requires that argument to be
 evaluated and then only its result is relevant; its syntax is not supposed to
 matter.  We emphasize that only top-level evaluation depends on this
 ``intended use''; once evaluation is passed to Lisp, the issue disappears.  We
 illustrate below how to use the @(tsee top-level) utility to avoid this issue;
 see @(see top-level).  The example uses the utility @('defmacro-last') to
 ``install'' special handling of the raw-Lisp macro @('mac-raw') by
 @('return-last'); later below we discuss @('defmacro-last').</p>

 @({
  ACL2 !>(defttag t)

  TTAG NOTE: Adding ttag :T from the top level loop.
   T
  ACL2 !>(progn!
           (set-raw-mode t)
           (defmacro mac-raw (x y)
             `(progn (print (quote ,(cadr x)))
                     (terpri) ; newline
                     ,y)))

  Summary
  Form:  ( PROGN! (SET-RAW-MODE T) ...)
  Rules: NIL
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
   NIL
  ACL2 !>(defmacro-last mac)
  [[ ... output omitted ... ]]
   RETURN-LAST-TABLE
  ACL2 !>(return-last 'mac-raw '3 nil)

  ***********************************************
  ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
  Error:  Fault during read of memory address #x120000300006
  ***********************************************

  If you didn't cause an explicit interrupt (Control-C),
  then the root cause may be call of a :program mode
  function that has the wrong guard specified, or even no
  guard specified (i.e., an implicit guard of t).
  See :DOC guards.

  To enable breaks into the debugger (also see :DOC acl2-customization):
  (SET-DEBUGGER-ENABLE T)
  ACL2 !>(top-level (return-last 'mac-raw '3 nil))

  3
  NIL
  ACL2 !>
 })

 <p>We next describe how to extend the behavior of @('return-last').  This
 requires an active trust tag (see @(see defttag)), and is accomplished by
 extending a @(see table) provided by ACL2, see @(see return-last-table).
 Rather than using @(tsee table) @(see events) directly for this purpose, it is
 probably more convenient to use a macro, @('defmacro-last').  We describe the
 community book @('books/misc/profiling.lisp') in order to illustrate how this
 works.  The events in that book include the following, which are described
 below.</p>

 @({
  (defttag :profiling)

  (progn!
   (set-raw-mode t)
   (load (concatenate 'string (cbd) \"profiling-raw.lsp\")))

  (defmacro-last with-profiling)
 })

 <p>The first event introduces a trust tag.  The second loads a file into raw
 Lisp that defines a macro, @('with-profiling-raw'), which can do profiling for
 the form to be evaluated.  The third introduces an ACL2 macro
 @('with-profiling'), whose calls expand into calls of the form @('(return-last
 (quote with-profiling-raw) & &)').  The third event also extends @(tsee
 return-last-table) so that these calls will expand in raw Lisp to calls of
 @('with-profiling-raw').</p>

 <p>The example above illustrates the following methodology for introducing a
 macro that returns its last argument but produces useful side-effects with raw
 Lisp code.</p>

 <blockquote><p>(1) Introduce a trust tag (see @(see defttag)).</p>

 <p>(2) Using @(tsee progn!), load into raw Lisp a file defining a macro,
 @('RAW-NAME'), that takes two arguments, returning its last (second) argument
 but using the first argument to produce desired side effects during evaluation
 of that last argument.</p>

 <p>(3) Evaluate the form @('(defmacro-last NAME :raw RAW-NAME)').  This will
 introduce @('NAME') as an ACL2 macro that expands to a corresponding call of
 @('RAW-NAME') (see (2) above) in raw Lisp.  The specification of keyword value
 of @(':raw') as @('RAW-NAME') may be omitted if @('RAW-NAME') is the result of
 modifying the symbol @('NAME') by suffixing the string @('\"-RAW\"') to the
 @(tsee symbol-name) of @('NAME').</p></blockquote>

 <p>WARNING: Not every use of @('return-last') can be soundly evaluated outside
 a function body.  The reason is that ACL2's evaluator, @('ev-rec'), recurs
 through terms that are presented in the top-level loop, and handles
 @('return-last') calls in a special manner: basically, the call of @('ev-rec')
 on the form @('(return-last 'mac-raw x y)') leads to evaluation of a macro
 call of the form @('(mac-raw *return-last-arg2* (ev-rec ...))'), where
 *return-last-arg2* is a global variable bound to the result of evaluating
 @('x') with @('ev-rec').  Consider the following example.</p>

 @({
  (defttag t)
  (set-raw-mode-on state)
  (defmacro mac-raw (str y) ; print message is an atom
   `(let ((result (consp ,y))
          (str ,str))
      (or result
          (prog2$ (fmx ,str ',y)
                  nil))))
  (set-raw-mode-off state)
  (defmacro-last mac)
  ; Horrible error:
  (mac \"Not a cons: ~x0~%\" 17)
  ; Works, but probably many would consider it awkward to use top-level:
  (top-level (mac \"Not a cons: ~x0~%\" 17))
 })

 <p>In such cases we suggest supplying keyword @(':top-level-ok nil') to the
 call of @('defmacro-last'), for example:</p>

 @({
  (defmacro-last mac :top-level-ok nil)
 })

 <p>Then any attempt to call @('mac') at the top level, as opposed to inside a
 function body, will cause a clean error before evaluation begins.</p>

 <p>It is useful to explore what is done by @('defmacro-last').</p>

 @({
  ACL2 !>:trans1 (defmacro-last with-profiling)
   (PROGN (DEFMACRO WITH-PROFILING (X Y)
                    (LIST 'RETURN-LAST
                          (LIST 'QUOTE 'WITH-PROFILING-RAW)
                          X Y))
          (TABLE RETURN-LAST-TABLE 'WITH-PROFILING-RAW
                 'WITH-PROFILING))
  ACL2 !>:trans1 (with-profiling '(assoc-eq fgetprop rewrite) (mini-proveall))
   (RETURN-LAST 'WITH-PROFILING-RAW
                '(ASSOC-EQ FGETPROP REWRITE)
                (MINI-PROVEALL))
  ACL2 !>:q

  Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
  ? [RAW LISP] (macroexpand-1
                '(RETURN-LAST 'WITH-PROFILING-RAW
                               '(ASSOC-EQ FGETPROP REWRITE)
                               (MINI-PROVEALL)))
  (WITH-PROFILING-RAW '(ASSOC-EQ FGETPROP REWRITE) (MINI-PROVEALL))
  T
  ? [RAW LISP]
 })

 <p>To understand the macro @('with-profiling-raw') you could look at the
 community book loaded above: @('books/misc/profiling-raw.lsp').</p>

 <p>We mentioned above that ACL2 tends to print calls of @(tsee prog2$) or
 @(tsee time$) (or other such utilities) instead of calls of @('return-last').
 Here we elaborate that point.  ACL2's `@('untranslate')' utility treats
 @('(return-last (quote F) X Y)') as @('(G X Y)') if @('F') corresponds to the
 symbol @('G') in @('return-last-table').  However, it is generally rare to
 encounter such a term during a proof, since calls of @('return-last') are
 generally expanded away early during a proof.</p>

 <p>Calls of @('return-last') that occur in code &mdash; forms submitted in the
 top-level ACL2 loop, and definition bodies other than those marked as @(tsee
 non-executable) (see @(see defun-nx)) &mdash; have the following restriction:
 if the first argument is of the form @('(quote F)'), then @('F') must be an
 entry in @('return-last-table').  There are however four exceptions: the
 following symbols are considered to be keys of @('return-last-table') even if
 they are no longer associated with non-@('nil') values, say because of a
 @(tsee table) event with keyword @(':clear').</p>

 <blockquote><p>* @('progn'), associated with @(tsee prog2$)<br></br>

 * @('mbe1-raw'), associated with @('mbe1'), a version of @('mbe')<br></br>

 * @('ec-call1-raw'), associated with @('ec-call1') (a variant of @(tsee
 ec-call))<br></br>

 * @('with-guard-checking1-raw'), associated with @('with-guard-checking1') (a
 variant of @(tsee with-guard-checking))</p></blockquote>

 <p>Note that because of its special status, it is illegal to trace
 @('return-last').</p>

 <p>We conclude by warning that as a user, you take responsibility for not
 compromising the soundness or error handling of ACL2 when you define a macro
 in raw Lisp and especially when you install it as a key of @(tsee
 return-last-table), either directly or (more likely) using @('defmacro-last').
 In particular, be sure that you are defining a macro of two arguments that
 always returns the value of its last argument, returning the complete multiple
 value if that last argument evaluates to a multiple value.</p>

 <p>The following is correct, and illustrates care taken to return multiple
 values.</p>

 @({
  :q
  (defmacro my-time1-raw (val form)
    (declare (ignore val))
    `(let  ((start-time (get-internal-run-time))
            (result (multiple-value-list ,form))
            (end-time (get-internal-run-time)))
       (format t \"Total time: ~s~%\"
               (float (/ (- end-time start-time)
                         internal-time-units-per-second)))
       (values-list result)))
  (lp)
  (defttag t)
  (defmacro-last my-time1)
  (defmacro my-time (form)
    `(my-time1 nil ,form))
 })

 <p>Then for example:</p>

 @({
  ACL2 !>(my-time (equal (make-list 1000000) (make-list 1000000)))
  Total time: 0.12
  T
  ACL2 !>
 })

 <p>But if instead we provide the following more naive implementation, of the
 above raw Lisp macro, the above evaluation can produce an error, for example
 if the host Lisp is CCL.</p>

 @({
  (defmacro my-time1-raw (val form)
      (declare (ignore val))
      `(let  ((start-time (get-internal-run-time))
              (result ,form)
              (end-time (get-internal-run-time)))
         (format t \"Total time: ~s~%\"
                 (float (/ (- end-time start-time)
                           internal-time-units-per-second)))
         result)) ; WRONG -- need multiple values returned!
 })

 <p>Here is a second, similar example.  This time we'll start with the error;
 can you spot it?</p>

 @({
  (defttag t)
  (progn!
   (set-raw-mode t)
   (defmacro foo-raw (x y)
     `(prog1
          ,y
        (cw \"Message showing argument 1: ~x0~%\" ,x))))
  (defmacro-last foo)
 })

 <p>We then can wind up with a hard Lisp error:</p>

 @({
  ACL2 !>(foo 3 (mv 4 5))
  Message showing argument 1: 3

  ***********************************************
  ************ ABORTING from raw Lisp ***********
  ********** (see :DOC raw-lisp-error) **********
  Error:  value NIL is not of the expected type REAL.
  ***********************************************

  If you didn't cause an explicit interrupt (Control-C),
  then the root cause may be call of a :program mode
  function that has the wrong guard specified, or even no
  guard specified (i.e., an implicit guard of t).
  See :DOC guards.

  To enable breaks into the debugger (also see :DOC acl2-customization):
  (SET-DEBUGGER-ENABLE T)
  ACL2 !>
 })

 <p>Here is a corrected version of the above macro.  The point here is that
 @('prog1') returns a single value, while @('our-multiple-value-prog1') returns
 all the values that are returned by its first argument.</p>

 @({
  (progn!
   (set-raw-mode t)
   (defmacro foo-raw (x y)
     `(our-multiple-value-prog1 ;; better
       ,y
       (cw \"Message showing argument 1: ~x0~%\" ,x))))
 })

 @(def return-last)")

(defxdoc return-last-table
  :parents (return-last)
  :short "Install special raw Lisp behavior"
  :long "<p>Please first see @(see return-last) for relevant background.</p>

 <p>This @(see table) is for advanced users only, and requires an active trust
 tag (see @(see defttag)).  We recommend that you do not modify this table
 directly, but instead use the macro @('defmacro-last').  Here we augment that
 discussion with some highly technical observations that can probably be
 ignored if you use @('defmacro-last').</p>

 <p>This @(see table) has a @(':guard') requiring that each key be a symbol
 defined in raw Lisp, generally as a macro, and requiring that each
 non-@('nil') value be associated either with a symbol that names a macro
 defined in ACL2, or else with a list of one element containing such a symbol.
 The table can only be modified when there is an active trust tag; see @(see
 defttag).  If a key is associated with the value @('nil'), then that key is
 treated as though it were not in the table.</p>

 <p>Note that keys of this table are not eligible to be bound by @(tsee flet).
 The current value of this table may be obtained by evaluating the form
 @('(table-alist 'return-last-table (w state))').  The built-in constant
 @('*initial-return-last-table*') holds the initial value of this table.</p>")

(defxdoc revappend
  :parents (lists acl2-built-ins)
  :short "Concatenate the @(see reverse) of one list to another"
  :long "<p>@('(Revappend x y)') @(see concatenate)s the @(see reverse) of the
 list @('x') to @('y'), which is also typically a list.</p>

 <p>The following theorem characterizes this English description.</p>

 @({
  (equal (revappend x y)
         (append (reverse x) y))
 })

 <p>Hint: This lemma follows immediately from the definition of @(tsee reverse)
 and the following lemma.</p>

 @({
  (defthm revappend-append
    (equal (append (revappend x y) z)
           (revappend x (append y z))))
 })

 <p>The @(see guard) for @('(revappend x y)') requires that @('x') is a true
 list.</p>

 <p>@('Revappend') is defined in Common Lisp.  See any Common Lisp
 documentation for more information.</p>

 @(def revappend)")

(defxdoc reverse
  :parents (lists strings acl2-built-ins)
  :short "Reverse a list or string"
  :long "<p>@('(Reverse x)') is the result of reversing the order of the
 elements of the list or string @('x').</p>

 <p>The @(see guard) for @('reverse') requires that its argument is a true list
 or a string.</p>

 <p>@('Reverse') is defined in Common Lisp.  See any Common Lisp documentation
 for more information.</p>

 @(def reverse)")

(defxdoc revert-world
  :parents (programming)
  :short "Evaluate without (ultimately) changing the @(see world)"
  :long "@({
 General Form:
 (revert-world form)
 })

 <p>where @('form') evaluates to an @(see error-triple).</p>

 <p>Evaluation of @('(revert-world form) returns the same result, @('(mv erp
 val state)'), as the given @('form'), except that the @(see world) of the
 returned @(tsee state) is the same as the world of the input state even if the
 evaluation of @('form') modifies the world of the input state.</p>

 <p>To see @('revert-world') in action, consider the following defintion.</p>

 @({
 (defun test-revert-world (state)
  (declare (xargs :mode :program :stobjs state))
  (er-progn
   (value (cw \"Length of (w state) before defun: ~x0~%\"
              (length (w state))))
   (revert-world (er-progn
                  (trans-eval '(with-output :off :all ; avoid output ;
                                 (defun foo (x) x))
                              'my-ctx state nil)
                  (value (cw \"Length of (w state) after defun: ~x0~%\"
                             (length (w state))))))
   (value (cw \"Length of (w state) after revert-world: ~x0~%\"
              (length (w state))))))
 })

 <p>Here is a log produced after admitting the definition above in a fresh
 session (for an ACL2 build circa November 2017).  It shows that the definition
 lengthens the world, but that the world's length is back to its initial value
 after we return from @('revert-world').</p>

 @({
 ACL2 !>(test-revert-world state)
 Length of (w state) before defun: 107133
 Length of (w state) after defun: 107153
 Length of (w state) after revert-world: 107133
  NIL
 ACL2 !>:pbt 0
            0  (EXIT-BOOT-STRAP-MODE)
  P         1:x(DEFUN TEST-REVERT-WORLD (STATE) ...)
 ACL2 !>
 })

 <p>The macroexpansion of @('(revert-world form)') contains a call of a @(see
 program)-mode function.  It is thus illegal to call @('revert-world') in the
 body of a @(see logic)-mode function.  Contact the ACL2 implementors if you
 want them to consider working to lift this restriction.</p>")

(defxdoc rewrite
  :parents (rule-classes)
  :short "Make some @(':rewrite') rules (possibly conditional ones)"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 <p>This doc topic discusses the rule-class @(':rewrite').  If you want a
 general discussion of how rewriting works in ACL2 and some guidance on how to
 construct effective rewrite rules, see @(see
 introduction-to-rewrite-rules-part-1) and then see @(see
 introduction-to-rewrite-rules-part-2).</p>

 @({
  Examples:

  (defthm plus-commutes                 ; Replace (+ a b) by (+ b a) provided
    (equal (+ x y) (+ y x)))            ; certain heuristics approve the
                                        ; permutation.

  (defthm plus-commutes                 ; equivalent to the above
    (equal (+ x y) (+ y x))
    :rule-classes ((:rewrite :corollary (equal (+ x y) (+ y x))
                             :loop-stopper ((x y binary-+))
                             :match-free :all)))

  (defthm append-nil                    ; Replace (append a nil) by a, if
    (implies (true-listp x)             ; (true-listp a) rewrites to t.
             (equal (append x nil) x)))

  (defthm append-nil                    ; as above, but with defaults and
    (implies (true-listp x)             ; a backchain limit
             (equal (append x nil) x))
    :rule-classes ((:rewrite :corollary (implies (true-listp x)
                                                 (equal (append x nil) x))
                             :backchain-limit-lst (3) ; or equivalently, 3
                             :match-free :all)))

  (defthm member-append                 ; Replace (member e (append b c)) by
    (implies                            ; (or (member e b) (member e c) in
     (and                               ; contexts in which propositional
      (true-listp x)                    ; equivalence is sufficient, provided
      (true-listp y))                   ; b and c are true-lists.
     (iff (member e (append x y))
          (or (member e x) (member e y)))))

  General Form:
  (and ...
       (implies (and ...hi...)
                (implies (and ...hk...)
                         (and ...
                              (equiv lhs rhs)
                              ...)))
       ...)
 })

 <p>Note: One @(':rewrite') rule class object might create many rewrite rules
 from the @(':')@(tsee corollary) formula.  To create the rules, we first
 translate the formula, expanding all macros (see @(see trans)) and also
 removing @(see guard-holders).  Next, we eliminate all @('lambda')s; one may
 think of this step as simply substituting away every @(tsee let), @(tsee
 let*), and @(tsee mv-let) in the formula.  We then flatten the @(tsee AND) and
 @(tsee IMPLIES) structure of the formula; for example, if the hypothesis or
 conclusion is of the form @('(and (and term1 term2) term3)'), then we replace
 that by the ``flat'' term @('(and term1 term2 term3)').  (The latter is
 actually an abbreviation for the right-associated term @('(and term1 (and
 term2 term3))').)  The result is a conjunction of formulas, each of the
 form</p>

 @({
  (implies (and h1 ... hn) concl)
 })

 <p>where no hypothesis is a conjunction and @('concl') is neither a
 conjunction nor an implication.  If necessary, the hypothesis of such a
 conjunct may be vacuous.  We then further coerce each @('concl') into the form
 @('(equiv lhs rhs)'), where @('equiv') is a known @(see equivalence) relation,
 by replacing any @('concl') not of that form by @('(iff concl t)').  A
 @('concl') of the form @('(not term)') is considered to be of the form @('(iff
 term nil)').  By these steps we reduce the given @(':')@(tsee corollary) to a
 sequence of conjuncts, each of which is of the form</p>

 @({
  (implies (and h1 ... hn)
           (equiv lhs rhs))
 })

 <p>where @('equiv') is a known @(see equivalence) relation.  See @(see
 equivalence) for a general discussion of the introduction of new @(see
 equivalence) relations.  At this point, we check whether @('lhs') and @('rhs')
 are the same term; if so, we cause an error, since this rule will loop.  (But
 this is just a basic check; the rule could loop in other cases, for example if
 @('rhs') is an instance of @('lhs'); see @(see loop-stopper).)</p>

 <p>We create a @(':rewrite') rule for each such conjunct, if possible, and
 otherwise cause an error.  It is possible to create a rewrite rule from such a
 conjunct provided @('lhs') is not a variable, a quoted constant, a @(tsee
 let)-expression, or a @('lambda') application.  Although it is legal to create
 a rewrite rule from an @(tsee if)-expression @('(if tst tbr fbr)'), note that
 the rewriter uses the truth or falsity of the test, @('tst'), when rewriting
 the true and false branches @('tbr') and @('fbr'), respectively; so rewrite
 rules are most often unnecessary for @('if')-expressions.</p>

 <p>A @(':rewrite') rule is used when any instance of the @('lhs') occurs in a
 context in which the @(see equivalence) relation is an admissible @(see
 congruence) relation.  First, we find a substitution that makes @('lhs') equal
 to the target term.  Then we attempt to relieve the instantiated hypotheses of
 the rule.  Hypotheses that are fully instantiated are relieved by recursive
 rewriting.  Hypotheses that contain ``free variables'' (variables not assigned
 by the unifying substitution) are relieved by attempting to guess a suitable
 instance so as to make the hypothesis equal to some known assumption in the
 context of the target.  If the hypotheses are relieved, and certain
 restrictions that prevent some forms of infinite regress are met (see @(see
 loop-stopper)), the target is replaced by the instantiated @('rhs'), which is
 then recursively rewritten.</p>

 <p>ACL2's rewriting process has some optimizations, including the
 following.</p>

 <ul>

 <li>The notion of ``a substitution that makes @('lhs') equal to the target
 term'' is a bit more generous than the most straightforward such notion.
 Suppose for example that @('lhs') is @('(f (+ 3 x))') and the target term is
 @('(f (+ 3 (g y))').  (Aside: ACL2 deals in so-called translated terms, so
 since @('+') is a macro, @('lhs') and term would actually be @('(f (binary-+
 '3 x))') and @('(f (+ '3 (g y)))'); we will ignore this distinction, but if
 you want more information, see @(see term).)  Then of course, that
 substitution binds @('x') to @('(g y)').  But now suppose that instead the
 target term is @('(f 10)').  You may be surprised to learn that the
 substitution binding @('x') to @('7') makes @('(f (+ 3 x))') equal to @('(f
 10)'); for example, the rewrite rule @('(equal (f (+ x 3)) (h x)))') would
 rewrite @('(f 10)') to @('(h 7)').  This would also be the case if @('lhs')
 were instead @('(f (+ x 3))').  This sort of optimization occurs when the new
 constant has @(tsee acl2-count) no greater than the old constant.  There are
 similar optimizations for @('*'), @('/'), @('-'), strings, symbols, and
 conses (for details see ACL2 source function
 @('one-way-unify1-quotep-subproblems')).</li>

 <li>When a term @('t1') is rewritten to a new term @('t2'), the rewriter is
 then immediately applied to @('t2').  On rare occasions you may find that you
 do not want this behavior, in which case you may wish to use a trick involving
 @(tsee hide); see @(see meta), near the end of that documentation.</li>

 <li>When the hypotheses and right-hand side are rewritten, ACL2 does not
 really first apply the substitution and then rewrite; instead, it as it
 rewrites those terms it looks up the <i>already rewritten</i> values of the
 bound variables.  Sometimes you may want those bindings rewritten again, e.g.,
 because the variables occur in slots that admit additional equivalence
 relations.  See <i>double-rewrite</i>.</li>

 </ul>

 <p>See @(see introduction-to-rewrite-rules-part-1) and see @(see
 introduction-to-rewrite-rules-part-2) for an extended discussion of how to
 create effective rewrite rules.</p>")

(defxdoc rewrite-stack-limit
  :parents (rewrite)
  :short "Limiting the stack depth of the ACL2 rewriter"
  :long "<p>ACL2 users can create rules of class @(':')@(tsee rewrite) (see
 @(see rule-classes)) that have the potential of causing an infinite loop in
 the ACL2 rewriter.  This could lead to Lisp stack overflows and even
 segmentation faults.  For this reason, the depth of certain calls of functions
 in the ACL2 rewriter is limited by default using the value of the form
 @('(rewrite-stack-limit (w state))').  To see the limit in action, execute the
 following forms.</p>

 @({
  (defthm app-assoc-1
    (equal (append (append x y) z)
           (append x y z)))
  (defthm app-assoc-2
    (equal (append x y z)
           (append (append x y) z)))
  (thm (equal (append a b c) xxx)
       ; try without these hints to see a slightly different error message
       :hints ((\"Goal\" :do-not '(preprocess))))
 })

 <p>The ensuing error message shows a stack of one greater than the value of
 @('(rewrite-stack-limit (w state))'), which by default is the value of the
 constant @('*default-rewrite-stack-limit*').  The error message also explains
 how to use @(':')@(tsee brr)@(' t') and @('(')@(tsee cw-gstack)@(')') to find
 looping rewrite rules.</p>

 <p>This limit can be changed; see @(see set-rewrite-stack-limit).</p>

 <p>For a related limit, see @(see backchain-limit).</p>")

(defxdoc rfix
  :parents (numbers acl2-built-ins)
  :short "Coerce to a rational number"
  :long "<p>@('Rfix') simply returns any rational number argument unchanged,
 returning @('0') on a non-rational argument.  Also see @(see nfix), see @(see
 ifix), see @(see realfix), and see @(see fix) for analogous functions that
 coerce to a natural number, an integer, a real, and a number,
 respectively.</p>

 <p>@('Rfix') has a @(see guard) of @('t').</p>

 @(def rfix)")

(defxdoc round
  :parents (numbers acl2-built-ins)
  :short "Division returning an integer by rounding off"
  :long "@({
  Example Forms:
  ACL2 !>(round 14 3)
  5
  ACL2 !>(round -14 3)
  -5
  ACL2 !>(round 14 -3)
  -5
  ACL2 !>(round -14 -3)
  5
  ACL2 !>(round 13 3)
  4
  ACL2 !>(round -13 3)
  -4
  ACL2 !>(round 13 -3)
  -4
  ACL2 !>(round -13 -3)
  4
  ACL2 !>(round -15 -3)
  5
  ACL2 !>(round 15 -2)
  -8
 })

 <p>@('(Round i j)') is the result of taking the quotient of @('i') and @('j')
 and rounding off to the nearest integer.  When the quotient is exactly halfway
 between consecutive integers, it rounds to the even one.</p>

 <p>The @(see guard) for @('(round i j)') requires that @('i') and @('j') are
 rational (@(see real), in ACL2(r)) numbers and @('j') is non-zero.</p>

 <p>@('Round') is a Common Lisp function.  See any Common Lisp documentation
 for more information.  However, note that unlike Common Lisp, the ACL2
 @('round') function returns only a single value,</p>

 @(def round)")

(defxdoc rule-classes
  :parents (acl2)
  :short "Adding rules to the database"
  :long "@({
  Example Form (from community book finite-set-theory/total-ordering.lisp):
  (defthm <<-trichotomy
    (implies (and (ordinaryp x)
                  (ordinaryp y))
             (or (<< x y)
                 (equal x y)
                 (<< y x)))
    :rule-classes
    ((:rewrite :corollary
               (implies (and (ordinaryp x)
                             (ordinaryp y)
                             (not (<< x y))
                             (not (equal x y)))
                        (<< y x)))))

  General Form:
  a true list of rule class objects as defined below

  Special Cases:
  a symbol abbreviating a single rule class object
 })

 <p>When @(tsee defthm) is used to prove a named theorem, rules may be derived
 from the proved formula and stored in the database.  The user specifies which
 kinds of rules are to be built, by providing a list of rule class <i>names</i>
 or, more generally, rule class <i>objects</i>, which name the kind of rule to
 build and optionally specify various attributes of the desired rule.  The rule
 class names are @(':')@(tsee REWRITE), @(':')@(tsee BUILT-IN-CLAUSE),
 @(':')@(tsee CLAUSE-PROCESSOR), @(':')@(tsee COMPOUND-RECOGNIZER),
 @(':')@(tsee CONGRUENCE), @(':')@(tsee DEFINITION), @(':')@(tsee ELIM),
 @(':')@(tsee EQUIVALENCE), @(':')@(tsee FORWARD-CHAINING), @(':')@(tsee
 GENERALIZE), @(':')@(tsee INDUCTION), @(':')@(tsee LINEAR), @(':')@(tsee
 META), @(':')@(tsee REFINEMENT), @(':')@(tsee TAU-SYSTEM), @(':')@(tsee
 TYPE-PRESCRIPTION), @(':')@(tsee TYPE-SET-INVERTER), and
 @(':WELL-FOUNDED-RELATION').  Some classes <i>require</i> the
 user-specification of certain class-specific attributes.  Each class of rule
 affects the theorem prover's behavior in a different way, as discussed in the
 corresponding documentation topic.  In this topic we discuss the various
 attributes that may be attached to rule classes.</p>

 <p>Note that not all @(see events) generate rules.  For example, a @(tsee
 defthm) event that specifies @(':rule-classes nil') does not generate a rule.
 Similarly, a @(tsee defchoose) event generates an axiom that can be referenced
 by name in @(':use') @(see hints), but it does not generate a rule.</p>

 <p>A rule class object is either one of the @(':class') keywords or else is a
 list of the form shown below.  Those fields marked with ``(!)''  are required
 when the @(':class') is as indicated.</p>

 @({
  (:class
    :COROLLARY term
    :TRIGGER-FNS (fn1 ... fnk)   ; provided :class = :META (!)
    :WELL-FORMEDNESS-GUARANTEE x ; provided :class = :META
                                         or :class = :CLAUSE-PROCESSOR
    :TRIGGER-TERMS (t1 ... tk)   ; provided :class = :FORWARD-CHAINING
                                 ;       or :class = :LINEAR
    :TYPE-SET n                  ; provided :class = :TYPE-SET-INVERTER
    :TYPED-TERM term             ; provided :class = :TYPE-PRESCRIPTION
    :CLIQUE (fn1 ... fnk)        ; provided :class = :DEFINITION
    :CONTROLLER-ALIST alist      ; provided :class = :DEFINITION
    :INSTALL-BODY directive      ; provided :class = :DEFINITION
    :LOOP-STOPPER alist          ; provided :class = :REWRITE
    :PATTERN term                ; provided :class = :INDUCTION (!)
    :CONDITION term              ; provided :class = :INDUCTION
    :SCHEME term                 ; provided :class = :INDUCTION (!)
    :MATCH-FREE all-or-once      ; provided :class = :REWRITE
                                 ;       or :class = :LINEAR
                                 ;       or :class = :FORWARD-CHAINING
    :BACKCHAIN-LIMIT-LST limit   ; provided :class = :REWRITE
                                 ;       or :class = :META
                                 ;       or :class = :LINEAR
                                 ;       or :class = :TYPE-PRESCRIPTION
    :HINTS hints                 ; provided instrs = nil
    :INSTRUCTIONS instrs         ; provided  hints = nil
    :OTF-FLG flg)
 })

 <p>When rule class objects are provided by the user, most of the fields are
 optional and their values are computed in a context sensitive way.  When a
 @(':class') keyword is used as a rule class object, all relevant fields are
 determined contextually.  Each rule class object in @(':rule-classes') causes
 one or more rules to be added to the database.  The @(':class') keywords are
 documented individually under the following names.  Note that when one of
 these names is used as a @(':class'), it is expected to be in the keyword
 package (i.e., the names below should be preceded by a colon but the ACL2
 @(see documentation) facilities do not permit us to use keywords below).</p>

 <p>See also @(tsee force), @(see case-split), @(tsee syntaxp), and @(tsee
 bind-free) for ``pragmas'' one can wrap around individual hypotheses of
 certain classes of rules to affect how the hypothesis is relieved.</p>

 <p>Before we get into the discussion of rule classes, let us return to an
 important point.  In spite of the large variety of rule classes available, at
 present we recommend that new ACL2 users rely almost exclusively on
 (conditional) rewrite rules.  A reasonable but slightly bolder approach is to
 use @(':')@(tsee type-prescription) and @(':')@(tsee forward-chaining) rules
 for ``type-theoretic'' rules, especially ones whose top-level function symbol
 is a common one like @(tsee true-listp) or @(tsee consp); see @(see
 type-prescription) and see @(see forward-chaining).  However, the rest of the
 rule classes are really not intended for widespread use, but rather are mainly
 for experts.</p>

 <p>We expect that we will write more about the question of which kind of rule
 to use.  For now: when in doubt, use a @(':')@(tsee rewrite) rule.</p>

 <p>@(':Rule-classes') is an optional keyword argument of the @(tsee defthm)
 (and @(tsee defaxiom)) event.  In the following, let @('name') be the name of
 the event and let @('thm') be the formula to be proved or added as an
 axiom.</p>

 <p>If @(':rule-classes') is not specified in a @(tsee defthm) (or @(tsee
 defaxiom)) event, it is as though what was specified was to make one or more
 @(':')@(tsee rewrite) rules, i.e., as though @(':rule-classes')
 @('((:rewrite))') had been used.  Use @(':rule-classes') @('nil') to specify
 that no rules are to be generated.</p>

 <p>If @(':rule-classes') class is specified, where class is a non-@('nil')
 symbol, it is as though @(':rule-classes') @('((class))') had been used.
 Thus, @(':rule-classes') @(':')@(tsee forward-chaining) is equivalent to
 @(':rule-classes') @('((:forward-chaining))').</p>

 <p>We therefore now consider @(':rule-classes') as a true list.  If any
 element of that list is a keyword, replace it by the singleton list containing
 that keyword.  Thus, @(':rule-classes') @('(:rewrite :elim)') is the same as
 @(':rule-classes') @('((:rewrite) (:elim))').</p>

 <p>Each element of the expanded value of @(':rule-classes') must be a true
 list whose @(tsee car) is one of the rule class keyword tokens listed above,
 e.g., @(':')@(tsee rewrite), @(':')@(tsee elim), etc., and whose @(tsee cdr)
 is a ``keyword alist'' alternately listing keywords and values.  The keywords
 in this alist must be taken from those shown below.  They may be listed in any
 order and most may be omitted, as specified below.</p>

 <blockquote>

 <p>@(':')@(tsee Corollary) &mdash; its value, @('term'), must be a term.  If
 omitted, this field defaults to @('thm').  The @(':')@(tsee corollary) of a
 rule class object is the formula actually used to justify the rule created and
 thus determines the form of the rule.  Nqthm provided no similar capability:
 each rule was determined by @('thm'), the theorem or axiom added.  ACL2
 permits @('thm') to be stated ``elegantly'' and then allows the @(':')@(tsee
 corollary) of a rule class object to specify how that elegant statement is to
 be interpreted as a rule.  For the rule class object to be well-formed, its
 (defaulted) @(':')@(tsee corollary), @('term'), must follow from @('thm').
 Unless @('term') follows trivially from @('thm') using little more than
 propositional logic, the formula @('(implies thm term)') is submitted to the
 theorem prover and the proof attempt must be successful.  During that proof
 attempt the values of @(':')@(tsee hints), @(':')@(tsee instructions), and
 @(':')@(tsee otf-flg), as provided in the rule class object, are provided as
 arguments to the prover.  Such auxiliary proofs give the sort of output that
 one expects from the prover.  However, as noted above, corollaries that follow
 trivially are not submitted to the prover; thus, such corollaries cause no
 prover output.  Note that no rule is stored for the theorem until all
 corollaries have been proved.</p>

 <p>Note that before @('term') is stored, all calls of macros in it are
 expanded away.  See @(see trans).</p>

 <p>@(':')@(tsee Hints), @(':')@(tsee instructions), @(':')@(tsee otf-flg)
 &mdash; the values of these fields must satisfy the same restrictions placed
 on the fields of the same names in @(tsee defthm).  These values are passed to
 the recursive call of the prover used to establish that the @(':')@(tsee
 corollary) of the rule class object follows from the theorem or axiom
 @('thm').</p>

 <p>@(':')@(tsee Type-set) &mdash; this field may be supplied only if the
 @(':class') is @(':')@(tsee type-set-inverter).  When provided, the value must
 be a type-set, an integer in a certain range.  If not provided, an attempt is
 made to compute it from the corollary.  See @(see type-set-inverter).</p>

 <p>@(':Typed-term') &mdash; this field may be supplied only if the @(':class')
 is @(':')@(tsee type-prescription).  When provided, the value is the term for
 which the @(':')@(tsee corollary) is a type-prescription lemma.  If no
 @(':typed-term') is provided in a @(':')@(tsee type-prescription) rule class
 object, we try to compute heuristically an acceptable term.  See @(see
 type-prescription).</p>

 <p>@(':Trigger-terms') &mdash; this field may be supplied only if the
 @(':class') is @(':')@(tsee forward-chaining) or @(':')@(tsee linear).  When
 provided, the value is a list of terms, each of which is to trigger the
 attempted application of the rule.  If no @(':trigger-terms') is provided, we
 attempt to compute heuristically an appropriate set of triggers.  See @(see
 forward-chaining) or see @(see linear).</p>

 <p>@(':Trigger-fns') &mdash; this field must (and may only) be supplied if the
 @(':class') is @(':')@(tsee meta).  Its value must be a list of function
 symbols (except that a macro alias can stand in for a function symbol; see
 @(see add-macro-alias)).  Terms with these symbols trigger the application of
 the rule.  See @(see meta).</p>

 <p>@(':Well-formedness-guarantee') &mdash; this field may be supplied only if
 the @(':class') is @(':')@(tsee meta) or @(':')@(tsee clause-processor).  Its
 value must be of one of the following forms:</p>

 @({
  [1]  thm-name1                ; :META or :CLAUSE-PROCESSOR rules
  [2]  (thm-name1)              ; :META rules
  [3]  (thm-name1 thm-name2)    ; :META rules
 })

 <p>where @('thm-name1') and @('thm-name2') are the names of previously proved
 theorems establishing that the results of applying the metafunction(s) or
 clause-processor will be syntactically well-formed.  See @(':')@(see meta) and
 @(':')@(see clause-processor) for details of the required forms of these
 well-formedness theorems.  Forms [1] and [2] may be used for @(':meta') rules
 where no hypothesis metafunction is involved.  Form [3] must be used for
 @(':meta') rules with hypothesis metafunctions; that is, if you provide a
 well-formedness guarantee for a metatheorem with a hypothesis metafunction you
 must guarantee the well-formedness of both the metafunction (with
 @('thm-name1')) and the hypothesis metafunction (with @('thm-name2')).  Form
 [1] must be used for @(':clause-processor') rules.  In the absence of a proper
 @(':well-formedness-guarantee') the well-formedness of the output of a both
 kinds of rules is checked every time the rule is fired.  These checks are
 skipped when a proper @(':well-formedness-guarantee') is provided or when
 overridden as described in @(tsee set-skip-meta-termp-checks).</p>

 <p>@(':Clique') and @(':controller-alist') &mdash; these two fields may only
 be supplied if the @(':class') is @(':')@(tsee definition).  If they are
 omitted, then ACL2 will attempt to guess them.  Suppose the @(':')@(tsee
 corollary) of the rule is @('(implies hyp (equiv (fn a1 ... an) body))').  The
 value of the @(':clique') field should be a true list of function symbols, and
 if non-@('nil') must include @('fn').  These symbols are all the members of
 the mutually recursive clique containing this definition of @('fn').  That is,
 a call of any function in @(':clique') is considered a ``recursive call'' for
 purposes of the expansion heuristics.  The value of the @(':controller-alist')
 field should be an alist that maps each function symbol in the @(':clique') to
 a list of @('t')'s and @('nil')'s of length equal to the arity of the
 function.  For example, if @(':clique') consists of just two symbols, @('fn1')
 and @('fn2'), of arities @('2') and @('3') respectively, then @('((fn1 t nil)
 (fn2 nil t t))') is a legal value of @(':controller-alist').  The value
 associated with a function symbol in this alist is a ``mask'' specifying which
 argument slots of the function ``control'' the recursion for heuristic
 purposes.  Sloppy choice of @(':clique') or @(':controller-alist') can result
 in infinite expansion and stack overflow.</p>

 <p>@(':Install-body') &mdash; this field may only be supplied if the
 @(':class') is @(':')@(tsee definition).  Its value must be @('t'), @('nil'),
 or the default, @(':normalize').  A value of @('t') or @(':normalize') will
 cause ACL2 to install this rule as the new body of the function being
 ``defined'' (@('fn') in the paragraph just above); hence this definition will
 be installed for future @(':expand') @(see hints).  Furthermore, if this field
 is omitted or the value is @(':normalize'), then this definition will be
 simplified with the @(see normalization) procedure that is used by default
 when processing definitions made with @(tsee defun).  You must explicitly
 specify @(':install-body nil') in the following cases: @('fn') (as above) is a
 member of the value of constant @('*definition-minimal-theory*'), the
 arguments are not a list of distinct variables, @('equiv') (as above) is not
 @(tsee equal), or there are free variables in the hypotheses or right-hand
 side (see @(see free-variables)).  However, supplying @(':install-body nil')
 will not affect the rewriter's application of the @(':definition') rule, other
 than to avoid using the rule to apply @(':expand') hints.  If a definition
 rule equates @('(f a1 ... ak)') with @('body') but there are hypotheses,
 @('hyps'), then @(':expand') @(see hints) will replace terms @('(f term1
 ... termk)') by corresponding terms @('(if hyps body (hide (f term1
 ... termk)))').</p>

 <p>@(':')@(tsee Loop-stopper) &mdash; this field may only be supplied if the
 class is @(':')@(tsee rewrite).  Its value must be a list of entries each
 consisting of two variables followed by a (possibly empty) list of function
 symbols, for example @('((x y binary-+) (u v foo bar))').  It will be used to
 restrict application of rewrite rules by requiring that the list of instances
 of the second variables must be ``smaller'' than the list of instances of the
 first variables in a sense related to the corresponding functions listed; see
 @(see loop-stopper).  The list as a whole is allowed to be @('nil'),
 indicating that no such restriction shall be made.  Note that any such entry
 that contains a variable not being instantiated, i.e., not occurring on the
 left side of the rewrite rule, will be ignored.  However, for simplicity we
 merely require that every variable mentioned should appear somewhere in the
 corresponding @(':')@(tsee corollary) formula.</p>

 <p>@(':Pattern'), @(':Condition'), @(':Scheme') &mdash; the first and last of
 these fields must (and may only) be supplied if the class is @(':')@(tsee
 induction).  @(':Condition') is optional but may only be supplied if the class
 is @(':')@(tsee induction).  The values must all be terms and indicate,
 respectively, the pattern to which a new induction scheme is to be attached,
 the condition under which the suggestion is to be made, and a term which
 suggests the new scheme.  See @(see induction).</p>

 <p>@(':Match-free') &mdash; this field must be @(':all') or @(':once') and may
 be supplied only if the @(':class') is either @(':')@(tsee rewrite),
 @(':')@(tsee linear), or @(':')@(tsee forward-chaining).  (This field is not
 implemented for other rule classes, including the @(':')@(tsee
 type-prescription) rule class.)  See @(see free-variables) for a description
 of this field.  Note: Although this field is intended to be used for
 controlling retries of matching free variables in hypotheses, it is legal to
 supply it even if there are no such free variables.  This can simplify the
 automated generation of rules, but note that when @(':match-free') is
 supplied, the warning otherwise provided for the presence of free variables in
 hypotheses will be suppressed.</p>

 <p>@(':Backchain-limit-lst') &mdash; this field may be supplied only if the
 @(':class') is either @(':')@(tsee rewrite), @(':')@(tsee meta), @(':')@(tsee
 linear), or @(':')@(tsee type-prescription).  It is further required that
 either only one rule is generated from the formula or, at least, every such
 rule has the same list of hypotheses.  The value for @(':backchain-limit-lst')
 must be @('nil'); a non-negative integer; or, except in the case of
 @(':')@(tsee meta) rules, a true list each element of which is either @('nil')
 or a non-negative integer.  If it is a list, its length must be equal to the
 number of hypotheses of the rule and each item in the list is the ``backchain
 limit'' associated with the corresponding hypothesis.  If
 @('backchain-limit-lst') is a non-negative integer, it is defaulted to a list
 of the appropriate number of repetitions of that integer.  The backchain limit
 of a hypothesis is used to limit the effort that ACL2 will expend when
 relieving the hypothesis.  If it is @('NIL'), no new limits are imposed; if it
 is an integer, the hypothesis will be limited to backchaining at most that
 many times.  Note that backchaining may be further limited by a global
 @('backchain-limit'); see @(see backchain-limit) for details.  For different
 ways to reign in the rewriter, see @(see rewrite-stack-limit) and see @(see
 set-prover-step-limit).  Jared Davis has pointed out that you can set the
 @(':backchain-limit-lst') to 0 to avoid any attempt to relieve @(tsee force)d
 hypotheses, which can lead to a significant speed-up in some cases.</p>

 </blockquote>

 <p>Once @('thm') has been proved (in the case of @(tsee defthm)) and each rule
 class object has been checked for well-formedness (which might require
 additional proofs), we consider each rule class object in turn to generate and
 add rules.  Let @(':class') be the class keyword token of the @('i')th class
 object (counting from left to right).  Generate the @(see rune) @('(:class
 name . x)'), where @('x') is @('nil') if there is only one class and otherwise
 @('x') is @('i').  Then, from the @(':')@(tsee corollary) of that object,
 generate one or more rules, each of which has the name @('(:class name . x)').
 See the @(':')@(tsee doc) entry for each rule class to see how formulas
 determine rules.  Note that it is in principle possible for several rules to
 share the same name; it happens whenever a @(':')@(tsee corollary) determines
 more than one rule.  This in fact only occurs for @(':')@(tsee rewrite),
 @(':')@(tsee linear), and @(':')@(tsee forward-chaining) class rules and only
 then if the @(':')@(tsee corollary) is essentially a conjunction.  (See the
 documentation for @(see rewrite), @(see linear), or @(see forward-chaining)
 for details.)</p>")

(defxdoc rule-names
  :parents (theories)
  :short "How rules are named."
  :long "@({
  Examples:
  (:rewrite assoc-of-app)
  (:linear delta-aref . 2)
  (:definition length)
  (:executable-counterpart length)
 })

 <p>See @(see rune).</p>")

(defxdoc rulers
  :parents (defun)
  :short "Control for ACL2's termination and induction analyses"
  :long "<p><b>Introduction</b></p>

 <p>Consider the following recursive definition, which returns a list of threes
 of length one more than the length of @('x').</p>

 @({
    (defun f (x)
      (cons 3
            (if (consp x)
                (f (cdr x))
              nil)))
 })

 <p>One might expect ACL2's termination analysis to admit this function, since
 we know that @('(cdr x)') is ``smaller'' than @('x') if @('(consp x)') is
 true.  (By default, ACL2's notion of ``smaller'' is ordinary natural-number
 @('<'), and the argument @('x') is measured by applying function
 @('acl2-count') to @('x').)  However, that termination analysis does not
 consider @(tsee IF) tests, like @('(consp x)') above, when they occur under
 calls of functions other than @('IF'), such as @('CONS') in the case
 above.</p>

 <p>In the example above, we say that the term @('(consp x)') <i>governs</i>
 the recursive call @('(f (cdr x))') shown above, but does not <i>rule</i> that
 call.  Roughly speaking, the set of <i>governors</i> of a subterm occurrence
 in a given term consists of all superior @('IF') tests and their negations
 that must be true in order for evaluation to reach that subterm; however, the
 set of <i>rulers</i> of the occurrence only includes, at least by default,
 those tests and their negations from the top-level @('IF') structure of the
 term.  It is the rulers of a recursive call that affect its role in the
 termination and induction analysis for a function.</p>

 <p>One way to overcome this problem is to ``lift'' the @('IF') test to the top
 level, as follows, so that now @('(consp x)') is a ruler of the recursive
 call, and not merely a governor (though it remains a governor as well, of
 course).</p>

 @({
    (defun f (x)
      (if (consp x)
          (cons 3 (f (cdr x)))
        (cons 3 nil)))
 })

 <p>But another way to overcome the problem is to tell ACL2 to extend its
 termination (and induction) analysis through calls of @('cons'), as
 follows, by designating that calls of @('cons') should not block the
 accumulation of rulers.</p>

 @({
    (defun f (x)
      (declare (xargs :ruler-extenders (cons)))
      (cons 3
            (if (consp x)
                (f (cdr x))
              nil)))
 })

 <p>Let's look at one more (contrived) example:</p>

 @({
 (defun g (x)
   (if (atom x)
       x
     (len (if (symbolp (car x))
              (g (cddr x))
            (g (cdr x))))))
 })

 <p>There are two recursive calls, and the set of rulers is @('{(not (atom
 x))}') for each of those.  The set of governors for the first recursive call
 is @('{(not (atom x)), (symbolp (car x))}'), and for the second,
 @('{(not (atom x)), (not (symbolp (car x)))}').  The rulers is extended to be
 the governors in each case if we specify:
 @('(declare (xargs :ruler-extenders (len)))').</p>

 <p>You may even wish to provide value @(':all') instead of an explicit list of
 ruler-extenders, so that no function call blocks the termination analysis:</p>

 @({
    (defun f (x)
      (declare (xargs :ruler-extenders :all))
      (cons 3
            (if (consp x)
                (f (cdr x))
              nil)))
 })

 <p>Alternatively, you can omit the @('XARGS') @(':RULER-EXTENDERS') form,
 instead modifying the global default set of ruler-extenders:</p>

 @({
    (set-ruler-extenders :all)

    ; or, for example:
    (set-ruler-extenders '(cons return-last))
 })

 <p>You can call the function @(tsee default-ruler-extenders) as follows to see
 the current global default set of ruler-extenders:</p>

 @({
  (default-ruler-extenders (w state))
 })

 <p>We conclude this introduction by considering the handling of @('LET')
 expressions by termination analysis.  Consider the following example.</p>

 @({
    (defun fact (n)
      (the (integer 1 *)
           (if (posp n)
               (* n (fact (1- n)))
             1)))
 })

 <p>ACL2 treats the call of @(tsee THE) in the body of this definition as
 follows.</p>

 @({
    (let ((var (if (posp n)
                   (* n (fact (1- n)))
                 1)))
      (if (and (integerp var) (<= 1 var))
          var
        <some_error>))
 })

 <p>A @(tsee LET) expression, in turn, is treated as a @(tsee LAMBDA)
 application:</p>

 @({
    ((lambda (var)
       (if (if (integerp var)
               (not (< var 1))
             nil)
           var
         <some_error>))
     (if (posp n)
         (* n (fact (1- n)))
       1))
 })

 <p>Notice that the @(tsee posp) test, which governs the recursive call of
 @('fact'), is inside an argument of a function application, namely the
 application of the @('LAMBDA') expression.  So by default, ACL2 will not
 consider this @(tsee posp) test in its termination analysis.  The keyword
 @(':LAMBDAS') in the list of ruler-extenders denotes all calls of lambda
 expressions, much as the inclusion of @('CONS') in the ruler-extenders denotes
 all calls of @('CONS').  The following definition is thus accepted by
 ACL2.</p>

 @({
    (defun fact (n)
      (declare (xargs :ruler-extenders (:lambdas)))
      (the (integer 1 *)
           (if (posp n)
               (* n (fact (1- n)))
             1)))
 })

 <p>As a convenience, ACL2 allows the symbol @(':lambdas') in place of
 @('(:lambdas)'), and in fact the former will also include the two basic
 ruler-extenders: @(tsee RETURN-LAST) (which comes from macroexpansion of calls
 of @(tsee PROG2$), @(tsee EC-CALL), and others) and @(tsee MV-LIST).</p>

 <p>IMPORTANT REMARKS.  (1) Notice that the argument to
 @('set-ruler-extenders') is evaluated, but the argument to
 @(':RULER-EXTENDERS') in @('XARGS') is not evaluated.  (2) Do not put macro
 names in your list of ruler-extenders.  For example, if you intend that @('+')
 should not block the termination analysis, in analogy to @('cons') in the
 example above, then the list of ruler-extenders should include @('binary-+'),
 not @('+').  Of course, if you use @(':all') then this is not an issue, but
 see the next remark.  (3) Also please note that by taking advantage of the
 ruler-extenders, you may be complicating the induction scheme stored for the
 function, whose computation takes similar advantage of the additional @('IF')
 structure that you are specifying.</p>

 <p>To see the ruler-extenders of an existing function symbol, @('fn'), in a
 logical @(see world), @('wrld'), evaluate @('(ruler-extenders 'fn wrld)')
 after @('(include-book \"kestrel/utilities/world-queries\" :dir :system)').  For
 example, evaluation of @('(ruler-extenders 'fn (w state))') provides the
 ruler-extenders of @('fn') in the current logical world.</p>

 <p>Below we describe the notion of ruler-extenders in detail, as well as how
 to set its default using @('set-ruler-extenders').</p>

 <p><b>Details</b></p>

 <p>We begin by discussing how to set the ruler-extenders by using the macro
 @('set-ruler-extenders'); below we will discuss the use of keyword
 @(':ruler-extenders') in @(tsee XARGS) @(tsee declare) forms.  NOTE: The legal
 values discussed below for @('set-ruler-extenders') are the same as the legal
 values for the @(':ruler-extenders') @(tsee XARGS) keyword.</p>

 @({
  Examples:
  (set-ruler-extenders :basic) ; return to default
  (set-ruler-extenders *basic-ruler-extenders*) ; same as immediately above
  (set-ruler-extenders :all) ; every governing IF test rules a recursive call
  (set-ruler-extenders :lambdas) ; LET does not block termination analysis
  (set-ruler-extenders (cons :lambdas *basic-ruler-extenders*))
                                 ; same as immediately above
  (set-ruler-extenders '(f g)) ; termination analysis goes past calls of f, g

  General Form:
  (set-ruler-extenders val)
 })

 <p>where @('val') evaluates to one of @(':basic'), @(':all'), @(':lambdas'),
 or a true list of symbols containing no keyword other than, optionally,
 @(':lambdas').</p>

 <p>When a recursive definition is submitted to ACL2 (in @(':')@(tsee logic)
 mode), the recursion must be proved to terminate; see @(see defun).  More
 precisely, ACL2 explores the @(tsee IF) structure of the body of the
 definition to accumulate the tests that ``rule'' any given recursive call.
 The following example reviews how this works.  Suppose that @('f') has already
 been defined.</p>

 @({
    (defun g (x y)
      (declare (xargs :measure (+ (acl2-count x) (acl2-count y))))
      (if (consp x)
          (g (cdr x) y)
        (if (consp y)
            (f (g x (cdr y)))
          (f (list x y)))))
 })

 <p>ACL2 makes the following response to this proposed definition.  Notice that
 the @(':measure') proposed above must be proved to be an ACL2 ordinal &mdash;
 that is, to satisfy @('O-P') &mdash; and that the arguments to each recursive
 call must be smaller (in the sense of that measure and @('O<'), which here
 reduces to the ordinary @('<') relation) than the formals under the assumption
 of the ruling @('IF') tests.  The first @('IMPLIES') term below thus
 corresponds to the recursive call @('(g (cdr x) y)'), while the second
 corresponds to the recursive call @('(g x (cdr y))').</p>

 @({
    For the admission of G we will use the relation O< (which is known
    to be well-founded on the domain recognized by O-P) and the measure
    (+ (ACL2-COUNT X) (ACL2-COUNT Y)).  The non-trivial part of the measure
    conjecture is

    Goal
    (AND (O-P (+ (ACL2-COUNT X) (ACL2-COUNT Y)))
         (IMPLIES (CONSP X)
                  (O< (+ (ACL2-COUNT (CDR X)) (ACL2-COUNT Y))
                      (+ (ACL2-COUNT X) (ACL2-COUNT Y))))
         (IMPLIES (AND (NOT (CONSP X)) (CONSP Y))
                  (O< (+ (ACL2-COUNT X) (ACL2-COUNT (CDR Y)))
                      (+ (ACL2-COUNT X) (ACL2-COUNT Y))))).
 })

 <p>Now consider the following alternate version of the above definition.</p>

 @({
    (defun g (x y)
      (declare (xargs :measure (+ (acl2-count x) (acl2-count y))))
      (if (consp x)
          (g (cdr x) y)
        (f (if (consp y)
               (g x (cdr y))
             (list x y)))))
 })

 <p>The first test, @('(consp x)'), still rules the first recursive call, @('(g
 (cdr x) y)').  And the negation of that test, namely @('(not (consp x))'),
 still rules the second recursive call @('(g x (cdr y))').  But the call of
 @('f') blocks the top-down exploration of the @('IF') structure of the body of
 @('g'), so @('(consp y)') does not rule that second recursive call, which
 (again) is @('(g x (cdr y))').  As a result, ACL2 fails to admit the above
 definition.</p>

 <p>@('Set-ruler-extenders') is provided to overcome the sort of blocking
 described above.  Suppose for example that the following event is
 submitted:</p>

 @({
    (set-ruler-extenders '(f))
 })

 <p>Then the alternate definition of @('g') above is admissible, because the
 call of @('f') no longer blocks the top-down exploration of the @('IF')
 structure of the body of @('g'): that is, @('(consp y)') becomes a ruler of
 the recursive call @('(g x (cdr y))').  In this case, we say that @('f') is a
 ``ruler-extender''.  The same result obtains if we first submit</p>

 @({
    (set-ruler-extenders :all)
 })

 <p>as this removes all function calls as blockers of the top-down analysis.
 In other words, with @(':all') it is the case that for every recursive call,
 every test argument of a superior call of @('IF') contributes a ruler of that
 recursive call.</p>

 <p>ACL2 handles @(tsee LET) (and @(tsee LET*)) expressions by translating them
 to @('LAMBDA') expressions (see @(see term)).  The next examples illustrates
 termination analysis involving such expressions.  First consider the following
 (admittedly inefficient) definition.</p>

 @({
    (defun fact (n)
      (let ((k (if (natp n) n 0)))
        (if (equal k 0)
            1
          (* k (fact (+ -1 k))))))
 })

 <p>ACL2 translates the body of this definition to a @('LAMBDA') application,
 essentially:</p>

 @({
    ((lambda (k)
       (if (equal k 0)
           1
         (* k (fact (+ -1 k)))))
     (if (natp n) n 0))
 })

 <p>As with the application of any function other than @('IF'), the top-down
 termination analysis does not dive into arguments: the @('LAMBDA') blocks the
 continuation of the analysis into its argument.  But here, the argument of the
 @('LAMBDA') is @('(if (natp n) n 0)'), which has no recursive calls to
 consider anyhow.  What is more interesting: ACL2 does continue its termination
 analysis into the body of the @('LAMBDA'), in an environment binding the
 @('LAMBDA') formals to its actuals.  In this case, the termination analysis
 thus continues into the term</p>

 @({
    (if (equal k 0)
        1
      (* k (fact (+ -1 k))))
 })

 <p>in the environment that binds @('k') to the term @('(if (natp n) n 0)').
 Thus, the proof obligation is successfully discharged, as reported by
 ACL2:</p>

 @({
    For the admission of FACT we will use the relation O< (which is known
    to be well-founded on the domain recognized by O-P) and the measure
    (ACL2-COUNT N).  The non-trivial part of the measure conjecture is

    Goal
    (IMPLIES (NOT (EQUAL (IF (NATP N) N 0) 0))
             (O< (ACL2-COUNT (+ -1 (IF (NATP N) N 0)))
                 (ACL2-COUNT N))).
    .....
    Q.E.D.

    That completes the proof of the measure theorem for FACT.
 })

 <p>But now consider the following definition, in which the recursion takes
 place inside the argument of the @('LAMBDA') rather than inside the
 @('LAMBDA') body.</p>

 @({
    (defun app (x y)
      (let ((result (if (endp x)
                        y
                      (cons (car x)
                            (app (cdr x) y)))))
        (if (our-test result)
            result
          0)))
 })

 <p>Writing the body in @('LAMBDA') notation:</p>

 @({
    ((lambda (result)
       (if (our-test result)
           result
         0))
     (if (endp x)
         y
       (cons (car x)
             (app (cdr x) y))))
 })

 <p>By default, the @('LAMBDA') call blocks the top-down termination analysis
 from proceeding into the term @('(if (endp x) ...)').  To solve this, one can
 submit the event:</p>

 @({
    (set-ruler-extenders :lambdas)
 })

 <p>The above definition of @('app') is then admitted by ACL2, because the
 termination analysis is no longer blocked by the @('LAMBDA') call.</p>

 <p>The example just above illustrates that the heuristically-chosen measure is
 suitably sensitive to the ruler-extenders.  Specifically: that measure is the
 application of @('acl2-count') to the first formal parameter of the function
 that is tested along every branch of the relevant @('IF') structure (as
 determined by the rulers) and occurs as a proper subterm at the same argument
 position in every recursive call.  The heuristics for choosing the
 controller-alist for a @(tsee definition) rule are similarly sensitive to the
 ruler-extenders (see @(see definition)).</p>

 <p>The remarks above for @(tsee defun) @(see events) are equally applicable
 when a definition sits inside a @(tsee mutual-recursion) event, except of
 course that in this case, a ``recursive call'' is a call of any function being
 defined by that @(tsee mutual-recursion) event.</p>

 <p>Rules of class @(':')@(tsee definition) are sensitive to
 @('set-ruler-extenders') in analogy to the case of @('defun') @(see
 events).</p>

 <p>This macro generates a call @('(table acl2-defaults-table :ruler-extenders
 val)') and hence is @(tsee local) to any @(see books) and @(tsee encapsulate)
 @(see events) in which it occurs. See @(see acl2-defaults-table).  The current
 list of ruler-extenders may be obtained as</p>

 @({
    (cdr (assoc-eq :ruler-extenders
         (table-alist 'acl2-defaults-table (w state))))
 })

 <p>or more conveniently, as:</p>

 @({
    (default-ruler-extenders (w state))
 })

 <p>Note that evaluation of @('(set-ruler-extenders lst)'), where @('lst')
 evaluates to a list, does not necessarily include the default ruler-extenders
 &mdash; i.e., those included for the argument, @(':basic') &mdash; which are
 the elements of the list constant @('*basic-ruler-extenders*'), namely @(tsee
 return-last) and @(tsee mv-list).  You may, of course, include these
 explicitly in your list argument.</p>

 <p>We conclude our discussion by noting that the set of ruler-extenders can
 affect the induction scheme that is stored with a recursive definition.  The
 community book @('books/misc/misc2/ruler-extenders-tests.lisp') explains how
 induction schemes are derived in this case.  Consider the following
 example.</p>

 @({
    (defun tree-of-nils-p (x)
      (if (consp x)
          (and (tree-of-nils-p (car x))
               (tree-of-nils-p (cdr x)))
        (null x)))
 })

 <p>The above definition generates the following induction scheme.  Note that
 @('(and u v)') expands to @('(if u v nil)'), which explains why the term
 @('(tree-of-nils-p (car x))') rules the recursive call @('(tree-of-nils-p (cdr
 x))'), resulting in the hypothesis @('(tree-of-nils-p (car x))') in the final
 conjunct below.</p>

 @({
    (AND (IMPLIES (NOT (CONSP X)) (:P X))
         (IMPLIES (AND (CONSP X)
                       (NOT (TREE-OF-NILS-P (CAR X)))
                       (:P (CAR X)))
                  (:P X))
         (IMPLIES (AND (CONSP X)
                       (TREE-OF-NILS-P (CAR X))
                       (:P (CAR X))
                       (:P (CDR X)))
                  (:P X)))
 })

 <p>Now consider the following variant of the above definition, in which a call
 of the function @('identity') blocks the termination analysis.</p>

 @({
    (defun tree-of-nils-p (x)
      (if (consp x)
          (identity (and (tree-of-nils-p (car x))
                         (tree-of-nils-p (cdr x))))
        (null x)))
 })

 <p>This time the induction scheme is as follows, since only the top-level
 @('IF') test contributes rulers to the termination analysis.</p>

 @({
    (AND (IMPLIES (NOT (CONSP X)) (:P X))
         (IMPLIES (AND (CONSP X)
                       (:P (CAR X))
                       (:P (CDR X)))
                  (:P X)))
 })

 <p>But now suppose we first designate @('identity') as a ruler-extender.</p>

 @({
  (set-ruler-extenders '(identity))
 })

 <p>Then the induction scheme generated for the both of the above variants of
 @('tree-of-nils-p') is the one shown for the first variant, which is
 reasonable because both definitions now produce essentially the same
 termination analysis.</p>")

(defxdoc rune
  :parents (theories)
  :short "A rule name"
  :long "@({
  Examples:
  (:rewrite assoc-of-app)
  (:linear delta-aref . 2)
  (:definition length)
  (:executable-counterpart length)
 })

 <p>Note: This topic discusses a basic notion of ``rule name'', or ``rune'' for
 short.  Users often use abbreviations for runes; for example, a @(see theory)
 expression @('(DISABLE APPEND)') abbreviates the following set of runes:
 @('{(:DEFINITION BINARY-APPEND), (:INDUCTION BINARY-APPEND)}').  See @(see
 theories) for a discussion of so-called ``runic designators'', which include
 expressions like @('APPEND') (as above) as well as @('(APPEND)') (for the
 @(see executable-counterpart) of @('BINARY-APPEND')).  Runic designators can
 also be ``runic abbreviations'' such as @('(:d APPEND)'), @('(:e APPEND)'),
 @('(:i APPEND)'), and @('(:t APPEND)'), which designate the definition,
 executable-counterpart, induction, and type-prescription rules for
 @('BINARY-APPEND').  For a complete description of runic designators, see
 @(see theories); we return now to the more basic notion of a rune.</p>

 <p>Background: The theorem prover is driven from a database of rules.  The
 most common rules are @(':')@(tsee rewrite) rules, which cause the simplifier
 to replace one term with another.  @(see Events) introduce rules into the
 database.  For example, a @(tsee defun) event may introduce runes for
 symbolically replacing a function call by its instantiated body, for
 evaluating the function on constants, for determining the type of a call of
 the function, and for the induction scheme introduced upon defining the
 function.  @(tsee Defthm) may introduce several rules, one for each of the
 @(':')@(tsee rule-classes) specified (where one rule class is specified if
 @(':')@(tsee rule-classes) is omitted, namely, @(':rewrite')).</p>

 <p>Every rule in the system has a name.  Each name is a structured object
 called a ``rune,'' which is short for ``rule name''.  Runes are always of the
 form @('(:token symbol . x)'), where @(':token') is some keyword symbol
 indicating what kind of rule is named, @('symbol') is the event name that
 created the rule (and is called the ``base symbol'' of the rune), and @('x')
 is either @('nil') or a natural number that makes the rule name distinct from
 that of rules generated by other @(see events) or by other @(':')@(tsee
 rule-classes) within the same event.</p>

 <p>For example, an event of the form</p>

 @({
  (defthm name thm
    :rule-classes ((:REWRITE :COROLLARY term1)
                   (:REWRITE :COROLLARY term2)
                   (:ELIM    :COROLLARY term3)))
 })

 <p>typically creates three rules, each with a unique rune.  The runes are</p>

 @({
  (:REWRITE name . 1), (:REWRITE name . 2), and (:ELIM name).
 })

 <p>However, a given formula may create more than one rule, and all rules
 generated by the same @(':corollary') formula will share the same rune.
 Consider the following example.</p>

 @({
  (defthm my-thm
    (and (equal (foo (bar x)) x)
         (equal (bar (foo x)) x)))
 })

 <p>This is treated identically to the following.</p>

 @({
  (defthm my-thm
    (and (equal (foo (bar x)) x)
         (equal (bar (foo x)) x))
    :rule-classes ((:rewrite
                    :corollary
                    (and (equal (foo (bar x)) x)
                         (equal (bar (foo x)) x)))))
 })

 <p>In either case, two rules are created: one rewriting @('(foo (bar x))') to
 @('x'), and one rewriting @('(bar (foo x))') to @('x').  However, only a
 single rune is created, @('(:REWRITE MY-THM)'), because there is only one rule
 class.  But now consider the following example.</p>

 @({
  (defthm my-thm2
    (and (equal (foo (bar x)) x)
         (equal (bar (foo x)) x))
    :rule-classes ((:rewrite
                    :corollary
                    (and (equal (foo (bar x)) x)
                         (equal (bar (foo x)) x)))
                   (:rewrite
                    :corollary
                    (and (equal (foo (bar (foo x))) (foo x))
                         (equal (bar (foo (bar x))) (bar x))))))
 })

 <p>This time there are four rules created.  The first two rules are as before,
 and are assigned the rune @('(:REWRITE MY-THM . 1)').  The other two rules are
 similarly generated for the second @(':corollary'), and are assigned the rune
 @('(:REWRITE MY-THM . 2)').</p>

 <p>The function @(tsee corollary) will return the @(see corollary) term
 associated with a given rune in a given @(see world).  Example:</p>

 @({
  (corollary '(:TYPE-PRESCRIPTION DIGIT-TO-CHAR) (w state))
 })

 <p>However, the preferred way to see the corollary term associated with a rune
 or a name is to use @(':pf'); see @(see pf).</p>

 <p>The @(tsee defun) event creates as many as four rules.  @('(:definition
 fn)') is the rune given to the equality axiom defining the function, @('fn').
 @('(:executable-counterpart fn)') is the rune given to the rule for computing
 @('fn') on known arguments.  A type prescription rule may be created under the
 name @('(:type-prescription fn)'), and an @(see induction) rule may be created
 under the name @('(:induction fn)').</p>

 <p>Runes may be individually @(see enable)d and @(see disable)d, according to
 whether they are included in the current theory.  See @(see theories).  Thus,
 it is permitted to @(see disable) @('(:elim name)'), say, while enabling the
 other rules derived from name.  Similarly, @('(:definition fn)') may be @(see
 disable)d while @('(:executable-counterpart fn)') and the type prescriptions
 for @('fn') are @(see enable)d.</p>

 <p>Associated with most runes is the formula justifying the rule named.  This
 is called the ``@(see corollary) formula'' of the rune and may be obtained via
 the function @(tsee corollary), which takes as its argument a rune and a
 property list @(see world).  Also see @(see pf).  The @(see corollary) formula
 for @('(:rewrite name . 1)') after the @(tsee defthm) event above is
 @('term1').  The corollary formulas for @('(:definition fn)') and
 @('(:executable-counterpart fn)') are always identical: the defining axiom.
 Some runes, e.g., @('(:definition car)'), do not have corollary formulas.
 @(tsee Corollary) returns @('nil') on such runes.  In any case, the corollary
 formula of a rune, when it is non-@('nil'), is a theorem and may be used in
 the @(':use') and @(':by') @(see hints).</p>

 <p>Note: The system has built-in rules that, for regularity, ought to have
 names but don't because they can never be @(see disable)d.  One such rule is
 that implemented by the @(see linear) arithmetic package.  Because many of our
 subroutines are required by their calling conventions to return the justifying
 rune, we have invented the notion of ``fake runes.''  Fake runes always have
 the base symbol @('nil'), use a keyword token that includes the phrase
 ``fake-rune'', and are always @(see enable)d.  Here is the list of fake
 runes.</p>

 <p>@(`(:code (pairlis$ (strip-cars *fake-rune-alist*) (pairlis$ (make-list
 (length *fake-rune-alist*)) nil)))`)</p>

 <p>Occasionally the system will print a fake rune where a rune is expected.
 For example, when @('(:FAKE-RUNE-FOR-LINEAR NIL)') is reported among the rules
 used in a proof, it is an indication that the linear arithmetic package was
 used.  However, fake runes are not allowed in @(see theories), they cannot be
 @(see enable)d or @(see disable)d, and they do not have associated @(see
 corollary) formulas.  In short, despite the fact that the user may sometimes
 see fake runes printed, they should never be typed.</p>")

(defxdoc |Revisiting the Admission of App|
  :parents (|Pages Written Especially for the Tours|)
  :short "Revisiting the Admission of App"
  :long "<p><see topic='@(url |Evaluating App on Sample Input|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>Here is the definition of @('app') again with certain parts highlighted.
 If you are taking the Walking Tour, please read the text carefully and click
 on each of the links below, <b>except those marked</b> <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>.
 Then come <b>back</b> here.</p>

 <p><img src='res/tours/green-line.gif'></img></p>

 <code>
 <see topic='@(url |About the Prompt|)'>ACL2 !&gt;</see><b>(defun app (x y)</b>
   <b>(cond ((endp x) y)</b>
         <b>(t (cons (car x) </b>
                  <b>(app (cdr x) y)))))</b>

 The <see topic='@(url |About the Admission of Recursive Definitions|)'>admission</see> of APP is trivial, using the
 relation @(see O<) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> (which is known to be well-founded on
 the domain recognized by @(see O-P) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>) and the measure
 (@(see ACL2-COUNT) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> X).  We <see topic='@(url |Guessing the Type of a Newly Admitted Function|)'>observe</see> that the
 <see topic='@(url |About Types|)'>type</see> of APP is described by the theorem (OR
 (CONSP (APP X Y)) (EQUAL (APP X Y) Y)).  We used primitive type
 reasoning.

 <see topic='@(url |The Event Summary|)'>Summary</see>
 Form:  ( DEFUN APP ...)
 Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
 Warnings:  None
 Time:  0.03 seconds (prove: 0.00, print: 0.00, other: 0.03)
  APP
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p><see topic='@(url |Evaluating App on Sample Input|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |Rewrite Rules are Generated from DEFTHM Events|
  :parents (|Pages Written Especially for the Tours|)
  :short "Rewrite Rules are Generated from DEFTHM Events"
  :long "<p><see topic='@(url
 |You Must Think about the Use of a Formula as a Rule|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>By reading the documentation of @(tsee defthm) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 (and especially of its :@(see rule-classes) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 argument) you would learn that when we submitted the command</p>

 <code>
 <b>(defthm associativity-of-app</b>
   <b>(equal (app (app a b) c)</b>
          <b>(app a (app b c))))</b>

 </code>

 <p>we not only command the system to prove that @('app') is an associative
 function but</p>

 <code>
   * <b>we commanded it to use that fact as a rewrite rule</b>.
 </code>

 <p>That means that every time the system encounters a term of the form</p>

 <code>
 (app (app <b>x</b> <b>y</b>) <b>z</b>)
 </code>

 <p>it will replace it with</p>

 <code>
 (app <b>x</b> (app <b>y</b> <b>z</b>))!
 </code>

 <p><see topic='@(url
 |You Must Think about the Use of a Formula as a Rule|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |Running Models|
  :parents (|Pages Written Especially for the Tours|)
  :short "Running Models"
  :long "<p><see topic='@(url |Symbolic Execution of Models|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>Suppose the machine being modeled is some kind of arithmetic unit.  Suppose
 the model can be initialized so as to <b>multiply</b> <b>x</b> times <b>y</b>
 and leave the answer in <b>z</b>.  Then if we initialize <b>s</b> to
 <b>multiply</b> with <b>x=5</b> and <b>y=7</b> and run the machine long
 enough, we can read the answer <b>35</b> in the final state.

  <img src='res/tours/computing-machine-5x7.gif'></img></p>

 <p>Because ACL2 is a programming language, our model can be <b>run</b> or
 <b>executed</b>.</p>

 <p>If you defined the model in ACL2 and then typed</p>

 @({
  (lookup 'z (mc (s 'mult 5 7) 29))
 })

 <p>then ACL2 would compute 35.  (Here we assume that the function @('s')
 creates a state ready to run a given application on given inputs @('x') and
 @('y').)  You can <b>emulate</b> or <b>test</b> the model of your machine.</p>

 <p>This is <b>obvious</b> because ACL2 is Common Lisp; and Common Lisp is a
 <b>programming language</b>.</p>

 <p><see topic='@(url |Symbolic Execution of Models|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc safe-mode
  :parents (guard macros)
  :short "A mode that avoids @(see guard) violations on @(see primitive)s"
  :long "<p>ACL2 has a special mode, called ``safe mode'', that guarantees that
 built-in ACL2 @(see primitive)s check their @(see guard)s even even when
 @(tsee set-guard-checking) has turned off guard-checking.  This mode is used
 for macroexpansion as well as in processing a few other kinds of forms,
 notably @(tsee defconst), @(tsee defpkg), and @(tsee value-triple) events.</p>

 <p>Use of this mode avoids the possibility of certain errors when loading a
 compiled file for a book.  Consider the following definitions.</p>

 @({
 (defun foo (x) (declare (xargs :guard (consp x))) (car x))
 (defmacro bar () (foo 3))
 })

 <p>Then we can see @('safe-mode') in action as follows.</p>

 @({
 ACL2 !>(set-guard-checking nil)

 Masking guard violations but still checking guards except for self-
 recursive calls.  To avoid guard checking entirely, :SET-GUARD-CHECKING
 :NONE.  See :DOC set-guard-checking.

 ACL2 >(bar)


 ACL2 Error in TOP-LEVEL:  In the attempt to macroexpand the form (BAR),
 evaluation of the macro body caused the following error:

 The guard for the function call (CAR X), which is
 (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the call
 (CAR 3).  The guard is being checked because this function is a primitive
 and a \"safe\" mode is being used for defconst, defpkg, macroexpansion,
 or another operation where safe mode is required.  To debug see :DOC
 print-gv, see :DOC trace, and see :DOC wet.

 ACL2 >
 })

 <p>Notice that because of the @('set-guard-checking') call above, no guard
 violation was reported for @('foo').  However, @('safe-mode') caused the call
 of the @(see primitive), @(tsee car), to be guard-checked, and a violation was
 reported.</p>

 <p>To understand how safe-mode works we refer to the notion of
 ``executable-counterpart''; see @(see evaluation) for relevant background.
 ACL2 arranges for that for the executable-counterpart of any program mode
 function, @('F'), then for every called subroutine @('G') of @('F') that is in
 program mode, the executable-counterpart of @('G') is called rather than the
 raw Lisp function for @('G').  This may result in an attempt to evaluate a
 so-called ``@(see program-only)'' function in safe-mode, which is illegal.
 See @(see safe-mode-cheat-sheet) for possible workarounds.</p>")

(defxdoc safe-mode-cheat-sheet
  :parents (safe-mode)
  :short "Working around ``@(see program-only)'' issues"
  :long "<p>This cheat sheet gives workarounds for errors caused by attempts to
 evaluate executable-counterparts (see @(see evaluation)) of so-called @(see
 program-only) functions.  This most often occurs when @(see safe-mode) is
 active.  Recall that safe-mode can be set by @('(assign safe-mode t)'), and
 also is used during macroexpansion and other logical acts that might involve
 @(':')@(tsee program) mode functions.</p>

 <p>The problems manifest with a hard error like this:</p>

 @({
 HARD ACL2 ERROR in PROGRAM-ONLY:  The call
 <term>
 is an illegal call of a function that has been marked as ``program-
 only,'' presumably because it has special raw Lisp code and safe-mode
 is active.  See :DOC program-only for further explanation and a link
 to possible workarounds.
 (See :DOC set-iprint to be able to see elided values in this message.)
 })

 <p>When the term is a call of @('ev-w'), an unsafe hack allowing such calls
 is as follows.  Warning: This may result in unsoundness!</p>

 @({
 (value :q)
 (setf (symbol-function (*1*-symbol 'ev-w))
       (symbol-function 'ev-w))
 (lp)
 })

 <p>Typically that just leads to other similar errors and so you discover the
 call tree, each of whose functions can be handled similarly (also in raw
 Lisp):</p>

 @({
 (setf (symbol-function (*1*-symbol 'ev-rec))
       (symbol-function 'ev-rec))
 (setf (symbol-function (*1*-symbol 'ev-fncall-rec))
       (symbol-function 'ev-fncall-rec))
 (setf (symbol-function (*1*-symbol 'push-warning))
       (symbol-function 'push-warning))
 })

 <p>Other times you may avoid the problem by defining your own utilities.  For
 example, in safe-mode you can't use the utility @(tsee without-evisc) (which
 is useful when @(see iprint)ing is active).  But the following works, provided
 @('form') evaluates to an @(see error-triple).</p>

 @({
 (defmacro without-evisc-error-triple (form)
   `(state-global-let*
     ((abbrev-evisc-tuple nil set-abbrev-evisc-tuple-state)
      (gag-mode-evisc-tuple nil set-gag-mode-evisc-tuple-state)
      (term-evisc-tuple nil set-term-evisc-tuple-state)
      (ld-evisc-tuple nil set-ld-evisc-tuple-state))
     ,form))
 })

 <p>The following log illustrates how to use this utility to avoid an error
 caused by @('without-evisc') in safe-mode.</p>

 @({
 ACL2 !>(set-iprint t)

 ACL2 Observation in SET-IPRINT:  Iprinting has been enabled.
 ACL2 !>(assign safe-mode t)
  T
 ACL2 !>(cw \"Something printed with evisceration: ~X01~|\"
            '((((DEEP))))
            (evisc-tuple 3 4 nil nil))
 Something printed with evisceration: (((#@1#)))
 NIL
 ACL2 !>(without-evisc-error-triple (value '(((#@1#)))))
  ((((DEEP))))
 ACL2 !>
 })")

(defxdoc save-and-clear-memoization-settings
  :parents (memoize)
  :short "Save and remove the current memoization settings"
  :long "<p>For background on memoization, see @(see memoize).</p>

 @({
  General Form:
  (save-and-clear-memoization-settings)
 })

 <p>Calls of this macro achieve two changes.  The first copies the current
 memoization settings into an ACL2 @(see table), and the second unmemoizes all
 functions that were memoized by calls of @(tsee memoize).  Also see @(see
 restore-memoization-settings).</p>")

(defxdoc save-exec
  :parents (interfacing-tools command-line)
  :short "Save an executable image and a wrapper script"
  :long "<p>@('Save-exec') saves your ACL2 state so that you can immediately
 re-start later in that same state.  This utility can be useful for a project
 with @(see books) to be included every time ACL2 is started (see
 @(see BUILD::using-extended-acl2-images)), to avoid time
 taken to run @(tsee include-book).  Another use of @('save-exec') is to save
 an executable that takes command-line arguments beyond those normally passed
 to the host Lisp executable.  All arguments of a call of @('save-exec') are
 evaluated.</p>

 @({
  Examples:

  ; Save an executable script named my-saved_acl2, with the indicated message
  ; added to the start-up banner:
  (save-exec \"my-saved_acl2\"
             \"This saved image includes Version 7 of Project Foo.\")

  ; Same as above, but instead with a generic comment in the start-up banner:
  (save-exec \"my-saved_acl2\" nil)

  ; Arrange that the generated script passes the indicated arguments to be
  ; processed by the Lisp (ACL2) executable (where this example is specific to
  ; the case that CCL is the host Lisp):
  (save-exec \"my-saved_acl2\" nil
             :host-lisp-args \"--no-init -Z 256M\")

  ; Arrange that the generated script passes along the indicated arguments
  ; to Lisp (ACL2), but that they are not processed by Lisp other than to
  ; record the additional arguments (see (6) below).
  (save-exec \"my-saved_acl2\" nil
             :inert-args \"abc xyz -i foo\")

  ; Combining the preceding two examples:
  (save-exec \"my-saved_acl2\" nil
             :host-lisp-args \"--no-init -Z 256M\"
             :inert-args \"abc xyz -i foo\")

  ; Arrange that ACL2 evaluates (with LD) the three forms shown.
  ; In this example, the THM form fails, but that does not stop the definition
  ; of BAR from being evaluated: LD continues on, just as the top-level loop
  ; lets you continue after a failure.
  (save-exec \"my-acl2\" \"test\"
             :init-forms
             '((defun foo (x) (reverse x))
               (thm (equal (foo x) x))
               (defun bar (x) x)))

  ; Essentially as just above, except that the call of LD returns after the THM
  ; failure, so BAR does not get defined.
  (save-exec \"my-acl2\" \"test\"
             :init-forms
             '((ld '((defun foo (x) (reverse x))
                     (thm (equal (foo x) x))
                     (defun bar (x) x))
                   :ld-pre-eval-print t :ld-verbose nil)))

  ; Immediately exit the ACL2 read-eval-print loop after starting up.
  (save-exec \"my-acl2\" nil
             :return-from-lp t)

  ; Immediately exit the ACL2 read-eval-print loop after starting up and
  ; defining function FOO in the logic.
  (save-exec \"my-acl2\" \"Start with foo defined.\"
             :return-from-lp '(with-output
                               :off :all
                               (defun foo (x) x)))

  ; Immediately exit the ACL2 read-eval-print loop after starting up and
  ; defining variable xxx in raw Lisp.
  (save-exec \"my-acl2\" \"Start with xxx defined.\"
             :return-from-lp '(with-output
                               :off :all
                               (ld '((set-raw-mode-on!)
                                     (defvar xxx (make-list 10))
                                     (set-raw-mode nil)
                                     (u)))))
 })

 <p>Each example above generates a file named \"my-saved_acl2\".  That file is
 quite similar in form to the script generated when building ACL2 directly from
 source code; details are below.  For example, here are the contents of that
 generated file if the host Lisp is CCL (but where dates and pathnames are
 specific to one's environment).  Here, we break lines using `\\', but the
 @('exec') command is actually on a single line.</p>

 @({
  #!/bin/sh

  # Saved August 16, 2013  23:06:49
  #  then August 17, 2013  11:01:56

  export CCL_DEFAULT_DIRECTORY=\"/projects/acl2/lisps/ccl/15542/ccl\"
  exec \"/projects/ccl/lx86cl64\" -I \"/u/smith/my-saved_acl2.lx86cl64\" \\
       -Z 64M -K ISO-8859-1 -e \"(acl2::acl2-default-restart)\" \\
       --no-init -Z 256M \\
       -- \\
       abc xyz -i foo \\
       \"$@\"
 })

 @({
  General Form:
  (save-exec exec-filename extra-startup-string
             :host-lisp-args host-lisp-args
             :inert-args inert-args
             :return-from-lp return-from-lp
             :init-forms init-forms)
 })

 <p>where the keyword arguments are optional, and arguments are as follows.</p>

 <blockquote><p>@('Exec-filename') is the filename of the proposed
 executable.</p>

 <p>@('Extra-startup-string') is a non-empty string to be printed after the
 normal ACL2 startup message when you start up the saved image.  However,
 @('extra-startup-string') is allowed to be @('nil'), in which case a generic
 string will be printed instead.</p>

 <p>@('Host-lisp-args') can be @('nil') (the default), but if it is a
 non-@('nil') value, then it is a string to be inserted into the command line
 in the saved script, specifying additional arguments that are to be processed
 by the host Lisp executable.  (Note for SBCL only: these are runtime options;
 for toplevel options, see (8) below.)</p>

 <p>@('Inert-args') can be @('nil') (the default), but if it is a non-@('nil')
 value, then it is a string to be inserted into the command line in the saved
 script, specifying additional arguments that are not to be processed by the
 host Lisp executable.</p></blockquote>

 <p>@('Return-from-lp') and @('init-forms') are @('nil') by default.
 Regardless of their value, ACL2 starts up and enters its read-eval-print loop
 in the usual way; see @(see lp).  Normally you'll stay inside that loop, but
 if @('return-from-lp') or @('init-forms') is not @('nil'), then the indicated
 forms are evaluated in the ACL2 read-eval-print loop: a single form in the
 case of @('return-from-lp'), and a list of forms in the case of
 @('init-forms').  (Essentially, the @(tsee ld) special @(tsee standard-oi) is
 provided to a call of @(tsee ld) as a list with the indicated forms on the
 front.)  Moreover, if the case of @('return-from-lp'), the loop is exited
 after evaluation of the form, leaving you in raw Lisp.  Evaluation of
 @('return-from-lp') is done with @(tsee ld) options that minimize output (also
 see @(see with-output) to minimize output).  Suggestion: let
 @('return-from-lp') be @('t') if you simply want to exit the read-eval-print
 loop at startup, without evaluating any (nontrivial) form.</p>

 <p>NOTE: It is illegal to supply non-@('nil') values for both
 @(':return-from-lp') and @(':init-forms').  But if you add @('(value :q)') to
 the end of your list of @(':init-forms'), and your other forms do not result
 in an error, then you will be left in raw Lisp (as was presumably intended if
 you were planning to use @(':return-from-lp')).</p>

 <p>The remainder of this documentation focuses on the options other than
 @('return-from-lp') and @('init-forms').</p>

 <p><b>Details</b>:</p>

 <p>(1) You must first exit the ACL2 read-eval-print loop, typically by
 executing @(':q'), before evaluating a @('save-exec') call; otherwise an error
 occurs.</p>

 <p>(2) The image will be saved so that in the new image, the raw Lisp package
 and the package in the ACL2 read-eval-print loop (see @(see lp)) will be the
 same as their respective values at the time @('save-exec') is called.</p>

 <p>(3) @('Save-exec') generates a small script file (e.g.,
 @('\"my-saved_acl2\"') in the examples above), similar in form (see (4) below)
 to the script generated when building ACL2 directly from source code, but with
 a comment line indicating the time at which the new script is written.
 @('Save-exec') also saves an associated binary file.  The binary file's name
 is obtained by putting a suffix on the script filename; for example, if the
 host Lisp is GCL running on a Linux or Darwin (MacOS) system, then that binary
 file has the name @('my-saved_acl2.gcl') in the examples above.</p>

 <p>(4) If @('inert-args') is @('nil') (for example if keyword @(':inert-args')
 is omitted), then when the generated ACL2 script is invoked with command line
 arguments, those arguments will be passed to the host Lisp; otherwise they
 will not.  Thus for the example above, suppose we invoke the generated script
 as follows.</p>

 @({
  my-saved_acl2 -a bcd -e fgh
 })

 <p>If @('my-saved_acl2') was generated using a @('save-exec') command with a
 non-@('nil') value specified for keyword @(':inert-args'), then the arguments
 ``@('-a bcd -e fgh')'' will not be passed to the host Lisp; otherwise, they
 will be.  Note that for ACL2 executable scripts generated by an ordinary ACL2
 build from sources, the latter case (i.e., without @('inert-args')) takes
 place.</p>

 <p>(5) The generated script, which specifies execution with @('/bin/sh'), will
 generally contain a line of one of the following forms.  (But for SBCL, see
 (8) below.)  In the examples that follow, @('ACL2_options') is a suitable list
 of command-line arguments given to the ACL2 executable.  The quoted string
 @('\"$@\"') is intended to allow the user to pass additional command-line
 arguments to that executable.</p>

 <blockquote>

 <p>If @('host-lisp-args') and @('inert-args') are omitted (or @('nil')):</p>

 @({
  exec <lisp_executable> <ACL2_options> \"$@\"
 })

 <p>More generally, @('host-lisp-args') is inserted immediately after
 @('<ACL2_options>'), but only if it is non-@('nil') (hence a string).  If
 @('inert-args') is @('nil'), we thus get:</p>

 @({
  exec <lisp_executable> <ACL2_options> host-lisp-args \"$@\"
 })

 <p>If @('host-lisp-args') redefines a value from @('<ACL2_options>'), then it
 is up to the host lisp which value to use.  For example, experiments show that
 in CCL, if @('-Z') appears twice, each with a legal value, then the second
 value is the one that is used (i.e. it does indeed override the original value
 written out by ACL2 in @('<ACL2_options>').  But experiments also show that in
 LispWorks, where ``@('-init -')'' is included in @('<ACL2_options>'), then
 inclusion of ``@('-init foo.lisp')'' in @('host-lisp-args') is ignored.</p>

 <p>The remaining cases below are for a non-@('nil') value of @('inert-args').
 In each case, if @('host-lisp-args') is @('nil') then it should be omitted
 from the displayed command.</p>

 <p>If @('inert-args') is @('t') then an additional argument, `@('--')',
 indicates that when ACL2 is given command line arguments, these should not be
 processed by the host Lisp (other than recording them; see (6) below):</p>

 @({
  exec <lisp_executable> <ACL2_options> host-lisp-args -- \"$@\"
 })

 <p>If @('inert-args') is a string then the result is similar to the above,
 except that @('inert-args') is added immediately after `@('--')':</p>

 @({
  exec <lisp_executable> <ACL2_options> host-lisp-args -- inert-args \"$@\"
 })

 </blockquote>

 <p>(6) See @(see oslib::argv) for a utility that returns a list of all
 @('inert-args') from an invocation of ACL2.  See also @(see getopt::getopt)
 for a convenient way to parse these arguments.</p>

 <p>(7) Suppose that you invoke an ACL2 script, say @('\"my-saved_acl2\"'),
 that was generated by @('save-exec'), and then optionally evaluate some forms.
 Then you may save a new ACL2 script with @('save-exec').  The new script will
 contain comment lines that extend comment lines in @('\"my-saved_acl2\"') with
 a new write date, but otherwise will be identical to the script that would
 have been generated by executing the new @('save-exec') call after invoking
 the original ACL2 executable (built directly from ACL2 sources) instead of
 @('\"my-saved_acl2\"').  In other words, the options added by the earlier
 @('save-exec') call that created @('\"my-saved_acl2\"') are discarded by the
 new @('save-exec') call.  However, the @('.core') file will built on top of
 the @('.core') file that was consulted when @('\"my-saved_acl2\"') was
 invoked.</p>

 <p>(8) The following note pertains only to the case that the host Lisp is
 SBCL.  For SBCL, the scripts written are analogous to, but slightly different
 from, those shown above.  Please note that for SBCL, the @('host-lisp-args')
 are what the SBCL manual calls ``runtime options''.  For SBCL only, an extra
 keyword argument, @(':toplevel-args'), may be used for specifying what the
 SBCL manual calls ``toplevel options.  As with @(':host-lisp-args'), this
 value, @('toplevel-args'), should be @('nil') (the default) or a string.  Here
 is an example.</p>

 @({
  (save-exec \"my-saved_acl2\" nil
             :host-lisp-args \"--dynamic-space-size 50000\"
             :toplevel-args \"--eval '(print \\\"HELLO\\\")'\"
             :inert-args \"--my-option my-value\")
 })

 <p>The script generated by this example call of @('save-exec') contains a line
 such as the following (with the same convention for `\\' as before).  Notice
 that @(':host-lisp-args') can be modified at startup (without @('save-exec'))
 by setting environment variable @('SBCL_USER_ARGS').</p>

 @({
  exec \"/projects/sbcl-1.1.7-x86-64-linux/src/runtime/sbcl\" \\
       --dynamic-space-size 24000 --control-stack-size 64 \\
       --core \"/u/smith/my-saved_acl2.core\" --dynamic-space-size 50000 \\
       ${SBCL_USER_ARGS} \\
       --end-runtime-options \\
       --no-userinit --eval '(acl2::sbcl-restart)' \\
       --eval '(print \"HELLO\")' \\
       --end-toplevel-options \\
       --my-option my-value \\
       \"$@\"
 })

 <p>In general, the generated script is of one of the following forms (with the
 same convention for `\\' as before).</p>

 <blockquote>

 <p>For the case that @('inert-args') is @('nil'):</p>

 @({
  exec <lisp_executable> \\
       <ACL2_runtime_options> host-lisp-args --end-runtime-options \\
       <ACL2_toplevel_options> host-lisp-args \\
       \"$@\"
 })

 <p>For the case that @('inert-args') is non-@('nil'):</p>

 @({
  exec <lisp_executable> \\
       <ACL2_runtime_options> host-lisp-args --end-runtime-options \\
       <ACL2_toplevel_options> host-lisp-args --end-toplevel-options \\
       inert-args \"$@\"
 })

 </blockquote>

 <p>Notice that as before, when the generated script is invoked (for example,
 at the shell), additional command-line arguments provided at that time are
 passed to Lisp if and only if @('inert-args') is @('nil').  For SBCL, when
 they are passed to Lisp they are passed as toplevel options, not as runtime
 options.</p>")

(defxdoc search
  :parents (lists strings acl2-built-ins)
  :short "Search for a string or list in another string or list"
  :long "@({
  Example Forms:
  (search \"cd\" \"Cdabcdefcde\")                   ; = 4, index of first match
  (search \"cd\" \"Cdabcdefcde\" :test 'equal)      ; same as above
  (search \"cd\" \"Cdabcdefcde\" :from-end t)       ; = 8, index of last match
  (search \"cd\" \"Cdabcdefcde\" :start1 1)         ; = 1
  (search \"cd\" \"Cdabcdefcde\" :start2 5)         ; = 8
  (search \"cd\" \"Cdabcdefcde\" :test 'char-equal) ; = 0 (case-insensitive)
  (search \"ac\" \"Cdabcdefcde\")                   ; = nil
  (search '(a b) '(9 8 a b 7 6))                    ; = 2

  General Form:
  (search seq1 seq2 &key from-end test start1 start2 end1 end2)
 })

 <p>@('Search') indicates whether one string or list occurs as a (contiguous)
 subsequence of another string or list, respectively.  It returns @('nil') if
 no such match is found; otherwise it returns the (zero-based) index of the
 first match by default, but a non-@('nil') value of keyword argument
 @(':from-end') causes it to return the last match.  The @(':test') is
 @('equal') by default.  The other legal value for @(':test') is
 @('char-equal'), which can be given only for two strings, in which case the
 match is case-insensitive.  Finally, values of @(':start1') and @(':end1') for
 the first sequence, and of @(':start2') and @(':end2') for the second
 sequence, bound the portion of the respective sequence used for deciding on a
 match, though the index returned is always an index into the second sequence
 as a whole.</p>

 <p>The @(see guard) for calls of @('search') is given by a function,
 @('search-fn-guard'), which has the following requirements.</p>

 <ul>

 <li>The two arguments much both satisfy @(tsee true-listp) or else must both
 be strings, which must consist of standard characters (see @(see
 standard-char-p)) if the @(':test') is @(tsee char-equal).</li>

 <li>The @(':test') must evaluate to one of the symbols @(tsee equal) or
 @(tsee char-equal), where the latter is only allowed if the (first) two
 arguments are strings.</li>

 <li>The values of @(':start1'), @(':start2'), @(':end1'), and @(':end2') must
 all be natural numbers, where if omitted they default to 0, 0, the length
 @('len1') of the first argument, and the length @('len2') of the second
 argument, respectively.</li>

 <li>If @('start1') is the value of @(':start1'), defaulting as described just
 above, and similarly for the other start and end keywords and for lengths
 @('len1') and @('len2') as described just above, then: @('start1 <= end1 <=
 len1') and @('start2 <= end2 <= len2').</li>

 </ul>

 <p>@('Search') is a Common Lisp function (actually, a macro in ACL2).  See any
 Common Lisp documentation for more information.</p>

 <h3>Definition</h3>

 @(def search)
 @(def search-fn)
 @(def search-from-end)
 @(def search-from-start)")

(defxdoc second
  :parents (nth acl2-built-ins)
  :short "Second member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc serialize
  :parents (io)
  :short "Routines for saving ACL2 objects to files, and later restoring them"
  :long "<p>We thank Jared Davis for contributing the ``serialization''
 routines for saving ACL2 objects in files for later loading.</p>

 <p>We implement some routines for writing arbitrary ACL2 objects to files, and
 for loading those files later.  We usually call these \".sao\" files, which
 stands for (S)erialized (A)CL2 (O)bject.</p>

 <p>Our serialization scheme uses a compact, binary format that preserves
 structure sharing in the original object.  We optimize for read
 performance.</p>")

(defxdoc serialize-alternatives
  :parents (serialize)
  :short "Historic alternatives to the @(see serialize) routines."
  :long "<p>Routines @('compact-print-file') and @('compact-read-file') were
 previously built into ACL2.  Another option was to use the @('hons-archive')
 library.  These tools were deprecated and ultimately removed from ACL2.  If
 for some reason you need to use them, see @(see community-books) SVN revisions
 prior to 1314.</p>")

(defxdoc serialize-in-books
  :parents (serialize)
  :short "Using serialization efficiently in books"
  :long "<p>Our serialize scheme was developed in order to allow very large
 ACL2 objects to be loaded into books.  Ordinarily this is carried out using
 @(tsee serialize-read) within a @(tsee make-event), e.g.,</p>

 @({
    (make-event (mv-let (obj state)
                        (serialize-read \"my-file\")
                        (value `(defconst *my-file* ',obj))))
 })

 <p>But this scheme is not particularly efficient.</p>

 <p>During @(tsee certify-book), the actual call of @('serialize-read') is
 carried out, and this is typically pretty fast.  But then a number of possibly
 inefficient things occur.</p>

 <ul>

 <li> The ACL2 function @('bad-lisp-object') is run on the resulting object.
 This is memoized for efficiency, but may still take considerable time when the
 file is very large.</li>

 <li> The @(see checksum) of the resulting object is computed (though this is
 not the default; see @(see book-hash).  This is also memoized, but as before
 may still take some time.</li>

 <li> The object that was just read is then written into book.cert, essentially
 with @(tsee serialize-write).  This can take some time, and results in large
 certificate files.</li>

 </ul>

 <p>Then, during @(see include-book), the @('make-event') expansion is loaded.
 This is now basically just a @('serialize-read').</p>

 <p>The moral of the story is that using serialize will only help your
 @('certify-book') time, and it only impacts a portion of the overall time.</p>

 <p>To avoid this overhead, we have developed an UNSOUND alternative to
 @('serialize-read'), which is available only by loading an additional book.
 So, if the above scheme is not performing well for you, you may wish to see
 @(see unsound-read).</p>")

(defxdoc serialize-read
  :parents (serialize acl2-built-ins)
  :short "Read a serialized ACL2 object from a file"
  :long "<p>General form:</p>

 @({
   (serialize-read filename
                   [:hons-mode {:always, :never, :smart}]   ; :smart by default
                   [:verbosep  {t, nil}])                   ; nil by default
    -->
   (mv obj state)
 })

 <p>In the logic this is an oracle read.</p>

 <p>Under the hood, we try to read and return a serialized object from a file
 that was presumably created by @(tsee serialize-write).  On success we return
 the contents of the file.  Any failures (e.g., file not found, bad file
 contents, etc.) will result in a hard Lisp error.</p>

 <p>The @('filename') should be a string that gives the path to the file.</p>

 <p>The @('hons-mode') controls how whether to use @(tsee hons) or @(tsee cons)
 to restore the object.  The default mode is @(':smart'), which means that
 conses that were @(see normed) at the time of the file's creation should be
 restored with @('hons').  But you can override this and insist that @('hons')
 is to @(':always') or @(':never') be used, instead.</p>

 <p>Why would you use @(':never')?  If your object previously had a lot of
 honses, but you no longer have any need for them to be normed, then using
 @(':never') may sometimes be a lot faster since it can avoid @('hons') calls.
 On the other hand, if you are going to @(tsee hons-copy) some part of the
 file's contents, then it is likely faster to use @(':smart') or @(':always')
 instead of first creating normal conses and then copying them to build
 honses.</p>

 <p>The @(':verbosep') flag just controls whether to print some low-level
 details related to timing and memory usage as the file is being read.</p>")

(defxdoc serialize-write
  :parents (serialize acl2-built-ins)
  :short "Write an ACL2 object into a file"
  :long "<p>General form:</p>

 @({
   (serialize-write filename obj
                    [:verbosep  {t, nil}])    ; nil by default
    -->
   state
 })

 <p>In the logic this carries out an oracle read.</p>

 <p>Under the hood, we try to save @('obj') into the file indicated by
 @('filename'), which must be a string.  The object can later be recovered with
 @(tsee serialize-read).  We just return @('state'), and any failures (e.g.,
 file not openable) will result in a hard Lisp error.</p>

 <p>Writing objects to disk is generally slower than reading them back in since
 some analysis is required to convert an object into our @(see serialize)d
 object format.</p>

 <p>The @('verbosep') flag just says whether to print some low-level details
 related to timing and memory usage as the file is being written.</p>")

(defxdoc set-absstobj-debug
  :parents (defabsstobj)
  :short "Obtain debugging information upon atomicity violation for an abstract stobj"
  :long "<p>This @(see documentation) topic assumes familiarity with abstract
 stobjs.  See @(see defabsstobj).</p>

 <p>Below we explain what is meant by an error message such as the
 following.</p>

 @({
  ACL2 Error in CHK-ABSSTOBJ-INVARIANTS:  Possible invariance violation
  for an abstract stobj!  See :DOC set-absstobj-debug, and PROCEED AT
  YOUR OWN RISK.
 })

 <p>The use of @('(set-absstobj-debug t)') will make this error message more
 informative, as follows, at the cost of slower execution &mdash; but in
 practice, the slowdown may be negligible (more on that below).</p>

 @({
  ACL2 Error in CHK-ABSSTOBJ-INVARIANTS:  Possible invariance violation
  for an abstract stobj!  See :DOC set-absstobj-debug, and PROCEED AT
  YOUR OWN RISK.  Evaluation was aborted under a call of abstract stobj
  export UPDATE-FLD-NIL-BAD.
 })

 <p>You may be best off starting a new ACL2 session if you see one of the
 errors above.  But you can continue at your own risk.  With a trust tag (see
 @(see defttag)), you can even fool ACL2 into thinking nothing is wrong, and
 perhaps you can fix up the abstract stobj so that indeed, nothing really is
 wrong.  See the community book @('books/misc/defabsstobj-example-4.lisp') for
 how to do that.  That book also documents the @(':always') keyword and a
 special value for the first argument, @(':RESET').</p>

 @({
  Examples:
  (set-absstobj-debug t)                 ; obtain extra debug info, as above
  (set-absstobj-debug t :event-p t)      ; same as above
  (set-absstobj-debug t
                      :on-skip-proofs t) ; as above, but even in include-book
  (set-absstobj-debug t :event-p nil)    ; returns one value, not error triple
  (set-absstobj-debug nil)               ; avoid extra debug info (default)

  General Form:
  (set-absstobj-debug val
                      :event-p        event-p        ; default t
                      :always         always         ; default nil
                      :on-skip-proofs on-skip-proofs ; default nil
                      )
 })

 <p>where the keyword arguments are optional with defaults as indicated above,
 and all supplied arguments are evaluated except for @('on-skip-proofsp'),
 which must be Boolean (if supplied).  Keyword arguments are discussed at the
 end of this topic.</p>

 <p>Recall (see @(see defabsstobj)) that for any exported function whose
 @(':EXEC') function might (according to ACL2's heuristics) modify the concrete
 stobj non-atomically, one must specify @(':PROTECT t').  This results in extra
 code generated for the exported function, which provides a check that
 atomicity was not actually violated by a call of the exported function.  The
 extra code might slow down execution, but perhaps only negligibly in typical
 cases.  If you can tolerate a bit extra slow-down, then evaluate the form
 @('(set-absstobj-debug t)').  Subsequent such errors will provide additional
 information, as in the example displayed earlier in this documentation
 topic.</p>

 <p>Finally we document the keyword arguments, other than @(':ALWAYS'), which
 is discussed in a book as mentioned above.  When the value of @(':EVENT-P') is
 true, which it is by default, the call of @('set-absstobj-debug') will expand
 to an event.  That event is a call of @(tsee value-triple).  In that case,
 @(':ON-SKIP-PROOFS') is passed to that call so that @('set-absstobj-debug')
 has an effect even when proofs are being skipped, as during @(tsee
 include-book).  That behavior is the default; that is, @(':ON-SKIP-PROOFS') is
 @('nil') by default.  Also see @(see value-triple).  The value of keyword
 @(':ON-SKIP-PROOFS') must always be either @('t') or @('nil'), but other than
 that, it is ignored when @('EVENT-P') is @('nil').</p>")

(defxdoc set-backchain-limit
  :parents (backchain-limit)
  :short "Sets the backchain-limit used by the type-set and rewriting mechanisms"
  :long "<p>Note: This is an event!  It does not print the usual event summary
 but nevertheless changes the ACL2 logical @(see world) and is so recorded.
 Moreover, its effect is to set the @(tsee acl2-defaults-table), and hence its
 effect is @(tsee local) to the book or @(tsee encapsulate) form containing it;
 see @(see acl2-defaults-table).</p>

 <p>This event sets the global @(tsee backchain-limit) used by the ACL2
 type-set and rewriting mechanisms.  Its value may be a cons whose car and cdr
 are each either @('nil') or a non-negative integer.  Its value @('x') may also
 be @('nil') or a non-negative integer, which is treated as a cons whose car
 and cdr are both @('x').</p>

 <p>The car is used to limit backchaining used by the ACL2 type-set mechanism,
 while the cdr is used to limit backchaining used by the rewriting mechanism.
 See @(see backchain-limit) for details about how backchain-limits are used.
 Rewrite backchain limits may also be installed at the level of hints; see
 @(see hints) for a discussion of @(':backchain-limit-rw').</p>

 @({
  :set-backchain-limit nil  ; do not impose any additional limits
  :set-backchain-limit 0    ; allow only type-set reasoning for rewriting
                            ; hypotheses
  :set-backchain-limit 500  ; allow backchaining to a depth of no more
                            ; than 500 for rewriting hypotheses
  (set-backchain-limit 500) ; same as above
  :set-backchain-limit (500 500)
                            ; same as above
  (set-backchain-limit '(500 500))
                            ; same as above
  (set-backchain-limit '(3 500))
                            ; allow type-set backchaining to a depth of no more
                            ; than 3 and rewriter backchaining to a depth of no
                            ; more than 500
 })

 <p>The default limit is @('(nil nil)').</p>")

(defxdoc set-bad-lisp-consp-memoize
  :parents (memoize)
  :short "Turn off or on memoization of raw Lisp function @('bad-lisp-consp')"
  :long "<p>WARNING: This is an advanced utility, recommended only for users
 who understand ACL2 at a deep level.  Calling this function can permanently
 alter the performance of low-level raw Lisp function
 @('bad-lisp-consp').</p>

 <p>Invoke @('(set-bad-lisp-consp-memoize t)') to memoize raw Lisp function
 @('bad-lisp-consp'), which is memoized by default in ACL2 but not ACL2(p).
 This call has no effect if @('bad-lisp-consp') is already memoized.
 Similarly, invoke @('(set-bad-lisp-consp-memoize nil)') to unmemoize
 @('bad-lisp-consp'); this call has no effect if @('bad-lisp-consp') is
 already unmemoized.</p>")

(defxdoc set-body
  :parents (definition events)
  :short "Set the definition body"
  :long "@({
  Examples:
  (set-body foo (:definition foo)) ; restore original definition of foo
  (set-body foo foo) ; same as just above
  (set-body foo my-foo-def) ; use my-foo-def for the body of foo
  (set-body foo (:definition my-foo-def)) ; same as just above
 })

 <p>Rules of class @(':')@(tsee definition) can install a new definition body,
 used for example by @(':expand') @(see hints).  See @(see definition) and also
 see @(see hints) for a detailed discussion of the @(':install-body') fields of
 @(':')@(tsee definition) rules and their role in @(':expand') hints.</p>

 <p>There may be several such definitions, but by default, the latest one is
 used by @(':expand') hints.  Although the @(':with') keyword may be used in
 @(':expand') hints to override this behavior locally (see @(see hints)), it
 may be convenient to install a definition for expansion other than the latest
 one &mdash; for example, the original definition.  @('Set-body') may be used
 for this purpose.</p>

 @({
  General Form:
  (set-body function-symbol rule-name)
 })

 <p>where @('rule-name') is either a @(':definition') @(see rune) or is a
 function symbol, @('sym'), which represents the rune @('(:definition
 sym)').</p>

 <p>You can view all definitions available for expansion; see @(see
 show-bodies).</p>")

(defxdoc set-bogus-defun-hints-ok
  :parents (defun)
  :short "Allow unnecessary @('(xargs :hints ...)') and @(see measure)s."
  :long "@({
  General Forms:
  (set-bogus-defun-hints-ok t)
  (set-bogus-defun-hints-ok nil)
  (set-bogus-defun-hints-ok :warn)
 })

 <p>By default, ACL2 causes an error when either of the keywords @(':')@(tsee
 hints) or @(':measure') is supplied in an @(tsee xargs) @(see declare) form
 for a @(':')@(tsee logic) mode non-recursive definition.  That restriction
 also applies to @(':')@(tsee program) mode definitions in the case of
 @(':measure').  This behavior can be defeated with
 @('(set-bogus-defun-hints-ok t)'), or if you still want to see a warning in
 such cases, @('(set-bogus-defun-hints-ok :warn)').  This utility should
 perhaps be called @('set-bogus-defun-hints-and-measures-ok'), but we retain
 its original name (from when it did not deal with bogus measures).</p>")

(defxdoc set-bogus-measure-ok
  :parents (defun)
  :short "Allow unnecessary @(see measure)s and @('(xargs :hints ...)')."
  :long "<p>A call @('(set-bogus-measure-ok X)') is just an abbreviation for
 @('(set-bogus-defun-hints-ok X)').  See @(see set-bogus-defun-hints-ok).</p>")

(defxdoc set-bogus-mutual-recursion-ok
  :parents (mutual-recursion)
  :short "Allow unnecessary ``mutual recursion''"
  :long "@({
  Examples:
  (set-bogus-mutual-recursion-ok t)
  (set-bogus-mutual-recursion-ok nil)
  (set-bogus-mutual-recursion-ok :warn)
 })

 <p>By default, ACL2 checks that when a ``clique'' of more than one function is
 defined simultaneously (using @(tsee mutual-recursion) or @(tsee defuns)),
 then every body calls at least one of the functions in the ``clique.''  Below,
 we refer to definitional events that fail this check as ``bogus'' mutual
 recursions.  The check is important because ACL2 does not store induction
 schemes for functions defined with other functions in a @(tsee
 mutual-recursion) or @(tsee defuns) event.  Thus, ACL2 may have difficulty
 proving theorems by induction that involve such functions.  Moreover, the
 check can call attention to bugs, since users generally intend that their
 mutual recursions are not bogus.</p>

 <p>Nevertheless, there are times when it is advantageous to allow bogus mutual
 recursions, for example when they are generated mechanically, even at the
 expense of losing stored induction schemes.  The first example above allows
 bogus mutual recursion.  The second example disallows bogus mutual recursion;
 this is the default.  The third example allows bogus mutual recursion, but
 prints an appropriate warning.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.
 Moreover, its effect is to set the @(tsee acl2-defaults-table), and hence its
 effect is @(tsee local) to the book or @(tsee encapsulate) form containing it;
 see @(see acl2-defaults-table).</p>

 @({
  General Form:
  (set-bogus-mutual-recursion-ok flg)
 })

 <p>where @('flg') is either @('t'), @('nil'), or @(':warn').</p>")

(defxdoc set-case-split-limitations
  :parents (miscellaneous)
  :short "Set the @(see case-split-limitations)"
  :long "<p>Also see @(see case-split-limitations) for an example of how this
 utility inhibits case splitting.</p>

 @({
  Examples:
  (set-case-split-limitations '(500 100))
  (set-case-split-limitations 'nil)
  (set-case-split-limitations '(500 nil))
 })

 <p>The first of these prevents @('clausify') from trying the
 subsumption/replacement (see below) loop if more than 500 clauses are
 involved.  It also discourages the clause simplifier from splitting into more
 than 100 cases at once.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.
 Moreover, its effect is to set the @(tsee acl2-defaults-table), and hence its
 effect is @(tsee local) to the book or @(tsee encapsulate) form containing it;
 see @(see acl2-defaults-table).</p>

 <p>See @(see hints) for discussion of a related hint,
 @(':case-split-limitations').  Also see @(see splitter) for information about
 reports on rules that may be responsible for case splits.</p>

 @({
  General Form:
  (set-case-split-limitations lst)
 })

 <p>where @('lst') is either @('nil') (denoting a list of two @('nil')s), or a
 list of length two, each element of which is either @('nil') or a natural
 number.  When @('nil') is used as an element, it is treated as positive
 infinity.  The default setting is @('(500 100)').</p>

 <p>The first number specifies the maximum number of clauses that may
 participate in the ``subsumption/replacement'' loop.  Because of the expensive
 nature of that loop (which compares every clause to every other in a way that
 is quadratic in the number of literals in the clauses), when the number of
 clauses exceeds about 1000, the system tends to ``go into a black hole,''
 printing nothing and not even doing many garbage collections (because the
 subsumption/replacement loop does not create new clauses so much as it just
 tries to delete old ones).  The initial setting is lower than the threshold at
 which we see noticeably bad performance, so you probably will not see this
 behavior unless you have raised or disabled the limit.</p>

 <p>Why raise the subsumption/replacement limit?  The subsumption/replacement
 loop cleans up the set of subgoals produced by the simplifier.  For example,
 if one subgoal is</p>

 @({
  (implies (and p q r) s)            [1]
 })

 <p>and another is</p>

 @({
  (implies (and p (not q) r) s)      [2]
 })

 <p>then the subsumption/replacement loop would produce the single subgoal</p>

 @({
  (implies (and p r) s)              [3]
 })

 <p>instead.  This cleanup process is simply skipped when the number of
 subgoals exceeds the subsumption/replacement limit.  But each subgoal must
 nonetheless be proved.  The proofs of [1] and [2] are likely to duplicate much
 work, which is only done once in proving [3].  So with a low limit, you may
 find the system quickly produces a set of subgoals but then takes a long time
 to prove that set.  With a higher limit, you may find the set of subgoals to
 be ``cleaner'' and faster to prove.</p>

 <p>Why lower the subsumption/replacement limit?  If you see the system go into
 a ``black hole'' of the sort described above (no output, and few garbage
 collections), it could due to the subsumption/replacement loop working on a
 large set of large subgoals.  You might temporarily lower the limit so that it
 begins to print the uncleaned set of subgoals.  Perhaps by looking at the
 output you will realize that some function can be disabled so as to prevent
 the case explosion.  Then raise or disable the limit again!</p>

 <p>The second number in the case-split-limitations specifies how many case
 splits the simplifier will allow before it begins to shut down case splitting.
 In normal operation, when a literal rewrites to a nest of @('IF')s, the system
 simplifies all subsequent literals in all the contexts generated by walking
 through the nest in all possible ways.  This can also cause the system to ``go
 into a black hole'' printing nothing except garbage collection messages.  This
 ``black hole'' behavior is different from than mentioned above because space
 is typically being consumed at a prodigious rate, since the system is
 rewriting the literals over and over in many different contexts.</p>

 <p>As the simplifier sweeps across the clause, it keeps track of the number of
 cases that have been generated.  When that number exceeds the second number in
 case-split-limitations, the simplifier stops rewriting literals.  The
 remaining, unrewritten, literals are copied over into the output clauses.
 @('IF')s in those literals are split out, but the literals themselves are not
 rewritten.  Each output clause is then attacked again, by subsequent
 simplification, and eventually the unrewritten literals in the tail of the
 clause will be rewritten because the earlier literals will stabilize and stop
 producing case splits.</p>

 <p>The default setting of 100 is fairly low.  We have seen successful proofs
 in which thousands of subgoals were created by a simplification.  By setting
 the second number to small values, you can force the system to case split
 slowly.  For example, a setting of 5 will cause it to generate ``about 5''
 subgoals per simplification.</p>

 <p>You can read about how the simplifier works in the book Computer-Aided
 Reasoning: An Approach (Kaufmann, Manolios, Moore); also see @(see
 introduction-to-the-theorem-prover) for a detailed tutorial on using the ACL2
 prover.  If you think about it, you will see that with a low case limit, the
 initial literals of a goal are repeatedly simplified, because each time a
 subgoal is simplified we start at the left-most subterm.  So when case
 splitting prevents the later subterms from being fully split out, we revisit
 the earlier terms before getting to the later ones.  This can be good.
 Perhaps it takes several rounds of rewriting before the earlier terms are in
 normal form and then the later terms rewrite quickly.  But it could happen
 that the earlier terms are expensive to rewrite and do not change, making the
 strategy of delayed case splits less efficient.  It is up to you.</p>

 <p>Sometimes the simplifier produces more clauses than you might expect, even
 with case-split-limitations in effect.  As noted above, once the limit has
 been exceeded, the simplifier does not rewrite subsequent literals.  But
 @('IF')s in those literals are split out nonetheless.  Furthermore, the
 enforcement of the limit is &mdash; as described above &mdash; all or nothing:
 if the limit allows us to rewrite a literal then we rewrite the literal fully,
 without regard for limitations, and get as many cases as ``naturally'' are
 produced.  It quite often happens that a single literal, when expanded, may
 grossly exceed the specified limits.</p>

 <p>If the second ``number'' is @('nil') and the simplifier is going to produce
 more than 1000 clauses, a ``helpful little message'' to this effect is printed
 out.  This output is printed to the system's ``comment window'' not the
 standard proofs output.</p>")

(defxdoc set-cbd
  :parents (books-reference)
  :short "To set the connected book directory"
  :long "@({
  Example Forms:
  ACL2 !>:set-cbd \"/usr/home/smith/\"
  ACL2 !>:set-cbd \"my-acl2/books\"
 })

 <p>See @(see cbd) for a description of the connected book directory.</p>

 @({
  General Form:
  (set-cbd str)
 })

 <p>where @('str') is a nonempty string that represents the desired directory
 (see @(see pathname)).  This command sets the connected book directory (see
 @(see cbd)) to the string representing the indicated directory.  Thus, this
 command may determine which files are processed by @(tsee include-book) and
 @(tsee certify-book) @(see command)s typed at the top-level.  However, the
 @(tsee cbd) is also temporarily set by those two book processing @(see
 command)s.</p>

 <p>IMPORTANT: Pathnames in ACL2 are in the Unix (trademark of AT&amp;T) style.
 That is, the character ``@('/')'' separates directory components of a
 pathname, and pathnames are absolute when they start with this character, and
 relative otherwise.  See @(see pathname).</p>")

(defxdoc set-check-invariant-risk

; If someone asks for "assistance in writing such a utility" (as noted near the
; end of this topic), point them to the 'invariant-risk property.  If the value
; of that property is FOO and the top-level call is BAR, then the idea is
; simply to find a function symbol in the body of BAR whose
; 'invariant-risk property is also FOO, and then continue until reaching FOO
; (which will have FOO as its own value of that property).

  :parents (programming advanced-features guard debugging invariant-risk)
  :short "Affect certain @(see program)-mode updates to @(see stobj)s or @(see
 arrays)"
  :long "<p>See @(see invariant-risk) for an introduction to the notion of
 invariant-risk.  Also see @(see set-register-invariant-risk) for a way to
 avoid marking a specific set of functions as having invariant-risk, which can
 be much safer than avoiding invariant-risk checking for all functions at
 runtime as described below.</p>

 <p>Briefly put, if a syntactic analysis suggests that the call of a
 @(':')@(tsee program)-mode function can lead to an ill-guarded call of a @(see
 stobj) updater or of @(tsee aset1) or @(tsee aset2), then ACL2 considers such
 a call to be an ``invariant-risk call''.  There are four different ways that
 ACL2 can handle such a call, corresponding to four different values of the
 ``invariant-risk mode'', which is the value obtained by evaluating
 @('(get-check-invariant-risk state)').  The default invariant-risk mode is
 @(':WARNING'): in that mode, ACL2 prints a warning when encountering a topmost
 invariant-risk call and uses a slower mode of execution in order to avoid
 ill-guarded calls as discussed above.  Mode @('T') has the same behavior, but
 without the warning.  Mode @(':ERROR') causes a break when encountering a
 topmost invariant-risk call; the Lisp should give you the option of
 continuing (as though the mode were @('T')) or aborting, as you choose.
 Finally, mode @('NIL') &mdash; which is unsafe and hence involves a trust
 tag (see @(see defttag)), as discussed below &mdash; avoids any special
 treatment for invariant-risk calls.</p>

 <p>The utility, @('set-check-invariant-risk'), is provided for changing
 invariant-risk mode.  The simplest case is when that utility is only called
 with one argument, in which case, that argument becomes the new invariant-risk
 mode, as follows.</p>

 @({
 (set-check-invariant-risk :ERROR)   ; new mode is :ERROR
 (set-check-invariant-risk :WARNING) ; new mode is :WARNING (the default)
 (set-check-invariant-risk T)        ; new mode is T
 (set-check-invariant-risk NIL)      ; new mode is NIL
 })

 <p>The argument is evaluated (to itself when given one of the four constants
 shown above).  There must be an active trust tag in order to set the
 invariant-risk mode to @('NIL').  However, ACL2 arranges automatically to
 create a temporary trust tag when invoking @('set-check-invariant-risk') on an
 expression that is other than one of the symbols @(':ERROR'), @(':WARNING'),
 or @('T').</p>

 <p>An environment variable, @('ACL2_CHECK_INVARIANT_RISK'), provides a
 convenient way to evaluate one of these forms automatically when ACL2 is
 invoked.  When that environment variable has a value other than the empty
 string, the value is converted to a symbol after converting to upper-case with
 the function @(tsee string-upcase), and then corresponding call is make
 automatically (after loading the @(see acl2-customization) file, if any).</p>

 @({
 \"error\", \":error\" ==> (set-check-invariant-risk :ERROR)
 \"warning\", \":warning\" ==> (set-check-invariant-risk :WARNING)
 \"t\" ==> (set-check-invariant-risk T)
 \"nil\" ==> (set-check-invariant-risk NIL)
 })

 <p>Whether by direct user evaluation or environment variable, these calls
 simply set a certain global parameter, @(''check-invariant-risk')
 (technically, a @(see state) global variable).  However, they are not embedded
 event forms (see @(see embedded-event-form): they cannot appear at the top
 level of books, @(tsee encapsulate) @(see events), or @(tsee progn) events.  A
 non-nil second (optional) argument causes an @(tsee acl2-defaults-table) entry
 to be made, associating the key @(':check-invariant-risk') with the
 invariant-risk mode.  Thus, the following forms are embedded event forms.
 Notice the new ``mode'', @(':CLEAR'), which behaves as though removing the key
 @(':check-invariant-risk') from the @(tsee acl2-defaults-table).</p>

 @({
 (set-check-invariant-risk :ERROR   t)
 (set-check-invariant-risk :WARNING t)
 (set-check-invariant-risk t        t)
 (set-check-invariant-risk NIL      t)
 (set-check-invariant-risk :CLEAR t) ; avoid using table to determine mode
 })

 <p>As before, the value @('NIL') requires an active trust tag; but unlike
 before, ACL2 does not create a temporary trust tag, but instead expect the
 user to have created one already.  Note also that changes to the
 @('acl2-defaults-table') are automatically local to a book or @(tsee
 encapsulate) event in which they occur; @(tsee acl2-defaults-table).
 Therefore, do not surround the forms just above with @(tsee LOCAL).</p>

 <p>When the @(tsee acl2-defaults-table) associates the key
 @(':check-invariant-risk') with any value (as in the calls above) other than
 @(':CLEAR'), then the invariant-risk mode is actually the ``minimum'' of that
 value and the value of the global parameter, @(''check-invariant-risk'), where
 the modes are ordered from greatest to least as shown in the displays above.
 An @(see observation) is printed when the new mode does not change: for
 example, if you start your ACL2 session by evaluating
 @('(set-check-invariant-risk :ERROR t)'), then the invariant-risk mode will be
 the minimum of the existing (default) value of @(':WARNING') and the proposed
 value (newly stored in the @('acl2-defaults-table') of @(':ERROR'); that
 minimum is @(':WARNING'), so the mode will remain @(':WARNING') and an @(see
 observation) will be printed to that effect.  You can see all the relevant
 mode values as follows.</p>

 @({
 ; current invariant-risk mode (:WARNING by default):
 (get-check-invariant-risk state)

 ; invariant-risk mode stored in global parameter 'check-invariant-risk:
 (@ check-invariant-risk)

 ; invariant-risk mode stored in the acl2-defaults-table:
 (table acl2-defaults-table :check-invariant-risk)
 })

 <p>The following log illustrates the interaction of the two ways of setting
 the invariant-risk mode (state global and table).</p>

 @({
 ACL2 !>(set-check-invariant-risk :error t)

 ACL2 Observation in SET-CHECK-INVARIANT-RISK:  No change is being made
 in the value computed by (GET-CHECK-INVARIANT-RISK STATE).  This happens
 when the value of state global 'check-invariant-risk is less than the
 new table value; see :DOC set-check-invariant-risk.
  :ERROR
 ACL2 !>(get-check-invariant-risk state)
 :WARNING
 ACL2 !>(@ check-invariant-risk)
 :WARNING
 ACL2 !>(set-check-invariant-risk :error)
  :ERROR
 ACL2 !>(@ check-invariant-risk)
 :ERROR
 ACL2 !>(get-check-invariant-risk state)
 :ERROR
 ACL2 !>(set-check-invariant-risk t t)
  T
 ACL2 !>(get-check-invariant-risk state)
 T
 ACL2 !>(set-check-invariant-risk :warning)

 ACL2 Observation in SET-CHECK-INVARIANT-RISK:  No change is being made
 in the value computed by (GET-CHECK-INVARIANT-RISK STATE), because
 the new value of state global 'check-invariant-risk is greater than
 the table value; see :DOC set-check-invariant-risk.
  :WARNING
 ACL2 !>(get-check-invariant-risk state)
 T
 ACL2 !>(set-check-invariant-risk :clear t)
  :CLEAR
 ACL2 !>(get-check-invariant-risk state)
 :WARNING
 ACL2 !>
 })

 <p>Note that the handling of an invariant-risk call of a function, @('f'),
 depends on the current invariant-risk mode, not on the mode in place when
 @('f') was defined.</p>

 <p>It might not be obvious how a given function call could lead to an
 ill-guarded call of a @(see stobj) updater or of a primitive with
 invariant-risk such as @(see aref1).  It should be reasonably straightforward
 to write a utility that provides this information; contact the ACL2
 implementors if you want assistance in writing such a utility.</p>")

(defxdoc set-checkpoint-summary-limit
  :parents (set-gag-mode)
  :short "Control printing of key checkpoints upon a proof's failure"
  :long "<p>See @(see set-gag-mode) for a discussion of key checkpoints.</p>

 @({
  Examples:

  ; (Default) When a proof fails, print all key checkpoints before
  ; induction but at most 3 key checkpoints after induction:
  (set-checkpoint-summary-limit (nil . 3))

  ; When a proof fails, print at most 3 key checkpoints before
  ; induction but all 3 key checkpoints after induction:
  (set-checkpoint-summary-limit (3 . nil))

  ; When a proof fails, print at most 3 key checkpoints before
  ; induction and at most 5 key checkpoints after induction:
  (set-checkpoint-summary-limit (3 . 5))

  ; When a proof fails, print at most 3 key checkpoints before
  ; induction and at most 3 key checkpoints after induction:
  (set-checkpoint-summary-limit (3 . 3))
  ; or equivalently,
  (set-checkpoint-summary-limit 3)

  ; When a proof fails, print all key checkpoints:
  (set-checkpoint-summary-limit (nil . nil))
  ; or equivalently,
  (set-checkpoint-summary-limit nil)

  ; When a proof fails, print no information at all about key checkpoints:
  (set-checkpoint-summary-limit t)

  General Forms:
  (set-checkpoint-summary-limit (n1 . n2))
  (set-checkpoint-summary-limit n)
  (set-checkpoint-summary-limit t)
 })

 <p>where each of @('n1') and @('n2') is a natural number or @('nil').  For the
 second form, @('n') can be a natural number or @('nil') and is treated as
 @('(n . n)').  The value @('t') inhibits all printing of checkpoint summary
 information.  The values @('n1') and @('n2') determine printing of key
 checkpoints generated before the first induction and generated after the first
 induction, respectively, where at most @('n1') or @('n2') (respectively) such
 key checkpoints are printed unless the value is @('nil'), in which case there
 is no limitation.</p>

 <p>The argument @('x') for @('set-checkpoint-summary-limit'), as described
 above, may be quoted, i.e. supplied as @(''x') or @('(quote x)').  Thus, you
 may use the keyword form (see @(see keyword-commands)) if you prefer, for
 example:</p>

 @({
  :set-checkpoint-summary-limit (nil . 3)
 })

 <p>To see the current limit, invoke @('(checkpoint-summary-limit)').</p>

 <p>Note that if some subgoal in a set of key checkpoints is @('NIL'), then
 such a subgoal will be printed first in the corresponding list, provided of
 course that the list isn't entirely ignored because of a limit of 0.  See
 @(see nil-goal).</p>")

(defxdoc set-compile-fns
  :parents (compilation)
  :short "Have each function compiled as you go along."
  :long "@({
  Example Forms:
  (set-compile-fns t)    ; new functions compiled after DEFUN
  (set-compile-fns nil)  ; new functions not compiled after DEFUN
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 <p>Also see @(see comp), because it may be more efficient in some Common Lisps
 to compile many functions at once rather than to compile each one as you go
 along.</p>

 @({
  General Form:
  (set-compile-fns term)
 })

 <p>where @('term') is a variable-free term that evaluates to @('t') or
 @('nil').  This macro is equivalent to</p>

 @({
  (table acl2-defaults-table :compile-fns term)
 })

 <p>and hence is @(tsee local) to any @(see books) and @(tsee encapsulate)
 @(see events) in which it occurs; see @(see acl2-defaults-table).  However,
 unlike the above simple call of the @(tsee table) event function (see @(see
 table)), no output results from a @('set-compile-fns') event.</p>

 <p>@('Set-compile-fns') may be thought of as an event that merely sets a flag
 to @('t') or @('nil').  The flag's effect is felt when functions are defined,
 as with @(tsee defun).  If the flag is @('t'), functions are automatically
 compiled after they are defined, as are their executable-counterparts (see
 @(see evaluation)).  Otherwise, functions are not automatically compiled.
 Exception: The flag has no effect when explicit compilation is suppressed; see
 @(see compilation).</p>

 <p>Because @('set-compile-fns') is an event, the old value of the flag is
 restored when a @('set-compile-fns') event is undone.</p>

 <p>Even when @(':set-compile-fns t') has been executed, functions are not
 individually compiled when processing an @(tsee include-book) event.  If you
 wish to include a book of compiled functions, we suggest that you first
 certify it with the @(see compilation) flag set (see @(see certify-book)) or
 else compile the book by supplying the appropriate @('load-compiled-file')
 argument to @(tsee include-book).  More generally, @(see compilation) via
 @('set-compile-fns') is suppressed when the @(see state) global variable
 @(tsee ld-skip-proofsp) has value @(''')@(tsee include-book).</p>")

(defxdoc set-compiler-enabled
  :parents (compilation)
  :short "Disable @(see compilation)."
  :long "<p>For a thorough discussion of this utility, see @(see compilation).
 Probably its most common use is the following, in order to prohibit @(tsee
 include-book) from attempting to include compiled files:</p>
 @({
 (set-compiler-enabled nil state)
 })")

(defxdoc set-debugger-enable
  :parents (debugging)
  :short "Control whether Lisp errors and breaks invoke the Lisp debugger"
  :long "@({
  Forms (see below for explanations and GCL exceptions):

  (set-debugger-enable t)         ; enable breaks into the raw Lisp debugger
  (set-debugger-enable :break)    ; same as above
  :set-debugger-enable t          ; same as above
  (set-debugger-enable :break-bt) ; as above, but print a backtrace first
  (set-debugger-enable :bt-break) ; as above, but print a backtrace first
  (set-debugger-enable :bt)       ; print a backtrace but do not enter debugger
  (set-debugger-enable :never)    ; disable all breaks into the debugger
  (set-debugger-enable nil)       ; disable debugger except when calling break$
 })

 <p><i>Introduction.</i> Suppose we define @('foo') in @(':')@(tsee program)
 mode to take the @(tsee car) of its argument.  This can cause a raw Lisp
 error.  ACL2 will then return control to its top-level loop unless you enable
 the Lisp debugger, as shown below (except: the error message can take quite a
 different form in non-ANSI GCL).</p>

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

    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)
    ***********************************************
    ************ ABORTING from raw Lisp ***********
    ********** (see :DOC raw-lisp-error) **********
    Error:  Attempt to take the car of 3 which is not listp.
    ***********************************************

    If you didn't cause an explicit interrupt (Control-C),
    then the root cause may be call of a :program mode
    function that has the wrong guard specified, or even no
    guard specified (i.e., an implicit guard of t).
    See :DOC guards.

    To enable breaks into the debugger (also see :DOC acl2-customization):
    (SET-DEBUGGER-ENABLE T)
    ACL2 !>(SET-DEBUGGER-ENABLE T)
    <state>
    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]
 })

 <p><i>Details.</i> ACL2 usage is intended to take place inside the ACL2
 read-eval-print loop (see @(see lp)).  Indeed, in most Lisp implementations
 ACL2 comes up inside that loop, as evidenced by the prompt:</p>

 @({
  ACL2 !>
 })

 <p>However, one can occasionally hit a raw Lisp error.  Here is the above
 example again, this time for a GCL implementation, which unfortunately gives a
 slightly less aesthetic report.</p>

 @({
    ACL2 !>(foo 3)

    Error: 3 is not of type LIST.
    Fast links are on: do (si::use-fast-links nil) for debugging
    Error signalled by CAR.
    Backtrace: funcall > system:top-level > lisp:lambda-closure > lp > acl2_*1*_acl2::foo > foo > car > system:universal-error-handler > system::break-level-for-acl2 > let* > UNLESS
    ACL2 !>
 })

 <p>Here, the user has defined @('foo') in @(':')@(tsee program) mode, with an
 implicit @(see guard) of @('t').  The ACL2 evaluator therefore called the Lisp
 evaluator, which expected @('nil') or a @(tsee consp) argument to @(tsee
 car).</p>

 <p>By default, ACL2 will return to its top-level loop (at the same level of
 @(tsee LD)) when there is a raw Lisp error, as though a call of @(tsee ER)
 with flag @('HARD') has been evaluated.  If instead you want to enter the raw
 Lisp debugger in such cases, evaluate the following form.</p>

 @({
  (set-debugger-enable t)
 })

 <p>You can subsequently return to the default behavior with:</p>

 @({
  (set-debugger-enable nil)
 })

 <p>Either way, you can enter the Lisp debugger from within the ACL2 loop by
 evaluating @('(')@(tsee break$)@(')').  If you want @('break$') disabled, then
 evaluate the following, which disables entry to the Lisp debugger not only for
 Lisp errors but also when executing @('(break$)').</p>

 @({
  (set-debugger-enable :never)
 })

 <p>The discussion above also applies to interrupts (from @('Control-C')) in
 some, but not all, host Common Lisps &mdash; perhaps all except for non-ANSI
 GCL, where interrupts will likely always put you into the debugger.</p>

 <p>It remains to discuss options @(':break'), @(':bt'), @(':break-bt'), and
 @(':bt-break').  Option @(':break') is synonymous with option @('t'), while
 option @(':bt') prints a backtrace.  Options @(':break-bt') and @(':bt-break')
 are equivalent, and each has the combined effect of @(':bt') and @(':break'):
 a backtrace is printed and then the debugger is entered.</p>

 <p>Note that @('set-debugger-enable') applies not only to raw Lisp errors, but
 also to ACL2 errors: those affected by @(tsee break-on-error).  However, for
 ACL2 errors, entering the debugger is controlled only by @('break-on-error'),
 not by @('set-debugger-enable').  For ACL2 errors encountered after evaluating
 @('(break-on-error t)'), the @('set-debugger-enable') values of @(':bt'),
 @(':break-bt'), and @(':bt-break') will result in the same effect: in many
 host Lisps, this effect will be to cause a backtrace to be printed.</p>

 <p>Remark for Common Lisp hackers (except for the case that the host Lisp is
 non-ANSI GCL).  You can customize the form of the backtrace printed by
 entering raw Lisp (with @(':q')) and then redefining function
 @('print-call-history'), whose definition immediately precedes that of
 @('break-on-error') in ACL2 source file @('ld.lisp').  Of course, all bets are
 off when defining any function in raw Lisp, but as a practical matter you are
 probably fine as long as your books are ultimately certified with an
 unmodified copy of ACL2.  If you come up with improvements to
 @('print-call-history'), please pass them along to the ACL2
 implementors.</p>")

(defxdoc set-default-backchain-limit
  :parents (backchain-limit)
  :short "Sets the default backchain-limit used when admitting a rule"
  :long "<p>Note: This is an event!  It does not print the usual event summary
 but nevertheless changes the ACL2 logical @(see world) and is so recorded.
 Moreover, its effect is to set the @(tsee acl2-defaults-table), and hence its
 effect is @(tsee local) to the book or @(tsee encapsulate) form containing it;
 see @(see acl2-defaults-table).</p>

 <p>This event sets the default @(tsee backchain-limit) used when a new @(tsee
 rewrite), @(tsee linear), @(tsee meta), or @(tsee type-prescription) rule is
 admitted.  Its value may be a two-element list whose elements are each either
 @('nil') or a non-negative integer.  Its value @('x') may also be @('nil') or
 a non-negative integer, which is treated as the two element list @('(x
 x)').</p>

 <p>The first element of the list is used to limit backchaining for a rule of
 class @(tsee type-prescription) while the second element is used to limit
 backchaining for the other three classes of rules mentioned above.  See @(see
 backchain-limit) for details about how backchain-limits are used.  The
 examples below assume that a new rule doesn't itself specify a value for
 @(':backchain-limit-lst').</p>

 @({
  :set-default-backchain-limit nil  ; do not impose backchain limits for the
                                    ; rule
  :set-default-backchain-limit 0    ; allow only type-set reasoning for
                                    ; relieving a new rule's hypotheses
  :set-default-backchain-limit 500  ; allow backchaining through a new rewrite,
                                    ; linear, or meta rule's hypotheses to a
                                    ; depth of no more than 500
  (set-default-backchain-limit 500) ; same as above
  :set-default-backchain-limit (nil 500)
                                    ; same as above
  (set-default-backchain-limit '(nil 500))
                                    ; same as above
  (set-default-backchain-limit '(3 500))
                                    ; for a new :type-prescription rule, allow
                                    ; type-set backchaining to a depth
                                    ; of no more than 3; for a new
                                    ; rule of class :rewrite, :linear,
                                    ; or :meta, allow backchaining to
                                    ; a depth of no more than 50
  (set-default-backchain-limit '(nil 500))
                                    ; do not limit backchaining for a
                                    ; new :type-prescription rule; for
                                    ; a new rule of class :rewrite,
                                    ; :linear, or :meta, allow
                                    ; backchaining to a depth of no
                                    ; more than 50
 })

 <p>The initial default backchain-limit is @('nil').</p>")

(defxdoc set-default-hints
  :parents (default-hints)
  :short "Set the default hints"
  :long "@({
  Examples:
  (set-default-hints '((computed-hint-1 clause)
                       (computed-hint-2 clause
                                        stable-under-simplificationp)))
  (set-default-hints nil)
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.  It is
 @(tsee local) to the book or @(tsee encapsulate) form in which it occurs; see
 @(see set-default-hints!) for a corresponding non-@(tsee local) event.</p>

 @({
  General Form:
  (set-default-hints lst)
 })

 <p>where @('lst') is a list.  Generally speaking, the elements of @('lst')
 should be suitable for use as @(tsee computed-hints).</p>

 <p>Whenever a @(tsee defthm) or @(tsee thm) command is executed, the default
 hints are appended to the right of any explicitly provided @(':')@(tsee hints)
 in the command.  The same applies to @(tsee defun)s as well (@(':hints'),
 @(':guard-hints'), and (for ACL2(r)) @(':std-hints')).  The hints are then
 translated and processed just as though they had been explicitly included.</p>

 <p>Technically, we do not put restrictions on @('lst'), beyond that it is a
 true list.  It would be legal to execute</p>

 @({
  (set-default-hints '((\"Goal\" :use lemma23)))
 })

 <p>with the effect that the given hint is added to subsequent hints supplied
 explicitly.  An explicit \"Goal\" hint would, however, take priority, as
 suggested by the mention above of ``appended to the right.''</p>

 <p>Note that @('set-default-hints') sets the default hints as specified.  To
 add to or remove from the current default, see @(see add-default-hints) and
 see @(see remove-default-hints).  To see the current default hints, see @(see
 default-hints).</p>

 <p>Finally, note that the effects of @('set-default-hints'), @(tsee
 add-default-hints), and @(tsee remove-default-hints) are @(tsee local) to the
 book in which they appear.  Thus, users who include a book with such forms
 will not have their default hints affected by such forms.  In order to export
 the effect of setting the default hints, use @(tsee set-default-hints!),
 @(tsee add-default-hints!), or @(tsee remove-default-hints!).</p>

 <p>For a related feature, which however is only for advanced system builders,
 see @(see override-hints).</p>")

(defxdoc set-default-hints!
  :parents (default-hints)
  :short "Set the default hints non-@(tsee local)ly"
  :long "<p>Please see @(see set-default-hints), which is the same as
 @('set-default-hints!')  except that the latter is not @(tsee local) to the
 @(tsee encapsulate) or the book in which it occurs.  Probably @(see
 set-default-hints) is to be preferred unless you have a good reason for
 wanting to export the effect of this event outside the enclosing @(tsee
 encapsulate) or book.</p>")

(defxdoc set-deferred-ttag-notes
  :parents (defttag)
  :short "Modify the verbosity of @('TTAG NOTE') printing"
  :long "@({
  General Form:
  (set-deferred-ttag-notes val state)
 })

 <p>where @('val') is @('t') or @('nil').</p>

 <p>See @(see defttag) for a discussion of trust tags (ttags).  By default, a
 ``@('TTAG NOTE')'' is printed in order to indicate reliance on a ttag.  When
 many such notes are printed, it may be desirable to avoid seeing them all.
 Upon evaluation of the form</p>

 @({
  (set-deferred-ttag-notes t state)
 })

 <p>ACL2 will enter a deferred mode for the printing of ttag notes.  In this
 mode, only the first ttag note is printed for each top-level command, and the
 remainder are summarized before the next top-level prompt (if any) is printed,
 hence before the next command is evaluated.  That summary is merely a list of
 ttags, but the summary explains that the full ttag notes may be printed with
 the command @('(show-ttag-notes)').</p>

 <p>Note that @('(show-ttag-notes)') spares you duplicate ttag notes.  If you
 want to see every ttag note as it would normally appear, for maximum security,
 do not evaluate the command @('(set-deferred-ttag-notes t state)').  You can
 undo the effect of this command, returning to an immediate mode for printing
 ttag notes, by evaluating:</p>

 @({
  (set-deferred-ttag-notes nil state)
 })")

(defxdoc set-difference$
  :parents (lists acl2-built-ins)
  :short "Elements of one list that are not elements of another"
  :long "@({
  General Forms:
  (set-difference$ l1 l2)
  (set-difference$ l1 l2 :test 'eql)   ; same as above (eql as equality test)
  (set-difference$ l1 l2 :test 'eq)    ; same, but eq is equality test
  (set-difference$ l1 l2 :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Set-difference$ l1 l2)') equals a list that contains the @(tsee
 member)s of @('l1') that are not @(tsee member)s of @('l2').  More precisely,
 the resulting list is the same as one gets by deleting the members of @('l2')
 from @('l1'), leaving the remaining elements in the same order as in @('l1').
 The optional keyword, @(':TEST'), has no effect logically, but provides the
 test (default @(tsee eql)) used for comparing members of the two lists.</p>

 <p>The @(see guard) for a call of @('set-difference$') depends on the test.
 In all cases, both arguments must satisfy @(tsee true-listp).  If the test is
 @(tsee eql), then one of the arguments must satisfy @(tsee eqlable-listp).  If
 the test is @(tsee eq), then one of the arguments must satisfy @(tsee
 symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('set-difference$') and its variants:</p>

 <blockquote><p>@('(set-difference-eq l1 l2)') is equivalent to
 @('(set-difference$ l1 l2 :test 'eq)');</p>

 <p>@('(set-difference-equal l1 l2)') is equivalent to @('(set-difference$ l1
 l2 :test 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('set-difference-equal').</p>

 @(def set-difference-equal)

 <p>@('Set-difference$') is similar to the Common Lisp primitive
 @('set-difference').  However, Common Lisp does not specify the order of
 elements in the result of a call of @('set-difference').</p>")

(defxdoc set-difference-theories
  :parents (theories theory-functions)
  :short "Difference of two @(see theories)"
  :long "@({
  Example:
  (set-difference-theories (current-theory :here)
                           '(fact (fact)))

  General Form:
  (set-difference-theories th1 th2)
 })

 <p>where @('th1') and @('th2') are @(see theories) (see @(see theories)).  To
 each of the arguments there corresponds a runic theory.  This function returns
 the set-difference of those two runic @(see theories), represented as a list
 and ordered chronologically.  That is, a @(see rune) is in the result iff it
 is in the first runic theory but not in the second.</p>

 <p>The standard way to ``disable'' a theory, @('lst'), is: @('(in-theory
 (set-difference-theories (current-theory :here) lst))').</p>

 <p>This ``function'' is actually a macro that expands to a term mentioning the
 single free variable @(tsee world).  When theory expressions are evaluated by
 @(tsee in-theory) or the @(':')@(tsee in-theory) hint, @(tsee world) is bound
 to the current ACL2 @(see world).</p>")

(defxdoc set-duplicate-keys-action
  :parents (macro-args macros programming advanced-features)
  :short "Control action for macro calls with duplicate keyword arguments"
  :long "@({
  Example Forms:
  (set-duplicate-keys-action thm :warning)
  (set-duplicate-keys-action my-macro-1 nil)

  General Forms:
  (set-duplicate-keys-action name :error)
  (set-duplicate-keys-action name :warning)
  (set-duplicate-keys-action name nil)
 })

 <p>where @('name') is a symbol, one that is generally expected to be the name
 of a macro.</p>

 <p>By default, an error occurs when ACL2 encounters a macro call with
 duplicate keys, for example @('(foo 3 :y 4 :y 5)') where @(':y') is a keyword
 argument of the macro, @('foo').  However, the event
 @('(set-duplicate-keys-action name val)') can be used to determine whether
 such duplicate keys cause an error, a warning, or neither, according to
 whether @('val') is the keyword @(':error'), @(':warning'), or @('nil'),
 respectively.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.  It is
 @(tsee local) to the book or @(tsee encapsulate) form in which it occurs; see
 @(see set-duplicate-keys-action!) for a corresponding non-@(tsee local) event.
 Indeed, @('(set-duplicate-keys-action ...)') is equivalent to @('(local
 (set-duplicate-keys-action! ...))').</p>")

(defxdoc set-duplicate-keys-action!
  :parents (prover-output)
  :short "Non-@(tsee local) version of @(tsee set-duplicate-keys-action)"

  :long "<p>Please see @(see set-duplicate-keys-action), which is the same as
 @('set-duplicate-keys-action!') except that the latter is not @(tsee local) to
 the @(tsee encapsulate) or the book in which it occurs.  Perhaps @(see
 set-duplicate-keys-action) is to be preferred unless you have a good reason
 for wanting to export the effect of this event outside the enclosing @(tsee
 encapsulate) or book.</p>")

(defxdoc set-enforce-redundancy
  :parents (redundant-events)
  :short "Require most events to be redundant"
  :long "@({
  General Forms:
  (set-enforce-redundancy nil)   ; do not require redundancy (default)
  (set-enforce-redundancy t)     ; most events (see below) must be redundant
  (set-enforce-redundancy :warn) ; warn for most non-redundant events
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 @({
  General Form:
  (set-enforce-redundancy flag)
 })

 <p>where @('flag') is @('nil'), @('t'), or @(':warn'), as indicated above.
 This macro is essentially equivalent to</p>

 @({
  (table acl2-defaults-table :enforce-redundancy flag)
 })

 <p>and hence is @(tsee local) to any @(see books) and @(tsee encapsulate)
 @(see events) in which it occurs; see @(see acl2-defaults-table).  However,
 unlike the above simple call of the @(tsee table) event function (see @(see
 table)), no output results from a @('set-enforce-redundancy') event.</p>

 <p>@('Set-enforce-redundancy') may be thought of as an event that merely sets
 a flag as indicated above, which determines whether most @(see events),
 including @(tsee defun) and @(tsee defthm) events, are allowed to be
 redundant; see @(see redundant-events).  The exceptions are @(tsee deflabel),
 @(tsee defpkg), @(tsee encapsulate), @(tsee include-book), @(tsee
 push-untouchable), @(tsee remove-untouchable), @(tsee set-body), and @(tsee
 table) @(see events).  Any other type of non-redundant event will cause an
 error if @('flag') is @('t') and a warning if @('flag') is @('nil'),
 <i>except</i> in the course of carrying out an @(tsee include-book) form.</p>

 <p>Note that because @(tsee table) @(see events) that set the @(tsee
 acl2-defaults-table) are implicitly @(tsee local), @('set-enforce-redundancy')
 events are ignored when including books.  However, the presence of the event
 @('(set-enforce-redundancy t)') in a book guarantees that its subsequent
 definitions and theorems are redundant.  This can be a useful property to
 maintain in library development, as we now describe.</p>

 <p>An example of the use of this form can be found in the community @(see
 books) under directory @('books/rtl/rel4/').  The intention in that directory
 has been to put all the gory details in subdirectories @('support/') and
 @('arithmetic/'), so that the books in subdirectory @('lib/') contain only the
 ``exported'' definitions and theorems.  This approach is useful for human
 readability.  Moreover, suppose we want to prove new theorems in @('lib/').
 Typically we wish to prove the new theorems using the existing books in
 @('lib/'); however, our methodology demands that the proofs go into books in
 @('support/').  If every theorem in @('lib/') is redundant, then we can
 <i>develop</i> the proofs in @('lib/') but then when we are done, <i>move</i>
 each book with such proofs into @('support/') as follows.  In any such book,
 we first replace @(tsee include-book) forms referring to books in @('lib/') by
 @(tsee include-book) forms referring to corresponding books in @('support/')
 and/or @('arithmetic/').  Then, we add suitable @(tsee in-theory) events to
 get us back into the original @('lib/') proof environment.</p>

 <p>The default behavior of the system is as though the
 @(':enforce-redundancy') value is @('nil').  The current behavior can be
 ascertained by evaluating the following form.</p>

 @({
  (cdr (assoc-eq :enforce-redundancy (table-alist 'acl2-defaults-table wrld)))
 })")

(defxdoc set-evisc-tuple
  :parents (io)
  :short "Control suppression of details when printing"
  :long "<p>ACL2 output is generally printed in full.  However, ACL2 can be
 directed to abbreviate, or ``eviscerate'', objects before printing them,
 though the use of a so-called ``evisc-tuple''.  See @(see evisc-tuple) for a
 discussion of evisc-tuples.  The utility @('set-evisc-tuple') modifies certain
 global evisc-tuples, as explained below, to affect the extent to which ACL2
 eviscerates objects during printing, for example during proof output or when
 printing top-level evaluation results.</p>

 @({
  General Form:
  (set-evisc-tuple evisc-tuple  ; a legal evisc-tuple, or :DEFAULT
                  :iprint val   ; one of *iprint-actions*
                  :sites sites) ; either :ALL, or an element or a subset of
                                ;   the list of legal sites (see below)
 })

 <p>where the value of @(':iprint') is passed to @(tsee set-iprint), @(':sites
 :all') abbreviates @(':sites') '@(`*evisc-tuple-sites*`), and other
 documentation is provided below.  Note that all arguments are evaluated.</p>

 <p>See @(see without-evisc) for how to avoid evisceration for ACL2 output.</p>

 <p>The following example illustrates an invocation of @('set-evisc-tuple')
 that limits the print-level to 3 &mdash; only three descents into list
 structures are permitted before eviscerating a subterm &mdash; and limits the
 print-length to 4 &mdash; only the first four elements of any list structure
 will be printed.</p>

 @({
  ACL2 !>(set-evisc-tuple (evisc-tuple 3   ; print-level
                                       4   ; print-length
                                       nil ; alist
                                       nil ; hiding-cars
                                       )
                          :iprint :same ; better yet, T
                          :sites :all)
   (:TERM :LD :TRACE :ABBREV)
  ACL2 !>'((a b ((c d)) e f g) u v w x y)
  ((A B (#) E ...) U V W ...)
  ACL2 !>
 })

 <p>We recommend however using @(':iprint t') so that eviscerated terms may be
 read back in; see @(see set-iprint).  Indeed, the @(':iprint') argument is
 required as a reminder to the user to consider that issue, unless iprinting
 has been enabled at least once.  If @(':sites') or a required @(':iprint')
 argument is omitted, however, ACL2 will query the user for the missing
 arguments rather than causing an error.</p>

 <p>ACL2 eviscerates by default only in a few cases, primarily in informational
 messages for errors, warnings, and queries (i.e., in the @(':EVISC') case
 below).  Users can modify the default behavior by supplying a suitable
 argument to @('set-evisc-tuple').  The argument may be @(':default'), which
 denotes the evisceration provided when ACL2 starts up.  Otherwise that
 argument is an evisc-tuple, which is either @('nil') (no evisceration) or as
 described above.  Moreover, there are five evisc-tuple ``evisceration
 contexts'', each with its own evisceration control.  The value returned by
 @('set-evisc-tuple') indicates the evisceration contexts whose evisc-tuple has
 been set.  The evisceration contexts are as follows, all of which use a
 default value of @('nil') for the hiding-cars.  Accessors are also shown for
 retrieving the corresponding evisc-tuple.</p>

 <ul>

 <li>@(':TERM') &mdash; used for printing terms.  The accessor is
 @('(term-evisc-tuple flg state)'), where @('flg') is ignored if
 @('set-evisc-tuple') has been called for @(':term') with value other than
 @(':default'), and otherwise (hence initially): a @('flg') of @('nil')
 indicates an evisc-tuple of @('nil'), and otherwise the term-evisc-tuple has a
 print-level of 3 and print-length of 4.</li>

 <li>@(':ABBREV') &mdash; used for printing informational messages for errors,
 warnings, and queries.  Initially, the alist abbreviates the ACL2 @('world'),
 print-level is 5, and print-level is 7.  The accessor is
 @('(abbrev-evisc-tuple state)').</li>

 <li>@(':GAG-MODE') &mdash; used for printing induction schemes (and perhaps,
 in the future, for other printing) when @(see gag-mode) is on.  If gag-mode is
 off, the value used for this @(see evisc-tuple) is @('(term-evisc-tuple nil
 state)').  But if gag-mode is on (i.e., @('(gag-mode)') evaluates to a
 non-@('nil') value), then with one exception, the value is an evisc-tuple or
 @('nil'), to be used in gag-mode for printing of induction schemes and, during
 proofs, the ``The non-trivial part of the guard conjecture''.  The exceptional
 value is @('t'), which indicates that in gag-mode, no printing of induction
 schemes should be and the guard conjecture should be printed using
 @('(term-evisc-tuple t state)').  The accessor is @('(gag-mode-evisc-tuple
 state)').</li>

 <li>@(':LD') &mdash; used by the ACL2 read-eval-print loop.  The accessor is
 @('(')@(tsee ld-evisc-tuple)@(' state)').</li>

 <li>@(':TRACE') &mdash; used for printing @(see trace) output.  No accessor
 is available (though in raw Lisp, @('(trace-evisc-tuple)') returns the
 trace-evisc-tuple).</li>

 </ul>

 <p>Each context @('ectx') also has an updater, @('(set-ectx-evisc-tuple val
 state)'), where @('val') is a legal value for @('set-evisc-tuple') as
 described above: @(':default') or an @(see evisc-tuple) (possibly
 @('nil')).</p>

 <p>Note that the @(see break-rewrite) commands and the interactive @(see
 proof-builder) generally do their printing using the term-evisc-tuple.</p>")

(defxdoc set-fc-criteria
  :parents (forward-chaining-reports)
  :short "To set the tracking criteria for forward chaining reports"
  :long "@({
  Examples:
  (set-fc-criteria)                 ; shut off all tracking
  (set-fc-criteria nil)

  (set-fc-criteria t)               ; to track all forward chaining
  (set-fc-criteria (t t t))

  (set-fc-criteria
   ((:FORWARD-CHAINING LEMMA1)      ; track all uses of LEMMA1,
     t
     t)
    ((:FORWARD-CHAINING LEMMA2)     ; uses of LEMMA2 triggered
     (ALISTP (BASIC-MAPPER A B))    ; by this specific ALISTP term
     t)
    (t t (TRUE-LISTP (DLT D))))     ; and every rule deriving
                                    ; this TRUE-LISTP term.

  General Forms:
  (set-fc-criteria nil)
  (set-fc-criteria t)
  (set-fc-criteria triple1 triple2 ...)
 })

 <p>where each triple is of the form @('(rune inst-trigger inst-concl)').  If
 rune is non-@('t') is must be a forward chaining @(see rune).  The other two
 components, @('inst-trigger') and @('inst-concl'), if non-@('t'), must be
 terms.  The list of all the triples supplied is called the ``criteria.''  In
 the form @('(set-fc-criteria nil)'), the criteria used is the empty list of
 triples.  (Technically, supplying @('nil') as a triple ``ought'' to be an
 error, but it is a more ``natural'' way to say the list of criteria is empty
 than to use the correct form @('(set-fc-criteria)').)  In the form
 @('(set-fc-criteria t)') the criteria used is the list containing the single
 triple @('(t t t)').</p>

 <p>This function sets the tracking criteria for forward chaining reporting.
 See @(see forward-chaining-reports) for a general discussion of tracking and
 reporting forward chaining activity.</p>

 <p>Think of the forward chaining criteria as a list of triples, representing a
 disjunction of conjunctions.  The activation of a @(':')@(tsee
 forward-chaining) rune by some triggering term in the current context
 <i>satisfies</i> the criteria if it satisfies one of the triples.  To satisfy
 the triple @('(rune inst-trigger inst-concl)'), the activation must satisfy
 each component of the triple.  Any @('t') component is always satisfied.  If
 @('rune') is non-@('t') it is satisfied if the activation is for the given
 rune.  If @('inst-trigger') is non-@('t'), it is satisfied if the activation
 is triggered by the given term.  (``@('Inst-trigger''') stands for
 ``instantiated trigger.''  It is not the trigger term of the rule but is
 supposed to be an instance of that term that you believe will arise in some
 proof attempt you are debugging &mdash; an instance you want to ``watch'' as
 it fires the rule.)  If @('inst-concl') is non-@('t'), it is satisfied if the
 activation could possibly derive the conclusion given.  (Again,
 ``@('inst-concl''') stands for ``instantiated conclusion'' and shows the term
 in your problem that you expect to be derived by forward chaining.)</p>

 <p>Note that if the criteria is empty, it is never satisfied, so tracking is
 turned off.  If the criteria is the singleton list containing just the triple
 @('(t t t)'), then every activation satisfies it and so all @(':forward
 chaining') rules are tracked.</p>

 <p>See @(see forward-chaining-reports) for details.</p>")

(defxdoc set-fc-report-on-the-fly
  :parents (forward-chaining-reports)
  :short "To determine when forward-chaining reports are printed"
  :long "@({
  Examples:  (set-fc-report-on-the-fly t)
             (set-fc-report-on-the-fly nil)
 })

 <p>If the flag is set to @('t'), forward chaining tracking reports are printed
 when forward chaining occurs.  If the flag is set to @('nil'), very short
 reports (giving just the caller and the report number) are printed during
 forward chaining but you can use @(tsee fc-report) to see the full report
 afterwards.</p>

 <p>Since nothing is tracked when the criteria is @('nil'), this function also
 prints out the current criteria to remind you of what it is.</p>

 <p>The flag manipulated by this function does not shut off tracking.  It only
 determines whether reports are printed on-the-fly or not.  To shut off
 tracking @(tsee set-fc-criteria).</p>

 <p>See @(see forward-chaining-reports) for details.</p>")

(defxdoc set-fmt-hard-right-margin
  :parents (io acl2-built-ins)
  :short "Set the right margin for formatted output"
  :long "<p>In this documentation topic we discuss setting of both a ``soft''
 and a ``hard'' right margin.</p>

 @({
  Example Forms:
  (set-fmt-soft-right-margin 55 state) ; set soft right margin to 55
  (set-fmt-hard-right-margin 68 state) ; set hard right margin to 68
 })

 <p>@(tsee Fmt) and related functions can insert linebreaks when lines get too
 long.  A linebreak is inserted at an aesthetically appropriate point once the
 column exceeds the value of @('(@ fmt-soft-right-margin)').  If however the
 column exceeds the value of @('(@ fmt-hard-right-margin)'), then a linebreak
 is soon inserted.  Such a ``hard'' linebreak follows the insertion of a
 backslash (@('\\')) character unless @(tsee fmt!), @(tsee fms!), or @(tsee
 fmt1!) is used, or state global @('write-for-read') is true.</p>")

(defxdoc set-fmt-soft-right-margin
  :parents (io acl2-built-ins)
  :short "Set the soft right margin for formatted output"
  :long "<p>See @(see set-fmt-hard-right-margin) for a discussion of the soft
 and hard right margin for formatted output.</p>")

(defxdoc set-gag-mode
  :parents (prover-output)
  :short "Modify the nature of proof output"
  :long "@({
  Examples:

  :set-gag-mode t      ; enable gag-mode, suppressing most proof commentary
  (set-gag-mode t)     ; same as above
  :set-gag-mode :goals ; same as above, but print names of goals when produced
  :set-gag-mode nil    ; disable gag-mode

  General Forms:
  (set-gag-mode val)
  :set-gag-mode val
 })

 <p>where @('val') is one of @('t'), @('nil'), or @(':goals').</p>

 <p>By default, gag-mode is enabled, set to @(':goals').  To see the current
 value of gag-mode, evaluate the form, @('(gag-mode)').</p>

 @({
  (gag-mode) ; evaluates to t, nil, or :goals
 })

 <p>The basic idea of gag-mode is to avoid much of the verbose output from the
 theorem prover, leaving only output that is expected to be helpful.  The first
 two forms below set gag-mode on, while the other turns it off; these may be
 placed in your ACL2 customization file; see @(see acl2-customization).</p>

 @({
  (set-gag-mode :goals) ; (default) avoid most prover output; show goal names
  (set-gag-mode t)      ; avoid most prover output; also, hide goal names
  (set-gag-mode nil)    ; allow prover output
 })

 <p>Gag-mode focuses attention on so-called ``key checkpoints''.  By default, a
 checkpoint is a goal that cannot be simplified.  (Below we discuss how to
 change this default.)  A key checkpoint is a checkpoint that is not descended
 from another checkpoint.  (Technical point: ``descended'' signifies that both
 goals are at the top level in the same forcing round, or are in the same proof
 by induction.)  Successful ACL2 users generally focus their attention on key
 checkpoints, or less often, induction schemes.  (To suppress or abbreviate
 induction schemes in gag-mode, see @(see set-evisc-tuple), specifically, the
 discussion of @(':GAG-MODE').)  For a discussion of how to use ACL2 prover
 output in an effective manner, see @(see the-method), and see @(see
 introduction-to-the-theorem-prover) for a more detailed tutorial.  In
 gag-mode, a key checkpoint is only displayed when ACL2 is unable to make any
 further progress on that goal or some descendant of it, other than with a
 proof by induction.</p>

 <p>Evaluation of @('(set-gag-mode t)') enters gag-mode, so that only key
 checkpoints are printed.  Evaluation of @('(set-gag-mode :goals)') also enters
 gag-mode, but will additionally cause the name of a goal to be printed as soon
 as it is generated (by invoking @(see set-print-clause-ids)).  The @(':goals')
 setting is the default, and is useful for cases in which the prover spends
 very little of its time generating goals to be proved by induction, yet you
 want to see that it is making progress.  For finer-grained feedback about the
 simplifier's activity, see @(see dmr).</p>

 <p>An alternative to gag-mode is to use proof-trees; see @(see proof-tree).
 With proof-trees it is not so important to avoid excessive prover output,
 since the proof-tree display provides structure that makes it easy to monitor
 proof attempts and navigate output for a proof that has failed or seems to be
 failing.  Still, output can take time to print, so you may get better
 performance with gag-mode.</p>

 <p>The intention of gag-mode is to show you only the parts of a proof attempt
 that are relevant for debugging a failure; additional output is generally more
 likely to be distracting than truly helpful.  But on occasion you may want to
 see the full proof output after an attempt made with gag-mode.  This can be
 done provided proof output is not inhibited (see @(see
 set-inhibit-output-lst)) during the proof attempt; see @(see pso) and see
 @(see pso!).  Since @('set-gag-mode') takes responsibility for the saving of
 output, related utility @(tsee set-saved-output) is disabled when gag-mode is
 active.  Also note that calling @('set-gag-mode') erases the currently saved
 output, if any.</p>

 <p>You may notice that gag-mode tends to print relatively little information
 about goals pushed for proof by sub-induction &mdash; i.e., a proof of *i.j,
 *i.j.k, etc.  That feature emphasizes that unsuccessful sub-inductions should
 generally be avoided, not analyzed for ways to make them succeed.  Instead,
 the key checkpoint that generated the goal pushed for this induction is more
 appropriate to analyze.  In general, the ``higher level'' the checkpoint, the
 more worthy it is of attention.  Thus, it might be helpful to look at the
 top-level checkpoints before looking at those labeled ``Key checkpoints under
 a top-level induction''.</p>

 <p>We conclude with remarks for advanced users.</p>

 <p>The notion of ``checkpoint'' can be modified by the user.  The default, as
 discussed above, is for a checkpoint to be a goal that cannot be simplified.
 Put differently, a checkpoint is acted on by one of the processes in the value
 of the form @('(@ checkpoint-processors)'); see @(see @).  Any or all of the
 symbols @('eliminate-destructors-clause'), @('fertilize-clause'),
 @('generalize-clause'), or @('eliminate-irrelevance-clause') can be removed
 from this value in order that invocation of the corresponding proof process
 does not cause its input goal to be labeled a checkpoint.  For example, if you
 do not want destructor elimination to be treated differently from
 simplification for purposes of labeling checkpoints, you can evaluate the
 following form (see @(see assign)):</p>

 @({
  (assign checkpoint-processors
          (remove 'eliminate-destructors-clause
                  (@ checkpoint-processors)))
 })

 <p>Note that the value of @('(@ checkpoint-processors)') also affects the
 proof tree display; see @(see proof-tree-details).  End of Remark.)</p>

 <p>See @(see set-evisc-tuple), in particular the discussion there of
 @(':GAG-MODE'), for how to influence slightly just what is printed in
 gag-mode.</p>")

(defxdoc set-gc-strategy
  :parents (miscellaneous acl2-built-ins)
  :short "Set the garbage collection strategy (CCL only)"
  :long "<p><em>Note</em>: This macro has no effect unless the host Lisp is
  CCL.</p>

  @({
  General Forms:

  (set-gc-strategy :egc)     ; the default: EGC is on, full GC is not delayed
  (set-gc-strategy :delay)   ; EGC is off, full GC is delayed
  (set-gc-strategy :current) ; same as replacing :current by the latest
                             ; strategy set (:egc or :delay)

  (set-gc-strategy strategy threshold)
                             ; Same as (set-gc-strategy strategy), but sets
                             ; threshold to the indicated number of bytes
                             ; (see below)
 })

 <p>Logically, @('(set-gc-strategy op)') returns @('op').  But in some host
 Lisps (currently CCL only), it changes how garbage collection is invoked.
 Exactly how that is done is best understood by reading the ACL2 source code,
 starting with @('set-gc-strategy').  Here we document what most users might
 want to know about this utility, assuming they are using CCL.  We defer
 discussion of the optional second argument, @('threshold'), to the end.</p>

 <p>Normally the default garbage collection strategy will probably be fine.
 That default has the ephemeral garbage collector (EGC) enabled.  But in jobs
 that stress @(tsee hons), or perhaps memoization (see @(see memoize)) or @(see
 fast-alists), it might be useful to switch to a strategy that disables EGC but
 also significantly delays garbage collection.  To switch to that delaying
 strategy:</p>

 @({
 (set-gc-strategy :delay)
 })

 <p>Then, you can return to the default strategy, re-enabling EGC and no longer
 causing delays in garbage collection, as follows.</p>

 @({
 (set-gc-strategy :egc)
 })

 <p>It is also legal to invoke @('(set-gc-strategy :current)'), which is
 equivalent to replacing @(':current') by the current strategy; see @(see
 gc-strategy).</p>

 <p>If you want to change the gc-strategy during certification of a book, but
 not when including that book, you can place your call of @('set-gc-strategy')
 inside @(tsee value-triple), for example as follows.</p>

 @({
 (value-triple (set-gc-strategy :delay))
 })

 <p>The following variant causes the @(see gc-strategy) to be modified when
 including the book as well.</p>

 @({
 (value-triple (set-gc-strategy :delay) :on-skip-proofs t)
 })

 <p>This capability might be extended to other host Lisps in the future,
 especially if ACL2 users provide suggestions for how to do so.</p>

 <p>Note that the default behavior can be changed to @(':delay') at ACL2 build
 time, by setting @('Make') variable @('ACL2_EGC_ON=nil') when building an ACL2
 executable.</p>

 <h3>The @('threshold') argument</h3>

 <p>When a second argument is supplied in a call of @('set-gc-strategy'), it
 must be either @('nil'), which is equivalent to supplying no second argument,
 or else a positive integer.  This positive integer will be the ``GC
 threshold'' number of bytes CCL will try to ensure are available before the
 next full garbage collection.  The default (i.e., the value used when the
 second argument is @('nil') or is omitted) is the minimum of the following two
 values: 1/2 GB, and 1/32 of physical memory (or 1/32 of 4 GB, if the physical
 memory cannot be determined).  (Technical note: The GC threshold is stored in
 raw Lisp variable @('*gc-min-threshold*').)</p>")

(defxdoc set-guard-checking
  :parents (guard)
  :short "Control checking @(see guard)s during execution of top-level forms"
  :long "<p>Detailed comments about the arguments of this function may be found
 elsewhere: see @(see guard-evaluation-table).  Here we provide an introduction
 to the use of @('set-guard-checking').</p>

 <p>New users are encouraged to execute one of the following forms in order to
 avoid evaluation errors due to @(see guard)s:</p>

 @({
  (set-guard-checking :none)
  (set-guard-checking nil)
 })

 <p>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).</p>

 <p>You may put one of the above forms in the @('\"acl2-customization.lsp\"')
 file in your current directory (see @(see cbd)) or your home directory; see
 @(see acl2-customization).</p>

 <p>Note that @(see guard)s are not part of the ACL2 logic, and hence new users
 can completely ignore the notion of @(see 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
 @(see guard) on @(tsee car) requires its first argument to be a @(tsee cons)
 pair or @('nil').</p>

 @({
  (thm (equal (car 3) nil))
 })

 <p>Moreover, unless your functions or top-level forms call built-in ACL2
 functions that are defined in @(':')@(tsee program) mode, the following
 property will hold.</p>

 <blockquote><p>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.</p></blockquote>

 <p>If you feel bold, then you may wish to read the rest of this documentation
 topic; also see @(see guard).</p>

 <p>See @(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.</p>

 <p>The top-level ACL2 loop has a variable which controls which sense of
 execution is provided.  To turn ``@(see guard) checking on,'' by which we mean
 that @(see guard)s 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 @(see guard) is @('t'). The status of guard-checking is
 reflected in the @(see prompt).</p>

 @({
  ACL2 !>
 })

 <p>means @(see guard) checking is on and</p>

 @({
  ACL2 >
 })

 <p>means @(see 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</p>

 @({
  ACL2 !>(car 'abc)
 })

 <p>will signal an error, while</p>

 @({
  ACL2 >(car 'abc)
 })

 <p>will return @('nil').</p>

 <p>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.</p>

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

 <p>For further discussion on evaluation and guards see @(see
 guards-and-evaluation), in particular the exception for safe-mode in the
 ``Aside'' there.  See @(see guard) for a general discussion of @(see
 guard)s.</p>

 <p>Now we fulfill our promise above to discuss two other values for
 @(':set-guard-checking'):</p>

 @({
  :set-guard-checking :nowarn
  :set-guard-checking :all
 })

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

 @({
  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 !>
 })

 <p>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 @(tsee true-listp).
 However, as the warning above explains, we do not by default check guards on
 recursive calls.  The reason is efficiency &mdash; 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 @(':')@(tsee program) mode functions
 &mdash; unless, of course, a call is made of a function whose guard has been
 verified (see @(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.</p>

 <p>For technical reasons, @(':all') does not have its advertised effect in the
 case of built-in @(':')@(tsee 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').</p>

 <p>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
 @(':')@(tsee program) mode functions, since one can get raw Lisp errors.  In
 the example below, the raw Lisp error occurs because @('foo') implicitly has a
 @(see guard) of @('t'), hence @('(foo 3)') is evaluated in raw Lisp, which
 leads to a raw Lisp call of c[(car 3)].</p>

 @({
  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 !>
 })")

(defxdoc set-guard-msg
  :parents (guard debugging)
  :short "Specify what is printed when a @(see guard) is violated"
  :long "<p>This is an advanced feature that may require considerable
  understanding of ACL2 programming.

 ACL2 provides default error messages for guard violations.  However, ACL2 also
 provides a @(see table), @('guard-msg-table'), that allows custom error
 messages for guard-checking failures.  The macro @('set-guard-msg') provides a
 convenient way to update this table.  The keys of the table are symbols, which
 can be expected to be function symbols or names of macros.  Each value is
 a (translated) @(see term) whose only free variables are @('world'),
 @('args'), and @('coda').  When guard-checking fails, the term is evaluated to
 create a <i>message</i> suitable for \"@('~@')\" formatted printing
 directives; see @(see fmt).  That evaluation is done with @('world') bound to
 the current ACL2 logical @(see world), with @('args') bound to the actual
 parameters of the call, and with @('coda') bound to the message that would
 typically be printed by default at the end of a guard violation.  (See ACL2
 source function @('guard-er-message-coda') for details, or simply
 experiment.)</p>

 <h3>Example</h3>

 <p>Consider the following example.</p>

 @({
 (defun foo (x)
  (declare (xargs :mode :program :guard (consp x)))
  (car x))

 (set-guard-msg foo (msg \"An error for call ~x0.\"
                         (cons 'foo args)))
 })

 <p>Corresponding output for a guard violation is as follows.</p>

 @({
 ACL2 !>(foo 3)


 ACL2 Error in TOP-LEVEL:  An error for call (FOO 3).

 ACL2 !>
 })

 <p>Continuing in the same session, suppose we provide this fancier error
 message specification.</p>

 @({
 (set-guard-msg foo
                (msg \"An error for call ~x0 in a world of length ~x1.~@2\"
                     (cons 'foo args)
                     (length world) ; length of the current ACL2 world
                     coda))
 })

 <p>The corresponding error is shown below.  Notice that the coda starts on a
 new line, with the same \"See :DOC ...\" message that one would see if the
 default error message were supplied for the same guard violation.</p>

 @({
 ACL2 !>(foo 3)


 ACL2 Error in TOP-LEVEL:  An error for call (FOO 3) in a world of length
 98582.
 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 !>
 })

 <p>The capability shown above for function symbols is also available for macro
 names.  However, the variable, @('coda'), should not be used for macro
 names.</p>")

(defxdoc set-ignore-ok
  :parents (declare defun)
  :short "Allow unused formals and locals without an @('ignore') or
  @('ignorable') declaration"
  :long "@({
  Examples:
  (set-ignore-ok t)
  (set-ignore-ok nil)
  (set-ignore-ok :warn)
 })

 <p>The first example above allows unused formals and locals, i.e., variables
 that would normally have to be @(see declare)d @('ignore')d or @('ignorable').
 The second example disallows unused formals and locals; this is the default.
 The third example allows them, but prints an appropriate warning.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.
 Moreover, its effect is to set the @(tsee acl2-defaults-table), and hence its
 effect is @(tsee local) to the book or @(tsee encapsulate) form containing it;
 see @(see acl2-defaults-table).</p>

 @({
  General Form:
  (set-ignore-ok flg)
 })

 <p>where @('flg') is either @('t'), @('nil'), or @(':warn').</p>

 <p>One might find this event useful when one is generating function
 definitions by an automated procedure, when that procedure does not take care
 to make sure that all formals are actually used in the definitions that it
 generates.</p>

 <p>Note: Defun will continue to report irrelevant formals even if
 @(':set-ignore-ok') has been set to @('t'), unless you also use @(tsee
 set-irrelevant-formals-ok) to instruct it otherwise.</p>")

(defxdoc set-inhibit-output-lst
  :parents (prover-output)
  :short "Control output"
  :long "@({
  Examples:
  (set-inhibit-output-lst '(warning))
  (set-inhibit-output-lst '(proof-tree prove proof-builder))
  (set-inhibit-output-lst *valid-output-names*) ; inhibit all prover output
  :set-inhibit-output-lst (proof-tree prove)

  General Form:
  (set-inhibit-output-lst lst)
 })

 <p>where @('lst') is a form (which may mention @(tsee state)) that evaluates
 to a list of names, each of which is the name of one of the following
 ``kinds'' of output produced by ACL2.</p>

 @({
    error          error messages (but for hard errors, see below)
    warning        warnings other than those related to soundness
    warning!       warnings (of all degrees of importance)
    observation    observations
    prove          commentary produced by the theorem prover
    proof-builder  commentary produced by the interactive proof-builder
    event          non-proof commentary produced by events such as defun
                   and encapsulate
    history        output from history commands such as :ubt and :pbt
    summary        the summary at the successful conclusion of an event
    proof-tree     proof-tree output
 })

 <p>It is possible to inhibit each kind of output by putting the corresponding
 name into @('lst').  For example, if @(''warning') is included in (the value
 of) @('lst'), then no warnings are printed except those related to soundness,
 e.g., the inclusion of an uncertified book.  Note that @(see proof-tree)
 output is affected by @('set-inhibit-output-lst'); see @(see proof-tree).</p>

 <p>Note that proof output can be controlled without inhibiting it using this
 utility, and indeed is already quite limited by default.  See @(tsee
 set-gag-mode).</p>

 <p>See @(see with-output) for a variant of this utility that can be used in
 @(see books).  Also see @(see set-inhibit-warnings) for how to inhibit
 individual warning types and see @(see set-inhibited-summary-types) for how to
 inhibit individual parts of the summary.</p>

 <p>Printing of events on behalf of @(tsee certify-book) and @(tsee
 encapsulate) is inhibited when both @(''event') and @(''prove') belong to
 @('lst').  Otherwise, printing of events is controlled by the @(tsee ld)
 special @(tsee ld-pre-eval-print).</p>

 <p>Normally, hard error messages (see @(see er)) are not inhibited.  To
 inhibit those as well when @('ERROR') output is inhibited: @('(assign
 inhibit-er-hard t)').  To restore the original behavior: @('(assign
 inhibit-er-hard nil)').</p>

 <p><i>Note for advanced users.</i> By including @('warning!') in @('lst'), you
 are automatically including @('warning') as well: all warnings will be
 inhibited.  This is not the case if you modify value of state global variable
 @(''inhibit-output-lst') directly (with @(tsee assign) or @('f-put-global'));
 then, if you include @('warning!') but not @('warning'), then warnings not
 related to soundness will still be printed (which is probably not what was
 intended).</p>")

(defxdoc set-inhibit-warnings
  :parents (prover-output)
  :short "Control warnings"
  :long "@({
  Examples:
  (set-inhibit-warnings \"theory\" \"use\")
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.  It is
 @(tsee local) to the book or @(tsee encapsulate) form in which it occurs; see
 @(see set-inhibit-warnings!) for a corresponding non-@(tsee local) event.
 Indeed, @('(set-inhibit-warnings ...)') is equivalent to @('(local
 (set-inhibit-warnings! ...))').</p>

 @({
  General Form:
  (set-inhibit-warnings string1 string2 ...)
 })

 <p>where each string is considered without regard to case.  This macro is
 equivalent to @('(local (table inhibit-warnings-table nil 'lst :clear))'),
 where @('lst') is the list of strings supplied.  This macro is an event (see
 @(see table)), but no output results from a @('set-inhibit-warnings')
 event.</p>

 <p>ACL2 prints warnings that may, from time to time, seem excessive to
 experienced users.  Each warning is ``labeled'' with a string identifying the
 type of warning.  Consider for example</p>

 @({
  ACL2 Warning [Use] in ( THM ...):  It is unusual to :USE ....
 })

 <p>Here, the label is \"Use\".  The argument list for
 @('set-inhibit-warnings') is a list of such labels, each of which is a string.
 Any warning is suppressed if its label is a member of this list, where case is
 ignored.  Thus, for example, the warning above will not be printed after a
 call of @('set-inhibit-warnings') that contains the string, @('\"Use\"') (or
 any string that is @(tsee string-equal) to @('\"Use\"'), such as @('\"use\"')
 or @('\"USE\"')).  In summary: the effect of this event is to suppress any
 warning whose label is a member of the given argument list, where case is
 ignored.</p>

 <p>The list of currently inhibited warnings is the list of keys in the @(see
 table) named @('inhibit-warnings-table').  (The values in the table are
 irrelevant.)  One way to get that value is to get the result from evaluating
 the following form: @('(table-alist 'inhibit-warnings-table (w state))').  Of
 course, if warnings are inhibited overall &mdash; see @(see
 set-inhibit-output-lst) &mdash; then this value is entirely irrelevant.</p>")

(defxdoc set-inhibit-warnings!
  :parents (prover-output)
  :short "Control warnings non-@(tsee local)ly"
  :long "<p>Please see @(see set-inhibit-warnings), which is the same as
 @('set-inhibit-warnings!')  except that the latter is not @(tsee local) to the
 @(tsee encapsulate) or the book in which it occurs.  Probably @(see
 set-inhibit-warnings) is to be preferred unless you have a good reason for
 wanting to export the effect of this event outside the enclosing @(tsee
 encapsulate) or book.</p>")

(defxdoc set-inhibited-summary-types
  :parents (prover-output)
  :short "Control which parts of the summary are printed"
  :long "@({
  Example:
  (set-inhibited-summary-types '(rules time))
 })

 <p>Note: This is not an event.  Rather, it changes the @(see state), in
 analogy to @(tsee set-inhibit-output-lst).</p>

 @({
  General Form:
  (set-inhibited-summary-types form)
 })

 <p>where form evaluates to a true-list of symbols, each of which is among the
 values of the constant @('*summary-types*'), i.e.: @('header'), @('form'),
 @('rules'), @('hint-events'), @('warnings'), @('time'), @('steps'),
 @('value'), and @('splitter-rules').  Each specified type inhibits printing of
 the corresponding portion of the summaries printed at the conclusions of @(see
 events), where @('header') refers to an initial newline followed by the line
 containing just the word @('Summary').</p>

 <p>Note the distinction between @('rules') and @('hint-events').  @('Rules')
 provides a record of automatic rule usage by the prover, while
 @('hint-events') shows the names of events given to @(':USE') or @(':BY')
 @(see hints), as well as @(see clause-processor) functions given to
 @(':CLAUSE-PROCESSOR') hints that have an effect on the proof.</p>

 <p>Also see @(see set-inhibit-output-lst).  Note that
 @('set-inhibited-summary-types') has no effect when @('summary') is one of the
 types inhibited by @(see set-inhibit-output-lst), because in that case none of
 the summary will be printed.</p>

 <p>To control summary types for a single event, see @(see with-output).</p>")

(defxdoc set-invisible-fns-table
  :parents (loop-stopper)
  :short "Set the invisible functions table"
  :long "@({
  Examples:
  (set-invisible-fns-table ((binary-+ unary--)
                            (binary-* unary-/)
                            (unary-- unary--)
                            (unary-/ unary-/)))
  (set-invisible-fns-table t) ; restore original invisible-fns-table
 })

 <p>Among other things, the setting above has the effect of making @(tsee
 unary--) ``invisible'' for the purposes of applying permutative @(':')@(tsee
 rewrite) rules to @(tsee binary-+) trees.  Thus, @('arg') and @('(unary--
 arg)') will be given the same weight and will be permuted so as to be
 adjacent.  The form @('(invisible-fns-table (w state))') returns the current
 value of the invisible functions table.</p>

 <p>Also see @(see add-invisible-fns) and see @(see remove-invisible-fns) for
 events that add to and remove from the invisible functions table, while
 accounting for macro aliases (see @(see macro-aliases-table)).</p>

 @({
  General Form:
  (set-invisible-fns-table alist)
 })

 <p>where @('alist') is either @('t') or a true list of pairs, each element of
 which is of the form @('(fn ufn1 ... ufnk)'), where @('fn') is a function
 symbol and each @('ufni') is a unary function symbol.  When alist is @('t'),
 the initial value of this table is used in its place.  Modulo the replacement
 of @('alist') by the default setting when @('alist') is @('t'), this macro is
 equivalent to</p>

 @({
  (table invisible-fns-table nil 'alist :clear)
 })

 <p>which is also an event (see @(see table)).</p>

 <p>Note that @('set-invisible-fns-table') does not evaluate its argument.
 However, you can call @(tsee table) directly for that purpose.  For
 example,</p>

 @({
  (set-invisible-fns-table ((binary-+ unary--)
                            (binary-* unary-/)
                            (unary-- unary--)
                            (unary-/ unary-/)))
 })

 <p>ie equivalent to the following; see @(see table).</p>

 @({
  (table invisible-fns-table nil
         (quote ((binary-+ unary--)
                 (binary-* unary-/)
                 (unary-- unary--)
                 (unary-/ unary-/)))
         :clear)
 })

 <p>See @(see invisible-fns-table) for a description of the invisible functions
 table.</p>")

(defxdoc set-iprint
  :parents (io)
  :short "Control whether abbreviated output can be read back in"
  :long "<p>The following log may be sufficient for you to see how to use
 @('set-iprint'); more explanation is below.  The example is taken from a
 session that used the @(see break-rewrite) utility, but familiarity with that
 utility is not necessary in order to understand this example.  What it shows
 is that the form @('(set-iprint t)') allows you to recover, using @(see
 without-evisc), output that had been hidden.</p>

 @({
 ACL2 !>(thm (p y))

 (1 Breaking (:REWRITE AX) on (P Y):
 1 ACL2 >:eval

 1x (:REWRITE AX) failed because :HYP 1 rewrote to
 (EQUAL Y '(NIL NIL NIL NIL ...)).

 1 ACL2 >:a!
 Abort to ACL2 top-level
 Here is the current pstack [see :DOC pstack]:
 (REWRITE-ATM SIMPLIFY-CLAUSE WATERFALL)

 *** Note: No checkpoints to print. ***

 ACL2 Version 6.4.  Level 1.  Cbd \"u/smith/\".
 System books directory \"/u/smith/acl2/v6-4/books/\".
 Type :help for help.
 Type (good-bye) to quit completely out of ACL2.

 ACL2 !>(set-iprint t)

 ACL2 Observation in SET-IPRINT:  Iprinting has been enabled.
 ACL2 !>(thm (p y))

 (1 Breaking (:REWRITE AX) on (P Y):
 1 ACL2 >:eval

 1x (:REWRITE AX) failed because :HYP 1 rewrote to
 (EQUAL Y '(NIL NIL NIL NIL . #@2#)).

 1 ACL2 >(without-evisc '(EQUAL Y '(NIL NIL NIL NIL . #@2#)))
 (EQUAL Y
        '(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
              NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
              NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
              NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
              NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
              NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
              NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
              NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
              NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
              NIL NIL NIL NIL NIL NIL NIL NIL NIL))
 1 ACL2 >
 })

 <p>This concludes the introductory example.</p>

 <p>When ACL2 pretty-prints large expressions using formatted printing
 (see @(see fmt)), it may save time and space by printing tokens `@('#')' or
 `@('...')' in place of certain subexpressions.  By default this only happens
 for a few settings such as error and warning messages; see @(see
 set-evisc-tuple) for controlling such elision in general.  The full expression
 is unavailable to the user when `@('#')' or `@('...')' is printed, but that is
 easily solved by evaluating the form</p>

 @({
    (set-iprint t)
 })

 <p>to enable a mode called ``iprinting''.  Then, instead of printing `@('#')'
 or `@('...')', ACL2 prints `@('#@i#')' for @('i') = 1,2,3,... &mdash; all in
 base 10.  ACL2 can read back in such `@('#@i#')' because under the hood,
 @('i') is associated with its corresponding elided form.  Thus the term
 ``iprint'' can be viewed as suggesting ``interactive print'' or ``index
 print''.  We also think of ``iprint'' as suggesting ``@('i') printing'', to
 suggest the printing of token `@('#@i#')'.  We call @('i') the ``iprint
 index'' of that token.</p>

 <p>The following example should suffice to illustrate how to recover elided
 subexpressions.  (Below this example we provide details that may be of
 interest only to advanced users.)  Here we cause an error by defining a macro
 of one argument and then calling it with two arguments.  By default, error
 messages abbreviate subexpressions deeper than level 5 with `@('#')' and past
 the 7th element of a list with `@('...')'.  We see this behavior below.</p>

 @({
  ACL2 !>(defmacro foo (x) x)

  Summary
  Form:  ( DEFMACRO FOO ...)
  Rules: NIL
  Warnings:  None
  Time:  0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
   FOO
  ACL2 !>(foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n))

  ACL2 Error in macro expansion:  Wrong number of args in macro expansion
  of (FOO ARG1 (A (B (C (D #))) H I J K L ...)).  (See :DOC set-iprint
  to be able to see elided values in this message.)

  ACL2 !>(set-iprint t)

  ACL2 Observation in SET-IPRINT:  Iprinting has been enabled.
  ACL2 !>(foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n))

  ACL2 Error in macro expansion:  Wrong number of args in macro expansion
  of (FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#)).

  ACL2 !>(acl2-count '(FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#)))
  23
  ACL2 !>
 })

 <p>Sometimes you may want to supply the abbreviated form not to compute with
 it, as in the @(tsee acl2-count) example just above, but so that you can see
 it.  The macro @(tsee without-evisc) eliminates elision during printing.
 Below we show two ways to use this utility: first, we use it to print the
 elided form, and then, we use it instead on the original input form to print
 the entire error message.</p>

 @({
  ACL2 !>(without-evisc '(FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#)))
  (FOO ARG1
       (A (B (C (D (E (F (G))))))
          H I J K L M N))
  ACL2 !>(without-evisc (foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n)))

  ACL2 Error in macro expansion:  Wrong number of args in macro expansion
  of (FOO ARG1 (A (B (C (D (E (F (G)))))) H I J K L M N)).

  ACL2 !>
 })

 <p>If you wish to know which elided expressions are equal, you may call
 @('set-iprint') with non-@('nil') value for keyword argument @(':share').
 That will turn on <i>iprint sharing</i>, which causes behavior as shown below:
 the value printed shows the iprint index 2 being used twice for the list @('(C
 D E F)').</p>

 @({
 ACL2 !>'((a b c d e f) (a b c d e f) (a b c d e f))
 ((A B . #@2#) (A B . #@2#) . #@3#)
 ACL2 !>
 })

 <p>We use the log displayed below to explain iprint sharing a bit more.  The
 Warning below is pointing out that previous iprint indices are no longer
 valid; we are starting over.  The first Observation points out that iprint
 sharing is on, and gives the name @(':IPRINT-FAL') to look for in
 @('(fast-alist-summary)') in case you want information on the @(see
 fast-alist) that associates values with corresponding iprint indices.  To see
 the relevance of a fast-alist, note that the two elided occurrences of the
 list @('(C D E F)') were originally not the identical list in memory; to make
 them identical, @(tsee hons-copy) is applied to each to get the same list in
 memory, which is the one associated with iprint index 2 in a fast-alist named
 @(':IPRINT-FAL').</p>

 @({
 ACL2 !>(set-iprint t :share t)

 ACL2 Warning [Iprint] in SET-IPRINT:  Converting SET-IPRINT action
 from T to :RESET-ENABLE, as required by use of keyword :SHARE or :HARD-
 BOUND.  See :DOC set-iprint.


 ACL2 Observation in SET-IPRINT:  Iprinting is enabled with sharing,
 with a fast-alist whose name is :IPRINT-FAL.

 ACL2 Observation in SET-IPRINT:  Iprinting has been reset and enabled.
 ACL2 !>(set-evisc-tuple (evisc-tuple 2 2 nil nil) :sites :all)
  (:TERM :LD . #@1#)
 ACL2 !>'((a b c d e f) (a b c d e f) (a b c d e f))
 ((A B . #@2#) (A B . #@2#) . #@3#)
 ACL2 !>'(b c d e f)
 (B C . #@4#)
 ACL2 !>
 })

 <p>One might have expected the last form printed above to take advantage of
 the fact that the tail @('(C D E F)') of the input's value is already
 associated with iprint index 2.  If you want that sort of behavior &mdash;
 that is, where we use an existing iprint index even when we have not yet
 reached the print-level or print-depth specified by our most recent call of
 @(tsee set-evisc-tuple) &mdash; then we can use the special value @(':eager')
 for keyword @(':share'), which gives us <i>eager iprinting</i>:</p>

 @({
 (set-iprint t :share :eager)
 })

 <p>If we use that call of @('set-iprint') instead of our earlier one above
 (that is, with @(':share t')), then the first of the two last results from the
 log above is unchanged, but in the second result, the tail @('(C D E F)') is
 indeed abbreviated using iprint index 2.</p>

 @({
 ACL2 !>'((a b c d e f) (a b c d e f) (a b c d e f))
 ((A B . #@2#) (A B . #@2#) . #@3#)
 ACL2 !>'(b c d e f)
 (B . #@2#)
 ACL2 !>
 })

 <p>The documentation above probably suffices for most users.  For those who
 want more details, below we detail all the ways to use the @('set-iprint')
 utility.</p>

 @({
  Example Forms:
  (set-iprint t)   ; enable iprinting (elision with #@i@)
  (set-iprint nil) ; disable iprinting

  General Form:
  (set-iprint action          ; t, nil, :reset, :reset-enable, or :same
              :share      sym ; initially nil
              :soft-bound s   ; initially  1000
              :hard-bound h   ; initially 10000)
 })

 <p>where all arguments are optional, but ACL2 queries for @('action') if it is
 omitted.  All arguments are evaluated.  When a keyword argument is omitted,
 there is no change in the behavior that it controls.  For now we defer further
 explanations of the keyword arguments.  The values for @('action') are as
 follows.</p>

 <blockquote>

 <p>@('t') &mdash; Enable iprinting.  If either keyword @(':share') or
 @(':hard-bound') is supplied, then @('t') is converted to
 @(':reset-enable').</p>

 <p>@('nil') &mdash; Disable iprinting.  If either keyword @(':share') or
 @(':hard-bound') is supplied, then @('nil') is converted to @(':reset').</p>

 <p>@(':reset') &mdash; Reset iprinting to its initial disabled state, so that
 when enabled, the first index @('i') for which `@('#@i#') is printed will be
 1.  Note that all stored information for existing iprint indices will be
 erased.</p>

 <p>@(':reset-enable') &mdash; Reset iprinting as with @(':reset'), and then
 enable iprinting.</p>

 <p>@(':same') &mdash; If either keyword @(':share') or @(':hard-bound') is
 supplied, then @(':same') is converted to @(':reset') or @(':reset-enable')
 according to whether iprinting is currently disabled or enabled, respectively.
 Otherwise, make no change to the iprinting state other than setting the
 @('soft-bound') if specified, as explained below.</p>

 </blockquote>

 <p>The value of @(':share') must be a symbol, with default @('nil').  If the
 value is @('nil'), then an elided value will be printed using the next
 available iprint index.  The value @(':same') is treated as though @(':share')
 had not been supplied.  Otherwise, iprint sharing is on, which provides the
 following behavior.  Suppose that a value @('V') is to be elided that would be
 assigned the next available iprint index, @('N').  If an iprint index @('I <
 N') is already associated with a value equal to @('V'), then ACL2 will print
 @('#@I') for @('V') instead of @('#@N').  Thus, @('N') will remain the next
 available iprint index.  This behavior is implemented using a @(see
 fast-alist) that associates values with indices; in our example, the @(tsee
 hons-copy) of @('V') is associated with @('I').  If the value of @(':share')
 is @('t') then the name of this fast-alist &mdash; that is, its initial value
 &mdash; is @(':iprint-fal'); otherwise, the value of @(':share') (other than
 @('nil') or @(':same')) is its name.  This name is useful when viewing the
 output of @(tsee fast-alist-summary).  Finally, a special case, called ``eager
 sharing'', is installed if the value of @(':share') is @(':eager').  In that
 case, the behavior described above &mdash; where @('#@I') is printed for
 @('V') &mdash; will occur even if the value @('V') would otherwise not be
 elided, provided the most recent call of @(tsee set-evisc-tuple) specified a
 non-@('nil') print-level or print-length.</p>

 <p>Immediately after a top-level form is read, hence before it is evaluated, a
 check is made for whether the latest iprint index exceeds a certain bound,
 @('(iprint-soft-bound state)') &mdash; 1000, by default.  If so, then the
 @('(iprint-last-index state)') is set back to 0 so that the next iprint index
 that is generated will be 1.  This soft bound can be changed to any positive
 integer @('k') by calling @('set-iprint') with @(':soft-bound k'), for
 example: @('(set-iprint :same :soft-bound k'))].</p>

 <p>The above ``soft bound'' is applied once for each top-level form, but you
 may want finer control by applying a bound after the pretty-printing of each
 individual form (since many forms may be pretty-printed between successive
 evaluations of top-level forms).  That bound is @('(iprint-hard-bound
 state)'), and can be set with the @(':hard-bound') argument in analogy to how
 @(':soft-bound') is set, as described above, but with the effect of resetting
 iprinting, with @('(iprint-last-index state)') set back to 0.</p>

 <p>A ``rollover'' is the detection that the soft or hard bound has been
 exceeded, along with a state update setting @('(iprint-last-index state)') to
 0 so that the next iprint index will be 1.  Immediately before a rollover, any
 index beyond the last iprint index used (which must be from before an earlier
 rollover) is no longer available for reading.  At the top level of the ACL2
 read-eval-print loop, this works as follows: ACL2 reads the next top-level
 form according to the current iprint state, then handles a rollover if the
 latest iprint index exceeded the current soft bound.  The following log
 illustrates a rollover, which follows the description above.</p>

 @({
  ACL2 !>(set-iprint t :soft-bound 3)

  ACL2 Observation in SET-IPRINT:  The soft-bound for iprinting has been
  set to 3.

  ACL2 Observation in SET-IPRINT:  Iprinting has been enabled.
  ACL2 !>(set-evisc-tuple (evisc-tuple 2 3 nil nil) :sites :ld)
   (:LD)
  ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g))
  ((A B C . #@1#) (A B C . #@2#) (A B C . #@3#))
  ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g))
  ((A B C . #@4#) (A B C . #@5#) (A B C . #@6#))
  ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#)))
  ((A B C D E F G)
   (A B C D E F G)
   (A B C D E F G))
  ACL2 !>'(1 2 3 4 5)
  (1 2 3 . #@1#)
  ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g))
  ((A B C . #@2#) (A B C . #@3#) (A B C . #@4#))
  ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#)))
  ((A B C D E F G)
   (A B C D E F G)
   (A B C D E F G))
  ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#)))

  ***********************************************
  ************ ABORTING from raw Lisp ***********
  ********** (see :DOC raw-lisp-error) **********
  Error:  Out-of-bounds index in #@5#.  See :DOC set-iprint.
  ***********************************************

  The message above might explain the error.  If not, and
  if you didn't cause an explicit interrupt (Control-C),
  then the root cause may be call of a :program mode
  function that has the wrong guard specified, or even no
  guard specified (i.e., an implicit guard of t).
  See :DOC guards.

  To enable breaks into the debugger (also see :DOC acl2-customization):
  (SET-DEBUGGER-ENABLE T)
  ACL2 !>
 })

 <p>Rollover has the following additional effect when iprint sharing is on: it
 is illegal to read a form that has both an index from before the rollover and
 an index from after the rollover.  The following log illustrates this
 requirement.  Note that if the last input form below were read without error,
 the result would likely be highly confusing, since iprint index 1 no longer
 refers to the value it was originally given at the time the other iprint
 indices in the input (2, 3, and 4) were given their values.</p>

 @({
 ACL2 !>(set-iprint t :soft-bound 3 :share t)

 ACL2 Warning [Iprint] in SET-IPRINT:  Converting SET-IPRINT action
 from T to :RESET-ENABLE, as required by use of keyword :SHARE or :HARD-
 BOUND.  See :DOC set-iprint.


 ACL2 Observation in SET-IPRINT:  The soft-bound for iprinting has been
 set to 3.

 ACL2 Observation in SET-IPRINT:  Iprinting is enabled with sharing,
 with a fast-alist whose name is :IPRINT-FAL.

 ACL2 Observation in SET-IPRINT:  Iprinting has been reset and enabled.
 ACL2 !>(set-evisc-tuple (evisc-tuple 2 3 nil nil) :sites :ld)
  (:LD)
 ACL2 !>'((a b c d) (x y z w))
 ((A B C . #@1#) (X Y Z . #@2#))
 ACL2 !>'((e f g h) (k l m n))
 ((E F G . #@3#) (K L M . #@4#))
 ACL2 !>'(#@1# #@2# #@3# #@4#) ; OK, since rollover occurs after the read
 ((D) (W) (H) . #@1#)
 ACL2 !>'(#@1# #@2# #@3# #@4#)

 ***********************************************
 ************ ABORTING from raw Lisp ***********
 ********** (see :DOC raw-lisp-error) **********
 Error:  Attempt to read a form containing both an index
 created before the most recent rollover (#@2#) and
 an index created after that rollover (#@1#).  See :DOC set-iprint.
 ***********************************************

 The message above might explain the error.  If not, and
 if you didn't cause an explicit interrupt (Control-C),
 then the root cause may be call of a :program mode
 function that has the wrong guard specified, or even no
 guard specified (i.e., an implicit guard of t).
 See :DOC guards.

 To enable breaks into the debugger (also see :DOC acl2-customization):
 (SET-DEBUGGER-ENABLE T)
 ACL2 !>
 })

 <p>We conclude by mentioning two cases where iprinting and evisc-tuples are
 ignored.  (1) This is typically the case when printing results in raw Lisp
 outside the ACL2 loop.  To use iprinting and evisc-tuples in raw Lisp, use
 raw-mode; see @(see set-raw-mode).  In raw-mode, results that are ACL2 objects
 will be printed in the same way that ACL2 would print those results if not in
 raw-mode.  (2) Iprinting and evisc-tuples are ignored by @(tsee
 print-object$), which however is sensitive to many settings that do not affect
 formatted (@(tsee fmt) etc.) printing; see @(see print-control).</p>

 <p>The reader interested in design and implementation issues considered during
 the addition of iprinting to ACL2 is invited to read the paper ``Abbreviated
 Output for Input in ACL2: An Implementation Case Study''; see the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/workshop-2009/'>proceedings of
 ACL2 Workshop 2009</a>.</p>")

(defxdoc set-irrelevant-formals-ok
  :parents (declare defun)
  :short "Allow irrelevant formals in definitions"
  :long "@({
  Examples:
  (set-irrelevant-formals-ok t)
  (set-irrelevant-formals-ok nil)
  (set-irrelevant-formals-ok :warn)
 })

 <p>The first example above allows irrelevant formals in definitions; see @(see
 irrelevant-formals).  The second example disallows irrelevant formals; this is
 the default.  The third example allows irrelevant formals, but prints an
 appropriate warning.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.
 Moreover, its effect is to set the @(tsee acl2-defaults-table), and hence its
 effect is @(tsee local) to the book or @(tsee encapsulate) form containing it;
 see @(see acl2-defaults-table).</p>

 @({
  General Form:
  (set-irrelevant-formals-ok flg)
 })

 <p>where @('flg') is either @('t'), @('nil'), or @(':warn').</p>

 <p>For a way to permit irrelevant formals in a specific definition, see @(see
 declare).</p>")

(defxdoc set-let*-abstractionp
  :parents (prover-output)
  :short "To shorten many prettyprinted clauses"
  :long "<p>Note: This is an event!  It does not print the usual event summary
 but nevertheless changes the ACL2 logical @(see world) and is so recorded.
 Moreover, its effect is to set the @(tsee acl2-defaults-table), and hence its
 effect is @(tsee local) to the book or @(tsee encapsulate) form containing it;
 see @(see acl2-defaults-table).</p>

 <p>When this flag is set to @('t'), subterms that occur more than once in a
 clause are abstracted away with @(tsee let*), generally shortening the
 displayed size of the clauses.  This flag only affects how clauses are
 printed.  It does not change what terms the theorem prover manipulates.</p>

 @({
  :set-let*-abstractionp t ;;; or, (set-let*-abstractionp t)
 })

 <p>will cause the prettyprinter to do ``let* abstraction'' on clauses before
 they are printed.  The algorithm finds the maximal multiply-occurring subterm
 and extracts it, binding it to some new variable and replacing its occurrences
 by that variable.  This produces a @('let*') form.  This process is iterated
 until no subterm occurs more than once.  This process generally takes a little
 time, but less time than to print large clauses.  The process can greatly
 reduce the amount of text produced by the prover.</p>

 <p>THIS ONLY AFFECTS HOW THE CLAUSES ARE PRINTED!  The unabstracted clauses
 are manipulated by the theorem prover.</p>

 @({
  :set-let*-abstractionp nil
 })

 <p>restores normal clause printing.</p>

 <p>The mode is stored in the defaults table, See @(see acl2-defaults-table).
 Thus, the mode may be set locally in books.</p>")

(defxdoc set-match-free-default
  :parents (free-variables)
  :short "Provide default for @(':match-free') in future rules"
  :long "@({
  General Forms:
  (set-match-free-default :once)
  (set-match-free-default :all)
  (set-match-free-default nil)
 })

 <p>Note: This utility does not apply to @(see type-prescription) rules; for a
 related topic pertinent to such rules, see @(see
 free-variables-type-prescription).</p>

 <p>As described elsewhere (see @(see free-variables)), a @(see rewrite), @(see
 linear), or @(see forward-chaining) rule may have free variables in its
 hypotheses, and ACL2 can be directed either to try all bindings
 (``@(':all')'') or just the first (``@(':once')'') when relieving that
 hypothesis, as a basis for relieving subsequent hypotheses.  This directing of
 @(':all') or @(':once') is generally provided by specifying either
 @(':match-free :once') or @(':match-free :all') in the @(':')@(tsee
 rule-classes) of the rule.  If neither of these is specified, then the most
 recent @('set-match-free-default') is used by ACL2 to fill in this missing
 @(':match-free') field.  See @(see rule-classes).  Except: If the last
 @('set-match-free-default') specifies @('nil'), then ACL2 reverts to the
 behavior it had at start-up, as described in Remarks (2) and (3) below.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.  It
 uses the @(tsee acl2-defaults-table), and hence its effect is @(tsee local) to
 the book or @(tsee encapsulate) form in which it occurs.</p>

 <p>Remarks.</p>

 <p>(1) The use of @('set-match-free-default') has no effect on existing rules.
 In order to change the behavior of existing rules with respect to
 free-variable matching, see @(see add-match-free-override).</p>

 <p>(2) If you submit a @(see rewrite), @(see linear), or @(see
 forward-chaining) rule with a free variable in a hypothesis, and no default
 setting was previously specified with @('set-match-free-default') or the
 default setting is @('nil'), and the rule is not within a book being processed
 with @(tsee include-book), @(tsee certify-book), or @(tsee rebuild), then a
 warning or error is caused.  In order to make this an error instead of a
 warning, see @(see set-match-free-error).</p>

 <p>(3) If you submit a @(see rewrite), @(see linear), or @(see
 forward-chaining) rule with a free variable in a hypothesis, and no default
 setting has been previously specified with @('set-match-free-default') or the
 default setting is @('nil'), and no error is caused (see (2) above), then the
 default @(':all') is used.</p>")

(defxdoc set-match-free-error
  :parents (free-variables)
  :short "Control error vs. warning when @(':match-free') is missing"
  :long "@({
  Legal Forms:
  (set-match-free-error nil)
  :set-match-free-error nil
  (set-match-free-error t)
  :set-match-free-error t
 })

 <p>As described elsewhere (see @(see free-variables)), when a @(see rewrite),
 @(see linear), or @(see forward-chaining) rule has free variables in its
 hypotheses, the user can specify whether to try all bindings (``@(':all')'')
 or just the first (``@(':once')'') when relieving its hypotheses, as a basis
 for relieving subsequent hypotheses.  This direction of @(':all') or
 @(':once') is generally provided by specifying either <i>:match-free :once</i>
 or <i>:match-free :all</i> in the @(':')@(tsee rule-classes) of the rule.</p>

 <p>But suppose that neither of these is specified for such a rule.  (Note:
 @('set-match-free-error') is not relevant for @(see type-prescription) rules.)
 Also suppose that @('set-match-free-default') has not specified a default of
 @(':once') or @(':all') (see @(see set-match-free-default)).  In this case a
 warning will occur except when in the context of @(tsee include-book).  If you
 prefer to see an error in such cases, except in the context of @(tsee
 certify-book), execute @('(set-match-free-error t)').  If there is no error,
 then a default of @(':all') is used.</p>

 <p>Note: This is NOT an event!  Instead, @('set-match-free-error') sets the
 state global @(''match-free-error') (see @(see state) and see @(see assign)).
 Thus, this form cannot be put into a book.  If you are tempted to put it into
 a book, consider the fact that it really isn't needed there, since the absence
 of @(':match-free') does not cause an error in the context of @(tsee
 certify-book) or @(tsee include-book).  If you still feel the need for such a
 form, consider using @('set-match-free-default') to provide a default, at
 least within the scope of the current book (if any); see @(see
 set-match-free-default).</p>")

(defxdoc set-measure-function
  :parents (defun)
  :short "Set the default measure function symbol"
  :long "@({
  Examples:
  (set-measure-function nqthm::count)
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 @({
  General Form:
  (set-measure-function name)
 })

 <p>where @('name') is a function symbol of one argument.  This macro is
 equivalent to @('(table acl2-defaults-table :measure-function 'name)'), and
 hence is @(tsee local) to any @(see books) and @(tsee encapsulate) @(see
 events) in which it occurs; see @(see acl2-defaults-table).  Although this is
 thus an event (see @(see table)), nevertheless no output results from a
 @('set-measure-function') event.</p>

 <p>This event sets the default measure function to @('name').  Subsequently,
 if a recursively defined function is submitted to @(tsee defun) with no
 explicitly given @(':measure') argument, @(tsee defun) ``guesses'' the measure
 @('(name var)'), where @('name') is the then current default measure function
 and @('var') is the first formal found to be tested along every branch and
 changed in every recursive call.</p>

 <p>Note that if @('(table acl2-defaults-table :measure-function 'name)') has
 its default value of @('nil'), then the default measure function is @(tsee
 acl2-count).</p>")

(defxdoc set-non-linearp
  :parents (non-linear-arithmetic)
  :short "To turn on or off non-linear arithmetic reasoning"
  :long "@({
  Examples:
  (set-non-linearp t)
  (set-non-linearp nil)
 })

 <p>See @(see non-linear-arithmetic).  This event is equivalent to @('(table
 acl2-defaults-table :non-linearp <t-or-nil>)'), and hence is @(tsee local) to
 any @(see books) and @(tsee encapsulate) @(see events) in which it occurs; see
 @(see acl2-defaults-table).</p>

 <p>The initial value is @('nil').</p>")

(defxdoc set-override-hints
  :parents (override-hints)
  :short "Set the @(see override-hints)"
  :long "<p>See @(see override-hints) for a discussion of override-hints.  Here
 we describe how to set them.  Note that the effects of @('set-override-hints')
 @(see events) are @(see local) to the @(see books) or @('encapsulate') @(see
 events) in which they reside; see @(see set-override-hints!) to avoid that
 restriction.  Also see @(see add-override-hints) to add to the list of
 override-hints, rather than setting a new list and ignoring the present
 list.</p>

 @({
  General Form:
  (set-override-hints form)
 })

 <p>where @('form') evaluates to a list of computed hint forms.  The effect of
 this event is to set the list of @(see override-hints) to the result of that
 evaluation.</p>")

(defxdoc set-override-hints!
  :parents (override-hints)
  :short "Set the @(see override-hints) non-@(see local)ly"
  :long "<p>@('Set-override-hints!') is the same as @(tsee set-override-hints),
 except that the former is not @(see local) to @(see books) or @(tsee
 encapsulate) @(see events) in which it occurs.  See @(see set-override-hints);
 also see @(see add-override-hints).</p>")

(defxdoc set-parallel-execution
  :parents (parallelism)
  :short "For ACL2(p): enabling parallel execution for four parallelism primitives"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).  See @(see parallelism-tutorial) for an introduction to parallel
 execution in ACL2.</p>

 @({
  General Forms:
  (set-parallel-execution nil) ; default for images not built for parallelism
  (set-parallel-execution t)   ; default for images built for parallelism
  (set-parallel-execution :bogus-parallelism-ok)
 })

 <p>@('Set-parallel-execution') takes an argument that specifies the enabling
 or disabling of @(see parallel) execution for the primitives @(tsee pand),
 @(tsee por), @(tsee plet), and @(tsee pargs) (but not @(tsee spec-mv-let),
 whose parallel execution remains enabled).  However, without using @(tsee
 top-level), calls of parallelism primitives made explicitly in the ACL2
 top-level loop, as opposed to inside function bodies, will never cause
 parallel execution; see @(see parallelism-at-the-top-level).  Parallel
 execution is determined by the value of the argument to
 @('set-parallel-execution'), as follows.</p>

 <p>Value @('t'):<br></br>

 All parallelism primitives used in bodies of function definitions are given
 the opportunity to execute in parallel.  However, the use of parallelism
 primitives directly in the ACL2 top-level loop causes an error.</p>

 <p>Value @(':bogus-parallelism-ok'):<br></br>

 Parallel execution is enabled, as for value @('t').  However, the use of
 parallelism primitives directly in the ACL2 top-level loop does not cause an
 error, but rather, simply results in serial execution for these
 primitives.</p>

 <p>Value @('nil'):<br></br>

 All parallelism primitives degrade to their serial equivalents, including
 their calls made directly in the ACL2 top-level loop.  Thus, uses of
 parallelism primitives do not in themselves cause errors.</p>")

(defxdoc set-print-base
  :parents (io acl2-built-ins)
  :short "Control radix in which numbers are printed"
  :long "<p>Also see @(tsee set-print-base-radix) for a nice combined use of
  @('set-print-base') and @(tsee set-print-radix).</p>

 <p>By default, integers and ratios are printed in base 10.  ACL2 also supports
 printing in radix 2, 8, or 16 by calling set-print-base with the desired
 radix (base).</p>

 @({
    (set-print-base 10 state) ; Default printing
    (set-print-base 16 state) ; Print integers and ratios in hex
 })

 <p>Here is a sample log.</p>

 @({
    ACL2 !>(list 25 25/3)
    (25 25/3)
    ACL2 !>(set-print-base 16 state)
    <state>
    ACL2 !>(list 25 25/3)
    (19 19/3)
    ACL2 !>
 })

 <p>See @(see set-print-radix) for how to print the radix, for example,
 printing the decimal number 25 in print-base 16 as ``@('#x25')'' rather than
 ``@('25')''.  Also see @(see print-control) for other user-settable print
 controls.</p>

 <p>Note: ACL2 @(see events) and some other top-level commands (for example,
 @(tsee thm), @(tsee verify), and history commands such as @(':')@('pe') and
 @(':')@('pbt')) set the print base to 10 during their evaluation.  So @(tsee
 set-print-base) has no effect while these forms are being processed.</p>")

(defxdoc set-print-base-radix
  :parents (io acl2-built-ins)
  :short "Control radix in which numbers are printed and printing of the radix"
  :long "<p>See @(tsee set-print-base) and @(tsee set-print-radix) for detailed
 discussions of those functions.  @('Set-print-base-radix') combines their
 functionality by setting the radix (as is done by @(tsee set-print-base)), and
 then causing the radix to be printed (as is done by @(tsee set-print-radix))
 exactly when the specified radix is not 10.</p>

 <p>Here is a sample log.</p>

 @({
 ACL2 !>(list 25 25/3)
 (25 25/3)
 ACL2 !>(set-print-base-radix 16 state)
 <state>
 ACL2 !>(list 25 25/3)
 (#x19 #x19/3)
 ACL2 !>(set-print-base-radix 10 state)
 <state>
 ACL2 !>(list 25 25/3)
 (25 25/3)
 ACL2 !>
 })")

(defxdoc set-print-case
  :parents (io acl2-built-ins)
  :short "Control whether symbols are printed in upper case or in lower case"
  :long "<p>By default, symbols are printed in upper case when vertical bars
 are not required, as specified by Common Lisp.  As with Common Lisp, ACL2
 supports printing in a \"downcase\" mode, where symbols are printed in lower
 case.  Many printing functions (some details below) print characters in lower
 case for a symbol when the ACL2 @(see state) global variable @('print-case')
 has value @(':downcase') and vertical bars are not necessary for printing that
 symbol.  (Thus, this state global functions in complete analogy to the Common
 Lisp global @('*print-case*').)  The value @('print-case') is returned by
 @('(print-case)'), and may be set using the function @('set-print-case') as
 follows.</p>

 @({
    (set-print-case :upcase   state) ; Default printing
    (set-print-case :downcase state) ; Print symbols in lower case when
                                     ; vertical bars are not required
 })

 <p>The ACL2 user can expect that the @(':downcase') setting will have an
 effect for formatted output (see @(see fmt) and see @(see fms)) when the
 directives are @('~p'), @('~P'), @('~q'), or @('~Q'), for built-in functions
 @('princ$') and @('prin1$'), and the @('ppr') family of functions, and
 <i>not</i> for built-in function @('print-object$').  For other printing
 functions, the effect of @(':downcase') is unspecified.</p>

 <p>Also see @(see print-control) for other user-settable print controls.</p>")

(defxdoc set-print-clause-ids
  :parents (prover-output)
  :short "Cause subgoal numbers to be printed when @(''prove') output is
  inhibited"
  :long "@({
  General Forms:
  (set-print-clause-ids t)
  :set-print-clause-ids t
  (set-print-clause-ids nil)
  :set-print-clause-ids nil
 })

 <p>This command affects output from the theorem prover only when @(''prove')
 output is inhibited (see @(see set-inhibit-output-lst)) or gag-mode is on (but
 in that case the @(':goals') setting issues this command automatically; see
 @(see set-gag-mode)).  Calling this macro with value @('t') as shown above
 will cause subsequent proof attempts with @(''prove') output inhibited to
 print the subgoal number, so that you can see the progress of the proof; value
 @('nil') reverts to the default behavior, where this is not the case.  On a
 related note, we point out that you can cause output to be saved for later
 display; see @(see pso) and see @(see pso!).</p>

 <p>If @(''prove') output is inhibited or gag-mode is on, and if you issue
 @('(set-print-clause-ids t)') (either explicitly or with @('(set-gag-mode
 :goals)')), then you can restrict when subgoal numbers are printed.  In the
 following example we restrict to subgoals that are no more than four
 inductions deep, no more than four casesplits deep, and no more than four
 single-subgoals deep.  For additional relevant explanation, see @(see
 clause-identifier) and see @(see defattach).</p>

 @({
  (defun print-clause-id-okp-level-4 (cl-id)
    (declare (xargs :mode :logic :guard (clause-id-p cl-id)))
    (and (<= (length (access clause-id cl-id :pool-lst))
             4)
         (<= (length (access clause-id cl-id :case-lst))
             4)
         (<= (access clause-id cl-id :primes)
             4)))

  (defattach print-clause-id-okp print-clause-id-okp-level-4)
 })")

(defxdoc set-print-gv-defaults
  :parents (print-gv guard debugging)
  :short "Set default keyword values for @(tsee print-gv)"
  :long "@({
 Example Forms:
 (set-print-gv-defaults :conjunct t)
 (set-print-gv-defaults :conjunct t :substitute t)
 (set-print-gv-defaults :conjunct t :substitute 20)
 (set-print-gv-defaults :evisc-tuple
                        (evisc-tuple 4   ; print-level
                                     5   ; print-length
                                     (world-evisceration-alist state nil)
                                     nil ; hiding-cars
                                     ))
 (set-print-gv-defaults :conjunct :restore
                        :substitute :restore
                        :evisc-tuple :restore)
 (set-print-gv-defaults)

 General Form:
 (set-print-gv-defaults :conjunct c
                        :substitute s
                        :evisc-tuple e)
 })

 <p>where any or all of @('c'), @('s'), and @('e') may be the keyword,
 @(':restore'), and otherwise these are as for @(tsee print-gv).  These forms
 set the defaults for the corresponding keyword arguments of the @('print-gv')
 utility, where the value @(':restore') restores the system defaults; see @(see
 print-gv).  Evaluation returns an @(see error-triple) whose value is an alist
 associating keywords with their current defaults.  In particular, the call
 @('(set-print-gv-defaults)') simply returns an error-triple with that alist as
 the value, without changing any defaults.</p>

 <p>Thus, for example, if you submit the form</p>

 @({
 (set-print-gv-defaults :substitute t
                        :conjunct t
                        :evisc-tuple (evisc-tuple 3 4 nil nil))
 })

 <p>then subsequently, if you submit the form @(':print-gv') or @('(print-gv'))
 it would be interpreted as follows.</p>

 @({
 (print-gv :substitute t
           :conjunct t
           :evisc-tuple (evisc-tuple 3 4 nil nil))
 })

 <p>Of course, you can override your defaults, so that for example if you
 subsequently submit the form @('(print-gv :substitute nil)') or the form
 @('(print-gv :substitute nil :evisc-tuple (print-gv-evisc-tuple))'), these
 would be equivalent to submitting the following forms, respectively.</p>

 @({
 (print-gv :substitute nil
           :conjunct t
           :evisc-tuple (evisc-tuple 3 4 nil nil))
 (print-gv :substitute nil
           :conjunct t
           :evisc-tuple (print-gv-evisc-tuple))
 })
 ")

(defxdoc set-print-radix
  :parents (io acl2-built-ins)
  :short "Control printing of the radix for numbers"
  :long "<p>Also see @(tsee set-print-base-radix) for a nice combined use of
  @(tsee set-print-base) and @('set-print-radix').</p>

 <p>See @(see set-print-base) for background on how the print base affects the
 printing of numbers.  @('set-print-radix') affects whether a radix indicated
 when a number is printed.  The radix is not indicated by default, or after
 evaluating @('(set-print-radix nil state)').  But if @('set-print-radix') is
 called with a first argument that evaluates to a non@('nil') value &mdash; for
 example, @('(set-print-radix t state)') &mdash; then the radix is shown when
 printing.  (This behavior is consistent with the handling of Common Lisp
 global @('*print-radix*').)  The following log illustrates how this works.</p>

 @({
  ACL2 !>(list 25 25/3)
  (25 25/3)
  ACL2 !>(set-print-base 16 state)
  <state>
  ACL2 !>(list 25 25/3)
  (19 19/3)
  ACL2 !>(set-print-radix t state)
  <state>
  ACL2 !>(list 25 25/3)
  (#x19 #x19/3)
  ACL2 !>(set-print-base 10 state)
  <state>
  ACL2 !>(list 25 25/3)
  (25. #10r25/3)
  ACL2 !>(set-print-radix nil state)
  <state>
  ACL2 !>(list 25 25/3)
  (25 25/3)
  ACL2 !>
 })")

(defxdoc set-prover-step-limit
  :parents (miscellaneous)
  :short "Sets the step-limit used by the ACL2 prover"
  :long "<p>This event provides a way to limit the number of so-called ``prover
 steps'' permitted for an event.  See @(see with-prover-step-limit) for a way
 to specify the limit on prover steps for a single event, rather than globally.
 For a related utility based on time instead of prover steps, see @(see
 with-prover-time-limit).  For examples of how step limits work, see the
 community book @('books/misc/misc2/step-limits.lisp').  For a utility that
 returns an indicator of the number of prover steps most recently taken, see
 @(see last-prover-steps).</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.
 Moreover, its effect is to set the @(tsee acl2-defaults-table), and hence its
 effect is @(tsee local) to the book or @(tsee encapsulate) form containing it;
 see @(see acl2-defaults-table).</p>

 @({
  Example Forms:
  (set-prover-step-limit *default-step-limit*) ; no limit on prover steps
  (set-prover-step-limit nil)   ; abbreviation for the form just above
  (set-prover-step-limit 10000) ; allow at most 10,000 prover steps per event

  General Form:
  (set-prover-step-limit expr)
 })

 <p>where @('expr') evaluates either to @('nil') or else to a natural number
 not exceeding the value of @('*default-step-limit*').  If that value is
 @('nil') or the value of @('*default-step-limit*'), then no default limit is
 placed on the number of prover ``steps'' (see below) during processing of an
 event.  Otherwise, that value is the maximum number of prover steps permitted
 before an error occurs.</p>

 <p>This event specifies the limit on the number of ``steps'' counted by the
 ACL2 prover during processing of an event.  Currently, a step is counted for
 each call of the system functions @('rewrite') and @('expand-abbreviations').
 However, the steps counted may change in future releases of ACL2, so users
 would probably be well served by avoiding the assumption that only the above
 two calls are counted as prover steps.</p>

 <p>Depending on the computer you are using, you may have less than a half-hour
 of time before the number of prover steps exceeds the maximum step-limit,
 which is one less than the value of @('*default-step-limit*').  Note however
 the exception stated above: if the ``limit'' is @('nil') or is the value of
 @('*default-step-limit*'), then no limit is imposed.</p>

 <p>There is at best a loose connection between the counting of steps and
 @(tsee with-prover-time-limit).  In particular, for a call of @('mfc-rw') or
 any @('mfc-') function (see @(see extended-metafunctions)), the steps taken
 during that call are forgotten when returning from that call.</p>

 <p>The limit is relevant for every event, as well as for calls of @(tsee thm)
 and @(tsee certify-book) &mdash; and more generally, to any form that creates
 a ``summary context'' to print the usual event summary.  The limit is also put
 in force when entering the interactive @(see proof-builder).  A call of
 @('set-prover-step-limit') applies to each subsequent form unless the call of
 @('set-prover-step-limit') is within a summary context, in which case its
 effect disappears when exiting that summary context.</p>

 <p>The limit applies to each event, not just ``atomic'' events.  Consider the
 following example.</p>

 @({
  (set-prover-step-limit 500)

  (encapsulate
    ()
    (defthm lemma-1 ; takes 380 steps
      (equal (append (append x y) z) (append x y z))
      :rule-classes nil)
    (defthm lemma-2 ; would take 319 steps
      (equal (len (append x y)) (+ (len x) (len y)))
      :rule-classes nil))
 })

 <p>The first @(tsee defthm) event, @('lemma-1') takes 380 steps (as of this
 writing), as shown in the summary:</p>

 @({
  Prover steps counted:  380
  LEMMA-1
 })

 <p>The second @(tsee defthm) event, @('lemma-2'), takes 319 steps (as of this
 writing) when evaluated at the top level.  However, in the context above, 380
 steps of the available 500 steps (from the @('set-prover-step-limit') event
 above) have already been taken under the above @(tsee encapsulate) event.
 Thus, when the number of steps would exceed 120, the proof of @('lemma-2') is
 aborted:</p>

 @({
  ACL2 Error in STEP-LIMIT:  The prover step-limit, which is 120 in the
  current context, has been exceeded.  See :DOC set-prover-step-limit.
 })

 <p>The summary for @('lemma-2') reflects that situation:</p>

 @({
  Prover steps counted:  More than 120
 })

 <p>The summary for the @(tsee encapsulate) event then indicates that the
 available steps for that event have also been exceeded:</p>

 @({
  Prover steps counted:  More than 500
 })

 <p>The discussion above applies to any event that contains other events, hence
 applies similarly to @(tsee progn) events.</p>

 <p>For those who use @(tsee make-event), we note that prover steps in the
 expansion phase similarly contribute to the total number of steps counted.
 For example, suppose that the limit is 500 prover steps as above, and you
 submit @('(make-event EXPR)'), where 300 prover steps take place during
 evaluation of @('EXPR'), producing event @('EV').  Then evaluation of @('EV')
 will cause an error if it takes more than 200 prover steps.  This observation
 actually can be used to count prover steps for sequences of forms that are not
 all legal @(tsee events) (see @(see embedded-event-form)), such as calls of
 @(tsee thm).  For example, a small built-in ACL2 test suite that includes
 @(tsee thm) forms can be run by evaluating the form @('(mini-proveall)'), and
 the steps can be counted as shown below.  (Here we assume a fresh ACL2
 session; an error would occur if first, we evaluate the event
 @('(set-prover-step-limit 500)') displayed above.)</p>

 @({
  ACL2 !>(make-event (er-progn (mini-proveall) (value '(value-triple nil))))
  [[... output omitted here ...]]
  Summary
  Form:  ( MAKE-EVENT (ER-PROGN ...))
  Rules: NIL
  Warnings:  Double-rewrite, Equiv, Subsume and Non-rec
  Time:  0.38 seconds (prove: 0.04, print: 0.29, other: 0.05)
  Prover steps counted:  41090
   NIL
  ACL2 !>
 })")

(defxdoc set-raw-mode
  :parents (defttag)
  :short "Enter or exit ``raw mode,'' a raw Lisp environment"
  :long "<p>Below we discuss raw-mode.  In brief: The simplest way to turn
 raw-mode on is @(':SET-RAW-MODE-ON!'), and to turn it off, @(':SET-RAW-MODE
 NIL').  Also see @(see set-raw-mode-on!).</p>

 <p>ACL2 users often find its careful syntax checking to be helpful during code
 development.  Sometimes it is even useful to do code development in
 @(':')@(tsee logic) mode, where ACL2 can be used to check termination of
 (mutually) recursive functions, verify guards, or even prove properties of the
 functions.</p>

 <p>However, loading code using @(tsee include-book) is much slower than using
 Common Lisp @('load') in raw Lisp, and in this sense ACL2 can get in the way
 of efficient execution.  Unfortunately, it is error-prone to use ACL2 sources
 (or their compilations) in raw Lisp, primarily because a number of ACL2
 primitives will not let you do so.  Perhaps you have seen this error message
 when trying to do so:</p>

 @({
  HARD ACL2 ERROR in ACL2-UNWIND-PROTECT:  Apparently you have tried
  to execute a form in raw Lisp that is only intended to be executed
  inside the ACL2 loop.
 })

 <p>Even without this problem it is important to enter the ACL2 loop (see @(see
 lp)), for example in order to set the @(tsee cbd) and (to get more technical)
 the readtable.</p>

 <p>ACL2 provides a ``raw mode'' for execution of raw Lisp forms.  In this
 mode, @(tsee include-book) reduces essentially to a Common Lisp @('load').
 More generally, the ACL2 logical @(tsee world) is not routinely extended in
 raw mode (some sneaky tricks are probably required to make that happen).  To
 turn raw mode off or on:</p>

 @({
  :set-raw-mode t   ; turn raw mode on
  :set-raw-mode nil ; turn raw mode off
 })

 <p>The way you can tell that you are in raw mode is by looking at the prompt
 (see @(see default-print-prompt)), which uses a capital ``@('P')'' (suggesting
 something like program mode, but more so).</p>

 @({
  ACL2 P>
 })

 <p>Typical benefits of raw mode are fast loading of source and compiled files
 and the capability to hack arbitrary Common Lisp code in an environment with
 the ACL2 sources loaded (and hence with ACL2 primitives available).  In
 addition, ACL2 hard errors will put you into the Lisp debugger, rather than
 returning you to the ACL2 loop, and this may be helpful for debugging; see
 @(see hard-error) and see @(see illegal), but also see @(see break-on-error).
 However, it probably is generally best to avoid raw mode unless these
 advantages seem important.  We expect the main benefit of raw mode to be in
 deployment of applications, where load time is much faster than the time
 required for a full-blown @(tsee include-book), although in certain cases the
 fast loading of books and treatment of hard errors discussed above may be
 useful during development.</p>

 <p>Raw mode is also useful for those who want to build extensions of ACL2.
 For example, the following form can be put into a certifiable book to load an
 arbitrary Common Lisp source or compiled file.</p>

 @({
  (progn (defttag my-application)
         (progn! (set-raw-mode t)
                 (load \"some-file\")))
 })

 <p>Also see @(see include-raw) and @(see with-raw-mode).  See @(see defttag),
 and see @(see progn!).</p>

 <p>Below are several disadvantages to raw mode.  These should discourage users
 from using it for general code development, as @(':')@(tsee program) mode is
 generally preferable.</p>

 <ul>
 <li>Forms are in essence executed in raw Lisp.  Hence:
     <ul>
     <li>Syntax checking is turned off; and</li>
     <li>Guard checking is completely disabled.</li>
     </ul></li>
 <li>Table events, including @(tsee logic), are ignored, as are many
     other @(tsee events), including @(tsee defthm) and @(tsee comp).</li>
 <li>Soundness claims are weakened for any ACL2 session in which raw
     mode was ever entered; see @(see defttag).</li>
 <li>The normal undoing mechanism (see @(see ubt)) is not supported.</li>
 <li>Unexpected behavior may occur when you return from raw-mode.
    For example, if you redefine a :logic mode function whose guards
    have not been verified, you will not see the change inside the
    ACL2 loop because there, the raw Common Lisp definition is only
    executed after guards have been verified; see @(see guards-and-evaluation)
    and see @(see guard-evaluation-table).</li>
 </ul>

 <p>We conclude with some details.</p>

 <p><i>Printing results</i>.  The rules for printing results are unchanged for
 raw mode, with one exception.  If the value to be printed would contain any
 Lisp object that is not a legal ACL2 object, then the @('print') routine is
 used from the host Lisp, rather than the usual ACL2 printing routine.  The
 following example illustrates the printing used when an illegal ACL2 object
 needs to be printed.  Notice how that ``command conventions'' are observed
 (see @(see ld-post-eval-print)); the ``@('[Note')'' occurs one space over in
 the second example, and no result is printed in the third example.</p>

 @({
  ACL2 P>(find-package \"ACL2\")
  [Note:  Printing non-ACL2 result.]
  #<The ACL2 package>
  ACL2 P>(mv nil (find-package \"ACL2\") state)
   [Note:  Printing non-ACL2 result.]
  #<The ACL2 package>
  ACL2 P>(mv t (find-package \"ACL2\") state)
  ACL2 P>(mv 3 (find-package \"ACL2\"))
  [Note:  Printing non-ACL2 result.]
  (3 #<The ACL2 package>)
  ACL2 P>
 })

 <p>If you have trouble with large structures being printed out, you might want
 to execute appropriate Common Lisp forms in raw mode, for example, @('(setq
 *print-length* 5)') and @('(setq *print-level* 5)').</p>

 <p><i>Include-book</i>.  The @(see events) @(tsee add-include-book-dir),
 @(tsee add-include-book-dir!), @(tsee delete-include-book-dir), and @(tsee
 delete-include-book-dir!) have been designed to work with raw mode.  However,
 if you enter raw mode and then evaluate such forms, then the effects of these
 forms will disappear when you exit raw mode, in which case you can expect to
 see a suitable warning.  Regarding <i>include-book</i> itself: it should work
 in raw mode as you might expect, at least if a compiled file or expansion file
 was created when the book was certified; see @(see certify-book).</p>

 <p><i>Packages</i>.  Raw mode disallows the use of @(tsee defpkg).  If you
 want to create a new package, first exit raw mode with @(':set-raw-mode nil');
 you can subsequently re-enter raw mode with @(':set-raw-mode t') if you
 wish.</p>")

(defxdoc set-raw-mode-on
  :parents (defttag)
  :short "Enter ``raw mode,'' a raw Lisp environment (requires trust tag)"
  :long "<p>@('(Set-raw-mode-on state)') is equivalent to @('(')@(tsee
 set-raw-mode)@(' t)'); see @(see set-raw-mode).  Both require an active trust
 tag; see @(see defttag).  Also see @(see set-raw-mode-on!), which first
 introduces a trust tag.</p>")

(defxdoc set-raw-mode-on!
  :parents (defttag)
  :short "Enter ``raw mode,'' a raw Lisp environment (adds trust tag)"
  :long "<p>This is equivalent to @('(')@(tsee set-raw-mode)@(' t)') except
 that it first introduces the required trust tag; see @(see defttag).  See
 @(see set-raw-mode) for a discussion of raw-mode.</p>")

(defxdoc set-raw-proof-format
  :parents (prover-output)
  :short "Print runes as lists in proof output from simplification"
  :long "@({
  General Forms:
  (set-raw-proof-format t)
  :set-raw-proof-format t
  (set-raw-proof-format nil)
  :set-raw-proof-format nil
 })

 <p>This command affects output from the theorem prover only when @(''prove')
 output is not inhibited (see @(see set-inhibit-output-lst)) and gag-mode is
 off (see @(see set-gag-mode)).  Calling this macro with value @('t') as shown
 above will cause simplification steps from proof output, including steps from
 preprocess (see @(see simple)), to print the list of runes used in a list
 format, rather than in the English proof commentary.  This ``raw'' format can
 be handy when you want to use that list as a basis for @(tsee hints) that you
 construct for a subsequent proof attempt.</p>

 <p>To obtain the current raw-proof-format (@('t') if that format is active,
 @('nil') if not), evaluate @('(@ raw-proof-format)').</p>")

(defxdoc set-raw-warning-format
  :parents (prover-output)
  :short "Print some warnings in a ``raw'', s-expression format"
  :long "@({
  General Forms:
  (set-raw-warning-format t)
  :set-raw-warning-format t
  (set-raw-warning-format nil)
  :set-raw-warning-format nil
 })

 <p>This command affects @(''warning') (and @(''warning!')) output from the
 theorem prover when not inhibited (see @(see set-inhibit-output-lst)).
 Calling this macro with value @('t') as shown above will cause warnings to be
 printed in a ``raw'', s-expression format, of the form @('(:WARNING
 warning-type alist)').  The following example shows a traditional warning
 message followed by its counterpart after evaluating
 @('(set-raw-warning-format t)').</p>

 @({
 ; default format
 ACL2 Warning [Subsume] in ( DEFTHM APP-COMMUTES ...):  A newly proposed
 :REWRITE rule generated from APP-COMMUTES probably subsumes the previously
 added :REWRITE rule APP-CONS, in the sense that the new rule will now
 probably be applied whenever the old rule would have been.

 ; raw format
 (:WARNING \"Subsume\"
           ((:CTX (DEFTHM . APP-COMMUTES))
            (:NEW-RULE APP-COMMUTES)
            (:RULE-CLASS-NEW :REWRITE)
            (:RULE-CLASS-OLD :REWRITE)
            (:SUBSUMED-RULES (APP-CONS))))
 })

 <p>As illustrated above, it is typical that in the raw format, the @(':CTX')
 entry is first in the alist while the others are ordered alphabetically by
 key (e.g., @(':NEW-RULE') precedes @(':RULE-CLASS-NEW') alphabetically).</p>

 <p>To obtain the current raw-warning-format (@('t') if that format is active,
 @('nil') if not), evaluate @('(@ raw-warning-format)').</p>

 <p>NOTE: Only a few commonly-occurring classes of warnings are shown
 differently in raw-warning-format.</p>")

(defxdoc set-register-invariant-risk
  :parents (programming advanced-features guard debugging invariant-risk)
  :short "Avoid @(see invariant-risk) checking for specified functions"
  :long "<p>See @(see invariant-risk) for an introduction to the notion of
 invariant-risk.  Also see @(see set-check-invariant-risk) for a way to avoid
 invariant-risk checking at runtime.  The present topic discusses a way to
 avoid marking specified functions as potentially having invariant-risk.</p>

 @({
  General Forms:
  (set-register-invariant-risk t)   ; default
  (set-register-invariant-risk nil) ; requires active trust tag
 })

 <p>See community book @('books/demos/register-invariant-risk.lisp') for a
 demonstration of how to use this utility.</p>

 <p>Normally a function is marked by ACL2 as having ``invariant-risk'' if its
 execution may have the potential to corrupt the ACL2 state.  This causes
 execution slowdown that is not necessary if there is actually no such
 potential.  In such cases it may be advisable to instruct ACL2 to avoid
 marking that function as having invariant-risk.  This can be done by including
 the form @('(set-register-invariant-risk nil)') in the book (or its @(see
 portcullis) commands) or @(tsee encapsulate) event that contains the
 definition of that function (or, it can be done in the top-level loop before
 defining that function).  This action requires an active trust tag (see @(see
 defttag)) because you are asserting, without proof, that invariant-risk is
 impossible for that function.  Its effect can be reversed (returning to the
 default behavior) by evaluating @('(set-register-invariant-risk t)'), which
 does not require an active trust tag.</p>

 <p>To see the current setting (i.e., the default of @('t') or else @('nil')
 after evaluation of @('(set-register-invariant-risk nil)')), evaluate
 @('(get-register-invariant-risk state)').</p>

 <p>Note this utility does not affect whether a @(see stobj) primitive is
 marked with invariant-risk (which seems too dangerous in general); it only
 applies to functions introduced by @(tsee defun).  If you want a version of a
 stobj updater that has no invariant-risk and you have invoked
 @('(set-register-invariant-risk nil)'), then define a function that calls the
 stobj updater.</p>

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.
 Moreover, its effect is to set the @(tsee acl2-defaults-table), and hence its
 effect is @(tsee local) to the book or @(tsee encapsulate) form containing it;
 see @(see acl2-defaults-table).</p>")

(defxdoc set-rewrite-stack-limit
  :parents (rewrite-stack-limit)
  :short "Sets the rewrite stack depth used by the rewriter"
  :long "<p>Note: This is an event!  It does not print the usual event summary
 but nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 @({
  Example Forms:
  (set-rewrite-stack-limit 30)                            ; set to small limit
  :set-rewrite-stack-limit 30                             ; same as above
  (set-rewrite-stack-limit *default-rewrite-stack-limit*) ; the default
  (set-rewrite-stack-limit (1- (expt 2 28)))              ; maximum legal limit
  :set-rewrite-stack-limit nil         ; same as above -- essentially, no limit
 })

 <p>This event sets the maximum stack depth for calls of certain functions that
 implement the ACL2 rewriter; see @(see rewrite-stack-limit).  It must be a
 non-negative integer less than 2^28.  A call @('(set-rewrite-stack-limit
 limit)') is equivalent to:</p>

 @({
  (table acl2-defaults-table :rewrite-stack-limit limit).
 })

 <p>The use of @(tsee acl2-defaults-table) ensures that this event's effect is
 implicitly @(tsee local) to the book or @(tsee encapsulate) form in which it
 occurs.</p>

 <p>For a different but somewhat related concept, see @(see
 backchain-limit).</p>")

(defxdoc set-rw-cache-state
  :parents (rewrite)
  :short "Set the default rw-cache-state"
  :long "<p>The ACL2 rewriter uses a data structure, called the
 rw-cache (rewriter cache), to save failed attempts to apply conditional @(see
 rewrite) rules.  The regression suite has taken approximately 11% less time
 with this mechanism.  The rw-cache is active by default but this event allows
 it to be turned off or modified.  Note that this event is @(see local) to its
 context (from @(tsee encapsulate) or @(tsee include-book)).  For a non-local
 version, use @(see set-rw-cache-state!).</p>

 @({
  Example forms:
  (set-rw-cache-state :atom)     ; default: rw-cache cleared for each literal
                                 ;   (i.e., hypothesis or conclusion of a goal)
  (set-rw-cache-state nil)       ; rw-cache is inactive
  (set-rw-cache-state t)         ; rw-cache persists beyond each literal
  (set-rw-cache-state :disabled) ; rw-cache is inactive, but the rw-cache-state
                                 ;   transitions to state t after
                                 ;   simplification takes place

  General Form:
  (set-rw-cache-state val)
 })

 <p>where @('val') evaluates to one of the four values shown in ``Example
 forms'' above.  The default is @(':atom'), which enables the rw-cache but
 clears it before rewriting a hypothesis or conclusion of any goal.  The value
 @('t') is provides more aggressive use of the rw-cache, basically preserving
 the rw-cache when there is a single subgoal.  The value @(':disabled') is the
 same as @('t'), except that the rw-cache is initially inactive and only
 becomes active when some simplification has taken place.  We have seen a few
 cases where value @('t') will make a proof fail but @(':disabled') does
 not.</p>

 <p>The following example illustrates the rw-cache in action.  You will see a
 break during evaluation of the @(tsee thm) form.  Type @(':eval') and you will
 see a failed rewriting attempt.  Type @(':go') to continue, and at the next
 break type @(':eval') again.  This time you will see the same failed rewriting
 attempt, but this time labeled with a notation saying that the failure was
 cached earlier, which indicates that this time the rewriter did not even
 attempt to prove the hypothesis of the @(see rewrite) rule @('f1->f2').</p>

 @({
  (defstub f1 (x) t)
  (defstub f2 (x) t)
  (defaxiom f1->f2
           (implies (f1 x) (equal (f2 x) t)))
  :brr t
  :monitor (:rewrite f1->f2) t
  (thm (equal (car (f2 a)) (cdr (f2 a))))
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.  It is
 @(tsee local) to the book or @(tsee encapsulate) form in which it occurs (see
 @(see set-rw-cache-state!) for a corresponding non-@(tsee local) event).</p>

 <p>We also note that rw-cache-state changes may also be caused at the subgoal
 level; see @(see hints).</p>

 <p>We welcome you to experiment with different rw-cache states.  If the more
 aggressive values of @('t') and @(':disabled') cause proofs to fail, then you
 can revert to the default of @(':atom') or even turn off the rw-cache using
 @('(set-rw-cache-state nil)').  We don't expect users to need a deep knowledge
 of the rw-cache in order to do such experiments, but readers interested in
 details of the rw-cache implementation are invited to read the ``Essay on
 Rw-cache'' in the ACL2 source code.</p>")

(defxdoc set-rw-cache-state!
  :parents (rewrite)
  :short "Set the default rw-cache-state non-@(tsee local)ly"
  :long "<p>Please see @(see set-rw-cache-state), which is the same as
 @('set-rw-cache-state!')  except that the latter is not @(tsee local) to the
 @(tsee encapsulate) or the book in which it occurs.</p>")

(defxdoc set-saved-output
  :parents (set-gag-mode)
  :short "Save proof output for later display with @(':')@(tsee pso) or
  @(':')@(tsee pso!)"
  :long "@({
  Examples:
  (set-saved-output t t)    ; save proof output for later, but inhibit it now
  (set-saved-output t :all) ; save proof output for later, but inhibit all
                            ;   output (except WARNING!, for critical warnings,
                            ;   and ERROR, unless these are already inhibited)
  :set-saved-output t :all  ; same as the line above
  (set-saved-output t nil)  ; save proof output for later, but print it now too
  (set-saved-output nil t)  ; do not save proof output, and inhibit it
  (set-saved-output nil nil); do not save proof output or inhibit output
  (set-saved-output nil :same), (set-saved-output t :same)
                            ; save proof output or not, as indicated, but do
                            ;   not change which output is inhibited
  (set-saved-output nil :normal)
                            ; the behavior when ACL2 first starts up: do not
                            ;   save output, and only inhibit proof-tree output
  (set-saved-output t '(warning observation proof-tree prove))
                            ; save proof output for later, and inhibit the
                            ;   indicated kinds of output

  General Form:
  (set-saved-output save-flg inhibit-flg)
 })

 <p>Parameter @('save-flg') is @('t') to cause output to be saved for later
 display using @('pso') or @('pso!'); see @(see pso) and see @(see pso!), and
 see the documentation for interactive @(see proof-builder) commands of the
 same names.  Set @('save-flg') to @('nil') to turn off this feature; except,
 it always stays on in proof-builder sessions entered with @(tsee verify).  The
 other argument, @('inhibit-flg'), controls whether output should be inhibited
 when it is created (normally, during a proof attempt).  So a common
 combination is to set both arguments to @('t'), to indicate that output should
 be suppressed for now but saved for printing with @(tsee pso) or @(tsee pso!).
 The examples above give a good summary of the functionality for the second
 argument.</p>

 <p>Saved output is cleared at every top-level prover call, including such
 calls made by: @(see events) (e.g., @(tsee defthm) and @(tsee defun)), @(tsee
 thm), and @(see proof-builder) commands that invoke the prover.  A single
 event can make more than one top-level prover call, for example: in the case
 of @(tsee defun), one call made for termination and another for guard
 verification; and in the case of @(tsee defthm), one call made for the
 proposed theorem and one for each @(see corollary).  If you want to see more
 than one proof log for a single top-level form, first evaluate
 @('(set-gag-mode nil)').  Note that interactive @(see proof-builder) commands,
 that is, from a proof-builder session entered with @(tsee verify), are always
 run with output saved.</p>

 <p>Also see @(see set-gag-mode); and see @(see set-print-clause-ids), which
 causes subgoal numbers to be printed during proof attempts when output is
 inhibited.</p>

 <p>See @(see set-inhibit-output-lst) if you want to inhibit certain output
 from the prover but not other output (e.g., not the summary), and you don't
 want to save any output.</p>")

(defxdoc set-serialize-character-system
  :parents (serialize)
  :short "Avoid some special @(see serialize) writing, including for @('.cert')
 files"
  :long "<p>This function can be used to turn off (or on) the @(see
 serialize-write) capability, which is on by default, for writing certain files
 during book certification, including @(see certificate) files.  To use this
 function during a session:</p>

 @({
 ; Disable the use of serialize-write by book certification:
 (set-serialize-character-system nil state)

 ; Re-enable the use of serialize-write by book certification:
 (set-serialize-character-system #\\Z state)
 })

 <p>To use this capability when certifying community-books, you can use a
 suitable @(see acl2-customization) file, for example:</p>

 @({
 cd books ; \\
 make basic \\
 ACL2_CUSTOMIZATION=`pwd`/../acl2-customization-files/no-serialize.lisp
 })

 <p>Alternatively, you can put the following form directly into the book:</p>

 @({
 (make-event
  (pprogn (set-serialize-character-system nil state)
          (value '(value-triple nil))))
 })

 <p>To control the use of @(see serialize) for writes controlled by the user
 rather than by the system, see @(see with-serialize-character).</p>")

(defxdoc set-skip-meta-termp-checks
  :parents (meta clause-processor)
  :short "Skip output checks for @(see meta) functions and @(see
 clause-processor)s"
  :long "<p>WARNING: Use of this macro may render ACL2 unsound, which is why it
 requires a trust tag.  If you obtained an error during application of a @(see
 meta)function, a hypothesis metafunction, or a @(see clause-processor), it might
 well be best to rewrite that function to avoid generating terms with
 the ``forbidden'' function calls described in that error message.  However,
 judicious use of this macro can be useful during development; the rest of this
 topic describes its usage.</p>

 <p>The result of applying a @(see meta)function (or a hypothesis metafunction)
 must be a term.  Similarly, the result of applying a @(see clause-processor)
 must be a list of clauses, where a clause is a list of terms.  If these
 conditions fail, then an error occurs; see @(see term-table) for how one
 obtains some assistance towards avoiding such errors.</p>

 <p>By default, ACL2 actually enforces a stronger requirement: the resulting
 term or clause-list cannot contain any calls of ``forbidden'' function
 symbols: ones that would be illegal when submitting a theorem.  These include
 function symbols that are <i>untouchable</i> (see @(see remove-untouchable))
 as well as those that are keys of the alist @('*ttag-fns-and-macros*').</p>

 <p>These two checks &mdash; that the results are terms and that they contain
 no calls of forbidden function symbols &mdash; can be expensive for large
 terms.  The macro @('set-skip-meta-termp-checks') provides a way to avoid both
 checks.  Since these checks can be critical for soundness, a trust tag (see
 @(see defttag)) must be active in order to invoke this macro unless the
 argument is @('nil').  It might be best to avoid using this macro except to
 skip such checks that you have identified to be expensive, and to skip them
 only when using ACL2 interactively (as opposed to doing batch certification
 jobs) &mdash; though this macro might also be useful in determining when such
 checks are indeed expensive.</p>

 <p>There are two legal ways to call this macro, as follows.  Note that the
 arguments are not evaluated.</p>

 @({
 ; Skip all such checks:
 (set-skip-meta-termp-checks t)

 ; Skip such checks for functions fn1, ..., fnk (each of which is presumably a
 ; metafunction, hypothesis metafunction, or clause-processor):
 (set-skip-meta-termp-checks (fn1 ... fnk))

 })

 <p>A special case of the second form above is to perform all such checks:
 @('(set-skip-meta-termp-checks nil)').  No trust tag is required in this
 case.</p>

 <p>This macro actually generates a @(see local) @(see table) event, for the
 table @('skip-meta-termp-checks-table') and its unique key, @('t').  The
 macro @(tsee set-skip-meta-termp-checks) generates a corresponding
 non-@(see local) @(see table) event.</p>

 @({
 ACL2 !>:trans1 (set-skip-meta-termp-checks (f g))
  (LOCAL (SET-SKIP-META-TERMP-CHECKS! (F G)))
 ACL2 !>:trans1 (set-skip-meta-termp-checks! (f g))
  (TABLE SKIP-META-TERMP-CHECKS-TABLE T '(F G))
 ACL2 !>
 })

 <p>It is probably good practice to use @('set-skip-meta-termp-checks') rather
 than @('set-skip-meta-termp-checks!'), except when there is a compelling
 reason to do otherwise.</p>")

(defxdoc set-skip-meta-termp-checks!
  :parents (meta clause-processor)
  :short "Skip output checks non-@(see local)ly for @(see meta) functions and
 @(see clause-processor)s"
  :long "<p>See @(see set-skip-meta-termp-checks).</p>")

(defxdoc set-splitter-output
  :parents (splitter)
  :short "Turn on or off reporting of rules that may have caused case splits"
  :long "@({
  Examples:
  (set-splitter-output t)   ; enable  reports of ``splitter'' rules (default)
  (set-splitter-output nil) ; disable reports of ``splitter'' rules
 })

 <p>After evaluation of the form @('(set-splitter-output t)') (the default),
 then whenever @('prove') output is not inhibited (see @(see
 set-inhibit-output-lst)), ACL2 will report @(see rewrite) and @(see
 definition) rules that may have reduced a goal to more than one subgoal.  See
 @(see splitter) for how to interpret such reports.  We call such rules
 ``splitter rules'' for the goal that is being split.  This information can be
 useful in deciding how to eliminate large splits, for example of Goal into
 Subgoal 1000 through Subgoal 1, by disabling some splitter rules.  If you want
 to avoid the printing of such information, you can put the form
 @('(set-splitter-output t)') in your customization file; see @(see
 acl2-customization).</p>

 <p>Note that this command does not change the ACL2 @(see world); it only
 modifies the @(see state).  More precisely, it sets a state global to the
 indicated value.  (See @(see state) for discussion of the ``global-table'' of
 the state.)  When @('prove') output is enabled (see @(see
 set-inhibit-output-lst)), the value of that state global is the value of the
 form @('(')@(tsee splitter-output)@(')'); otherwise the value of that form is
 @('nil').</p>

 <p>Again, see @(see splitter) for the effects of turning on the reporting of
 splitter rules.</p>")

(defxdoc set-state-ok
  :parents (state)
  :short "Allow the use of STATE as a formal parameter"
  :long "<p>Note: This is an event!  It does not print the usual event summary
 but nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 <p>In brief: The variable symbol @(tsee STATE) has an unusual status in ACL2.
 In order to use it, you either need to issue @(':set-state-ok t'), as we
 explain below, or you need to declare it to be a @(see stobj), as explained
 elsewhere (see @(see declare-stobjs)).  Now we explain in more detail.</p>

 <p>Because the variable symbol @(tsee STATE) denotes the ``current ACL2
 state,'' ACL2 treats the symbol very restrictively when it occurs as a formal
 parameter of a defined function.  The novice user, who is unlikely to be aware
 of the special status of that symbol, is likely to be confused when error
 messages about @('STATE') are printed in response to the innocent choice of
 that symbol as a formal variable.  Therefore the top-level ACL2 loop can
 operate in a mode in which @(tsee STATE) is simply disallowed as a formal
 parameter.</p>

 <p>For a discussion of @('STATE'), See @(see state) and see @(see stobj).
 Roughly speaking, at the top-level, the ``current ACL2 state'' is denoted by
 the variable symbol @('STATE').  Only the current state may be passed into a
 function expecting a state as an argument.  Furthermore, the name of the
 formal parameter into which the current state is passed must be @('STATE') and
 nothing but the current state may be passed into a formal of that name.
 Therefore, only certain access and change functions can use that formal
 &mdash; namely those with a @('STATE') formal &mdash; and if any such function
 produces a new state it becomes the ``current state'' and must be passed along
 in the @('STATE') position thereafter.  Thus, ACL2 requires that the state be
 single-threaded.  This, in turn, allows us to represent only one state at a
 time and to produce new states from it destructively in a von Neumannesque
 fashion.  The syntactic restrictions on the variable @('STATE') are enforced
 by the translate mechanism (see @(see trans) and see @(see term)) when terms
 are read.</p>

 <p>To prevent the novice user from seeing messages prohibiting certain uses of
 the variable symbol @('STATE') ACL2 has a mode in which it simply disallows
 the use of that symbol as a formal parameter.  Use of the symbol causes a
 simple error message.  The system is initially in that mode.</p>

 <p>To get out of that mode, execute:</p>

 @({
  :set-state-ok t ;;; or, (set-state-ok t)
 })

 <p>It is not recommended that you do this until you have read the
 documentation of @(tsee STATE).</p>

 <p>To enter the mode in which use of @('state') is prohibited as a formal
 parameter, do:</p>

 @({
  :set-state-ok nil
 })

 <p>The mode is stored in the defaults table, See @(see acl2-defaults-table).
 Thus, the mode may be set @(tsee local)ly in books.</p>")

(defxdoc set-tau-auto-mode
  :parents (tau-system)
  :short "Turn on or off automatic (``greedy'') generation of @(':tau-system')
  rules"
  :long "@({
  Examples:
  (set-tau-auto-mode t)      ; select automatic (``greedy'') mode
  (set-tau-auto-mode nil)    ; select manual mode
 })

 <p>This event is equivalent to @('(table acl2-defaults-table :tau-auto-modep
 <t-or-nil>)'), and hence is @(tsee local) to any @(see books) and @(tsee
 encapsulate) @(see events) in which it occurs; see @(see acl2-defaults-table).
 See @(see introduction-to-the-tau-system) for background details.</p>

 <p>The tau system gathers rules for its database in one of two ways: greedily
 or only at the explicit command of the user.  ``Greedy'' mode is officially
 called ``automatic mode'' and is the default.  The other mode is called
 ``manual mode.''</p>

 <p>In automatic mode, all rules processed by ACL2 are also considered for
 inclusion in the tau database: if the @(':corollary') of some proved theorem
 happens to fit into one of the forms described in @(':')@(tsee tau-system),
 that rule is quietly added to the tau database <i>regardless of what</i>
 @(':')@(tsee rule-classes) the user named for the @(':corollary').  Of course,
 such rules are also stored in the ways named by the user.  See the <i>Design
 Philosophy</i> section of @(see introduction-to-the-tau-system) for a
 discussion of why the tau system is greedy by default.  More details are given
 on automatic mode after we explain manual mode.</p>

 <p>To more tightly control the rules available to the tau system, the user may
 select manual mode by executing @('(set-tau-auto-mode nil)').  In manual mode,
 the only events that create @(':tau-system') rules are @('defthm') events
 explicitly specifying the @(':')@(tsee tau-system) rule class in the
 @(':')@(tsee rule-classes) argument.  Of course, for a @(':tau-system') rule
 to be created from a proved formula (or its specified @(':corollary')), the
 formula must be of the appropriate shape (syntactic form). See @(see
 tau-system).  In manual mode, if the @(':tau-system') rule class is specified
 but the formula is not of an appropriate form an error is signaled.  (Note:
 even in manual mode, monadic functions that are recognized as Boolean are
 classified as tau predicates; but no rules are created for them.)</p>

 <p>Returning to our discussion of automatic mode, a @(':')@(tsee tau-system)
 rule may be created by any of the events below, provided the definition or
 formula proved is of an appropriate shape:</p>

 <p>(1) @('defun') events introducing ``big switch'' or ``@('mv-nth')
 synonyms,''</p>

 <p>(2) @('defun') events creating type-prescription rules that may be also
 represented as ``signature rules'' of form 1, and</p>

 <p>(3) any @('defthm') event with a non-@('nil') @(':rule-classes') argument
   if no @(':tau-system') rule is among the rule classes and the formula proved
   is in the shape of any @('tau-system') rule.</p>

 <p>Of course, events such as @(tsee defstobj) and @(tsee defevaluator) may
 also add rules to the tau database when they execute the @(tsee defun) and
 @(tsee defthm) events implicit in their descriptions.  See @(see tau-system)
 for a description of the various shapes mentioned above.</p>

 <p>Note that any rule (of any rule class) created when the tau system is in
 manual mode is also created in automatic mode.  For example, if an event would
 create a @(':DEFINITION'), @(':TYPE-PRESCRIPTION'), @('FORWARD-CHAINING'), or
 @(':REWRITE') rule when the tau system is in manual mode, then the event will
 create that same rule when the tau system is in automatic mode.  Automatic
 mode just means that some additional @(':tau-system') rules may be
 created.</p>

 <p>Of course, if a @('defthm') event explicitly specifies a @(':tau-system')
 rule class, then even if the tau system is in automatic mode, that tau rule is
 created from the proved formula (or the specified @(':corollary')) or else an
 error is caused.  But if the tau system is in automatic mode and a @('defthm')
 event doesn't explicitly specify a @(':tau-system') rule class, then the
 system quietly checks each specified @(':corollary') &mdash; or, in the
 absence of any @(':corollary'), it checks the proved formula &mdash; for
 whether it can be stored as a tau rule.  If so, then the system stores a tau
 rule, in addition to storing the specified rule.  Of course, no error is
 signaled if a proved formula of some non-@(':tau-system') rule class fails to
 be of an appropriate shape for the tau system.</p>

 <p>In automatic mode, if the @(':rule-classes') specified for @('defthm')
 included several corollaries and any one of them is of class @(':tau-system')
 then the only tau system rules created are those explicitly classed as
 @(':tau-system') rules.  For example, suppose a @('defthm') has one
 @(':corollary') stored as a @(':rewrite') rule and another @(':corollary')
 stored as a @(':tau-system') rule.  But suppose the @(':rewrite') rule happens
 to also to fit the form of a @(':tau-system') rule.  Is it added to the tau
 database or not?  The answer is no.  If you have taken the trouble to specify
 @(':tau-system') corollaries for an event, then those corollaries are the only
 ones stored as tau system rules from that event.  Note that had both
 corollaries been classed as @(':rewrite') rules (and been of acceptable
 @(':tau-system') form) both would have also been made @(':tau-system') rules.
 This also allows you be in automatic mode and state a @(':rewrite') or other
 non-@(':tau-system') rule and prevent it from being also made a tau system
 rule: just add a frivolous @(':tau-system') @(':corollary') like @('(booleanp
 (integerp x))').</p>

 <p>Recall that the use of tau rules is controlled by the rune
 @('(:EXECUTABLE-COUNTERPART TAU-SYSTEM)').  When that rune is disabled, no tau
 rules are <i>used</i> in proofs.  However, the tau system continues to collect
 tau rules if the system is in automatic mode.  Thus, if and when the tau
 system is re-enabled, rules automatically generated while the tau system was
 disabled will be used as usual by the tau system.</p>

 <p>Finally, note that @('defthm') events with @(':rule-classes') @('nil') do
 not create @(':tau-system') rules even if the formula proved is of an
 appropriate shape, regardless of whether the tau system is in automatic or
 manual mode.</p>

 <p>The macro @(tsee tau-status) provides a convenient way to enable/disable
 the @(':')@(tsee executable-counterpart) of @('tau-system') and/or to switch
 between manual and automatic modes.  It may also be used to determine the
 current settings of those two flags.</p>")

(defxdoc set-total-parallelism-work-limit
  :parents (parallelism)
  :short "For ACL2(p): set thread limit for parallelism primitives"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).  While the most common use of the limit described below is in
 parallel proof (see @(see parallel-proof)), it also applies to all parallelism
 primitives (see @(see parallel-programming)) except @(tsee spec-mv-let)
 &mdash; though we expect that rather few programming applications will
 encounter this limit.</p>

 @({
  General Forms:
  (set-total-parallelism-work-limit :none)     ; disable the limit
  (set-total-parallelism-work-limit <integer>) ; set limit to <integer>
 })

 <p>See @(see parallelism-tutorial), Section ``Another Granularity Issue
 Related to Thread Limitations'', for an explanation of how the host Lisp can
 run out of threads.  Also see @(see
 set-total-parallelism-work-limit-error).</p>

 <p>If the underlying runtime system (the Operating System, the host Lisp,
 etc.)  is unable to provide enough threads to finish executing the parallelism
 work given to it, the runtime system can crash in a very unpleasant manner
 (ranging from a Lisp error to completely freezing the machine).  To avoid this
 unpleasantness, ACL2(p) will attempt to avoid creating so much parallelism
 that the runtime system crashes.</p>

 <p>ACL2 initially uses a conservative estimate to limit the number of threads.
 To tell ACL2(p) to use a different limit, call
 @('set-total-parallelism-work-limit') with the new limit.  For example, if the
 current default limit is 10,000, then to allow 13,000 threads to exist, issue
 the following form at the top level.</p>

 @({
  (set-total-parallelism-work-limit 13000)
 })

 <p>To disable this limit altogether, evaluate the following form:</p>

 @({
  (set-total-parallelism-work-limit :none)
 })

 <p>The default value of total-parallelism-work-limit can be found by calling
 function @('default-total-parallelism-work-limit').  If the default value is
 too high for your system please notify the ACL2 maintainers with a limit that
 does work for your system, as they might then lower the default limit.</p>")

(defxdoc set-total-parallelism-work-limit-error
  :parents (parallelism)
  :short "For ACL2(p): control the action taken when the thread limit is exceeded"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 @({
  General Forms:
  (set-total-parallelism-work-limit-error t)   ; cause error (default)
  (set-total-parallelism-work-limit-error nil) ; disable error and
                                               ; continue serially
 })

 <p>See @(see parallelism-tutorial), Section ``Another Granularity Issue
 Related to Thread Limitations'', for an explanation of how the host Lisp can
 run out of threads.  See @(see set-total-parallelism-work-limit) for further
 details, including an explanation of how to manage the limit that triggers
 this error.</p>

 <p>The value of state global @('total-parallelism-work-limit-error') dictates
 what occurs when the underlying runtime system runs reaches a limit on the
 number of threads for parallel computation.  By default, when this limit is
 reached, the ACL2(p) user will receive an error and computation will halt.  At
 this point, the ACL2(p) user has the following options.</p>

 <p>(1) Remove the limit by evaluating the following form.</p>

 @({
  (set-total-parallelism-work-limit :none)
 })

 <p>(2) Disable the error so that execution continues serially once the
 available thread resources have been exhausted.</p>

 @({
  (set-total-parallelism-work-limit-error nil)
 })

 <p>(3) Increase the limit on number of threads that ACL2(p) is willing to
 create, in spite of potential risk (see @(see
 set-total-parallelism-work-limit)).  In this case, the following query returns
 the current limit.</p>

 @({
  (f-get-global 'total-parallelism-work-limit)
 })

 <p>Then to increase that limit, evaluate the following form:</p>

 @({
  (set-total-parallelism-work-limit <new-integer-value>)
 })

 <p>For example, suppose that the value of @('total-parallelism-work-limit')
 was originally 10,000.  Then evaluation of the following form increases that
 limit to 13,000.</p>

 @({
  (set-total-parallelism-work-limit 13000)
 })")

(defxdoc set-trace-evisc-tuple
  :parents (trace)
  :short "Set the trace evisc tuple"
  :long "<p>A trace evisc-tuple, which is set by this utility, provides a means
 to restrict printing during tracing.  See @(see evisc-tuple) for an
 introduction to evisc-tuples; also see @(see set-evisc-tuple) and see @(see
 set-iprint).</p>

 <p>By default the ACL2 @(see trace) mechanism, @(tsee trace$), automatically
 deals with stobjs, the logical world, and certain other large structures.  See
 @(see trace$), in particular the documentation of @('trace$') option
 @(':hide').  However, even with that default behavior you may want to restrict
 what is printed according to the print-level and print-length of an
 evisc-tuple; see @(see evisc-tuple).</p>

 <code>
 Examples:

 ; Set trace evisc tuple to a standard value, using current Lisp *print-level*
 ; and *print-length* variables:
 (set-trace-evisc-tuple t state)

 ; Set trace evisc tuple back to its default:
 (set-trace-evisc-tuple nil state)

 ; Set trace evisc tuple to restrict print-level to 3 and print-length to 4,
 ; while hiding the logical world and suitably printing stobjs even if trace$
 ; option ``:hide nil'' is used.  (Note: calling @('trace-evisceration-alist')
 ; directly requires removing this function as `untouchable', which requires a
 ; trust tag; see @(see remove-untouchable).)
 (set-trace-evisc-tuple
  (evisc-tuple 3 4 (trace-evisceration-alist state) nil)
  state)

 General Forms:

 (set-trace-evisc-tuple nil state) ; trace evisc-tuple set to standard value
 (set-trace-evisc-tuple   t state) ; trace evisc-tuple set to hide the logical
                                   ;   world and deal with stobjs even when
                                   ;   trace$ option ``:hide nil'' is supplied
 (set-trace-evisc-tuple evisc-tuple state)
                                   ; tracing set to use indicated evisc-tuple
 </code>

 <p>See @(see trace$) for a discussion of ACL2 tracing.  The @(see evisc-tuple)
 used by that trace utility is the one last installed by
 @('set-trace-evisc-tuple') (or by @(tsee set-evisc-tuple) for the
 trace-evisc-tuple) &mdash; initially to the default of @('nil') &mdash; unless
 overridden by trace option @(':evisc-tuple').</p>

 <p><b>Remark</b>.  If you use value @('t'), then ACL2 will ensure that the
 logical world and stobjs are kept up-to-date in the trace evisc-tuple.</p>")

(defxdoc set-verify-guards-eagerness
  :parents (guard)
  :short "The eagerness with which @(see guard) verification is tried."
  :long "@({
  Example Forms:                        try guard verification?
  (set-verify-guards-eagerness 0) ; no, unless :verify-guards t
  (set-verify-guards-eagerness 1) ; yes if a guard or type is supplied
  (set-verify-guards-eagerness 2) ; yes, unless :verify-guards nil
 })

 <p>Note: This is an event!  It does not print the usual event summary but
 nevertheless changes the ACL2 logical @(see world) and is so recorded.</p>

 @({
  General Form:
  (set-verify-guards-eagerness n)
 })

 <p>where @('n') is a variable-free term that evaluates to @('0'), @('1'), or
 @('2').  This macro is essentially equivalent to</p>

 @({
  (table acl2-defaults-table :verify-guards-eagerness n)
 })

 <p>and hence is @(tsee local) to any @(see books) and @(tsee encapsulate)
 @(see events) in which it occurs; see @(see acl2-defaults-table).  However,
 unlike the above simple call of the @(tsee table) event function (see @(see
 table)), no output results from a @('set-verify-guards-eagerness') event.</p>

 <p>@('Set-verify-guards-eagerness') may be thought of as an event that merely
 sets a flag to @('0'), @('1'), or @('2').  The flag is used by certain @(tsee
 defun) @(see events) to determine whether @(see guard) verification is tried.
 The flag is irrelevant to those @(tsee defun) @(see events) in @(':')@(tsee
 program) mode and to those @(tsee defun) @(see events) in which an explicit
 @(':')@(tsee verify-guards) setting is provided among the @(tsee xargs).  In
 the former case, @(see guard) verification is not done because it can only be
 done when logical functions are being defined.  In the latter case, the
 explicit @(':')@(tsee verify-guards) setting determines whether @(see guard)
 verification is tried.  So consider a @(':')@(tsee logic) mode @(tsee defun)
 in which no @(':')@(tsee verify-guards) setting is provided.  Is @(see guard)
 verification tried?  The answer depends on the eagerness setting as follows.
 If the eagerness is @('0'), @(see guard) verification is not tried.  If the
 eagerness is @('1'), it is tried if and only if a guard is explicitly
 specified in the @(tsee defun), in the following sense: there is an @('xargs')
 keyword @(':guard') or @(':stobjs') or a @(tsee type) declaration.  If the
 eagerness is @('2'), @(see guard) verification is tried.</p>

 <p>The above remarks apply to @(tsee verify-termination) @(see events),
 according to whether guards are explicitly specified in the existing,
 corresponding @(':')@(tsee program) mode definitions.</p>

 <p>The default behavior of the system is as though the
 @(':verify-guards-eagerness') is @('1').  The current behavior can be
 ascertained by evaluating the form @('(default-verify-guards-eagerness (w
 state))').</p>")

(defxdoc set-waterfall-parallelism
  :parents (parallelism)
  :short "For ACL2(p): configuring the parallel execution of the waterfall"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 @({
  General Forms:
  (set-waterfall-parallelism nil)        ; never parallelize (serial execution)
  (set-waterfall-parallelism :full)      ; always parallelize
  (set-waterfall-parallelism :top-level) ; parallelize top-level subgoals
  (set-waterfall-parallelism             ; parallelize if sufficient resources
    :resource-based)                     ;   (recommended setting)
  (set-waterfall-parallelism t)          ; alias for :resource-based
  (set-waterfall-parallelism             ; parallelize if sufficient resources
    :resource-and-timing-based           ;   and suggested by prior attempts
  (set-waterfall-parallelism             ; never parallelize but use parallel
    :pseudo-parallel)                    ;   code base (a debug mode)
 })

 <p>@('Set-waterfall-parallelism') evaluates its argument, which specifies the
 enabling or disabling of the @(see parallel) execution of ACL2's main proof
 process, the waterfall.</p>

 <p>It also sets @(see state) global @('waterfall-printing') to an appropriate
 value.  See @(see set-waterfall-printing).</p>

 <p>Note that not all ACL2 features are supported when waterfall-parallelism is
 set to non-@('nil') (see @(see
 unsupported-waterfall-parallelism-features)).</p>

 <p>A value of @('t') is treated the same as a value of @(':resource-based')
 and is provided for user convenience.</p>

 <p>@(':Resource-based') waterfall parallelism typically achieves the best
 performance in ACL2(p), while maintaining system stability, so
 @(':resource-based') (or equivalently, @('t')) is the recommended value.</p>

 <p>A value of @('nil') indicates that ACL2(p) should never prove subgoals in
 parallel.</p>

 <p>A value of @(':full') indicates that ACL2(p) should always prove
 independent subgoals in parallel.</p>

 <p>A value of @(':top-level') indicates that ACL2(p) should prove each of the
 top-level subgoals in parallel but otherwise prove subgoals in a serial
 manner.  This mode is useful when the user knows that there are enough
 top-level subgoals, many of which take a non-trivial amount of time to be
 proved, such that proving them in parallel will result in a useful reduction
 in overall proof time.</p>

 <p>A value of @(':resource-based') (or equivalently, @('t')) indicates that
 ACL2(p) should use its built-in heuristics to determine whether CPU core
 resources are available for parallel execution.  Note that ACL2(p) does not
 hook into the operating system to determine the workload on the machine.
 ACL2(p) works off the assumption that it is the only process using significant
 CPU resources, and it optimizes the amount of parallelism based on the number
 of CPU cores in the system.  (Note that ACL2(p) knows how to obtain the number
 of CPU cores from the operating system in CCL, but that, in SBCL and in
 Lispworks, a constant is used instead).</p>

 <p>During the first proof attempt of a given conjecture, a value of
 @(':resource-and-timing-based') results in the same behavior as with
 @(':resource-based').  However, on subsequent proof attempts, the time it took
 to prove each subgoal will be considered when deciding whether to parallelize
 execution.  If a particular theorem's proof is already achieving satisfactory
 speedup via @(':resource-based') parallelism, there is no reason to try this
 setting.  However, if the user wishes to experiment, the
 @(':resource-and-timing-based') setting may improve performance.  Note that
 since the initial run does not have the subgoal proof times available, this
 mode will never be better than the @(':resource-based') setting for
 non-interactive theorem proving.</p>

 <p>A value of @(':pseudo-parallel') results in using the parallel waterfall
 code, but with serial execution.  This setting is useful for debugging the
 code base that supports parallel execution of the waterfall.  For example, you
 may wish to use this mode if you are an ``ACL2 Hacker'' who would like to see
 comprehensible output from tracing (see @(see trace$)) the @('@par') versions
 of the waterfall functions.</p>

 <p>Since @(see memoization) is not supported when waterfall parallelism is
 enabled (see @(see unsupported-waterfall-parallelism-features)), then when
 @('set-waterfall-parallelism') is called with a non-@('nil') value, all
 memoized functions are unmemoized.  When @('set-waterfall-parallelism') is
 again called with a @('nil') value, those memoization settings are
 restored.</p>

 <p>@('Set-waterfall-parallelism') is an embedded event form.  However, a call
 of this macro will not affect waterfall-parallelism when including a certified
 book that contains that call.  For such an effect, you may use the following
 @(tsee make-event) form; also see @(see non-parallel-book).</p>

 @({
  (make-event (er-progn (set-waterfall-parallelism :full)
                        (value '(value-triple nil)))
              :check-expansion t)
 })

 <p>To enable waterfall parallelism for book certification using ACL2(p), see
 @(see waterfall-parallelism-for-book-certification).</p>")

(defxdoc set-waterfall-parallelism-hacks-enabled
  :parents (parallelism)
  :short "For ACL2(p): enable waterfall-parallelism hacks"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 @({
  General Forms:
  (set-waterfall-parallelism-hacks-enabled t)
  (set-waterfall-parallelism-hacks-enabled nil)
 })

 <p>Some features (e.g., @(see override-hints) and @(see clause-processor)s) of
 serial ACL2 are by default not available in ACL2(p) with waterfall parallelism
 enabled, because they offer a mechanism to modify @(see state) that is
 unsound.  To allow or (once again) disallow the use the these features in
 ACL2(p), call @('set-waterfall-parallelism-hacks-enabled') with argument
 @('t') or @('nil'), respectively.</p>

 <p>@('Set-waterfall-parallelism-hacks-enabled') requires the use of a trust
 tag (see @(see defttag)).  One can call @(tsee
 set-waterfall-parallelism-hacks-enabled!)  instead, which will automatically
 install a trust tag named @(':waterfall-parallelism-hacks').</p>

 <p>See @(see error-triples-and-parallelism) for further related
 discussion.</p>")

(defxdoc set-waterfall-parallelism-hacks-enabled!
  :parents (parallelism)
  :short "For ACL2(p): enabling waterfall parallelism hacks"
  :long "<p>See @(see set-waterfall-parallelism-hacks-enabled).</p>")

(defxdoc set-waterfall-printing
  :parents (parallelism)
  :short "For ACL2(p): configuring the printing that occurs within the parallelized waterfall"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 @({
  General Forms:
  (set-waterfall-printing :full)    ; print everything
  (set-waterfall-printing :limited) ; print a subset that's thought to be useful
  (set-waterfall-printing :very-limited) ; print an even smaller subset
 })

 <p>@('Set-waterfall-printing') evaluates its argument, which indicates how
 much printing should occur when executing ACL2 with the parallelized version
 of the waterfall.  It only affects the printing that occurs when parallelism
 mode is enabled for the waterfall (see @(see set-waterfall-parallelism)).</p>

 <p>A value of @(':full') is intended to print the same output as in serial
 mode.  This output will be interleaved unless the waterfall-parallelism mode
 is one of @('nil') or @(':pseudo-parallel').</p>

 <p>A value of @(':limited') omits most of the output that occurs in the serial
 version of the waterfall.  Instead, the proof attempt prints key checkpoints
 (see @(see acl2p-key-checkpoints)).  The value of @(':limited') also prints
 messages that indicate which subgoal is currently being proved, along with the
 wall-clock time elapsed since the theorem began its proof; and if state global
 @(''waterfall-printing-when-finished') has a non-@('nil') value, then such a
 message will also be printed at the completion of each subgoal.  The function
 @('print-clause-id-okp') may receive an attachment to limit such printing; see
 @(see set-print-clause-ids).  Naturally, these subgoal numbers can appear out
 of order, because the subgoals can be proved in parallel.</p>

 <p>A value of @(':very-limited') is treated the same as @(':limited'), except
 that instead of printing subgoal numbers, the proof attempt prints a period
 (`@('.')') each time it starts a new subgoal.</p>

 <p>Note that this form cannot be used at the top level of a book, or of a
 @(tsee progn) or @(tsee encapsulate) event.  Here is a workaround for use in
 such contexts; of course, you may replace @(':very-limited') with any other
 legal argument for @('set-waterfall-printing').</p>

 @({
  (make-event (er-progn (set-waterfall-printing :very-limited)
                        (value '(value-triple nil))))
 })

 <p>(For more about event contexts and the use of @('make-event'), see @(see
 make-event), in particular the section ``Restriction to Event Contexts.'')</p>

 <p>The following form has the effect described above, except that it will
 affect waterfall-printing even when including a certified book that contains
 it.</p>

 @({
  (make-event (er-progn (set-waterfall-printing :very-limited)
                        (value '(value-triple nil)))
              :check-expansion t)
 })

 <p>Note that @('set-waterfall-printing') is automatically called by @(tsee
 set-waterfall-parallelism).</p>

 <p>To enable the printing of information when a subgoal is finished, assign a
 non-@('nil') value to global @('waterfall-printing-when-finished').  This can
 be accomplished by entering the following at the top level:</p>

 @({
  (f-put-global 'waterfall-printing-when-finished t state)
 })")

(defxdoc set-well-founded-relation
  :parents (defun)
  :short "Set the default well-founded relation"
  :long "@({
  Examples:
  (set-well-founded-relation lex2)
 })

 <p>provided @('lex2') has been proved to be a well-founded relation (see @(see
 well-founded-relation-rule)).  Note: This is an event!  It does not print the
 usual event summary but nevertheless changes the ACL2 logical @(see world) and
 is so recorded.</p>

 @({
  General Form:
  (set-well-founded-relation rel)
 })

 <p>where @('rel') has been proved to be a well-founded relation on objects
 satisfying some predicate, @('mp'); see @(see well-founded-relation-rule).
 This macro is equivalent to @('(table acl2-defaults-table
 :well-founded-relation 'rel)'), and hence is @(tsee local) to any @(see books)
 and @(tsee encapsulate) @(see events) in which it occurs; see @(see
 acl2-defaults-table).</p>

 <p>This event sets the default well-founded relation to be that imposed on
 @('mp')-measures by the relation @('rel').  Subsequently, if a recursively
 defined function is submitted to @(tsee defun) with no explicitly given
 @(':well-founded-relation') argument, @(tsee defun) uses the default relation,
 @('rel'), and the associated domain predicate @('mp') used in its
 well-foundedness theorem.  That is, the termination conditions generated will
 require proving that the measure used by the @(tsee defun) is an
 @('mp')-measure and that in every recursive call the measure of the arguments
 decreases according to @('rel').</p>")

(defxdoc set-wormhole-data
  :parents (wormhole)
  :short "Sets the wormhole data object in a wormhole status object"
  :long "@({
  General Form:  (set-wormhole-data whs data)
 })

 <p>See @(see wormhole).  @('Whs') should be a well-formed wormhole status;
 @('data') is arbitrary.  This function returns a new status with the same
 entry code as @('whs') but with the new @('data').  It avoids unnecessary
 consing if the data for @('whs') is already set to @('data').  This function
 does not affect state or a wormhole's hidden status.  It just returns a
 (possibly) new status object suitable as the value of the @('lambda')
 expressions in @(tsee wormhole-eval) and @(tsee wormhole).</p>")

(defxdoc set-wormhole-entry-code
  :parents (wormhole)
  :short "Sets the wormhole entry code in a wormhole status object"
  :long "@({
  General Form:  (set-wormhole-entry-code whs code)
 })

 <p>See @(see wormhole).  @('Whs') should be a well-formed wormhole status and
 @('code') should be @(':ENTER') or @(':SKIP').  This function returns a new
 status with the specified entry code but the same data as @('whs').  It avoids
 unnecessary consing if the entry code for @('whs') is already set to
 @('code').  This function does not affect state or a wormhole's hidden status.
 It just returns a (possibly) new status object suitable as the value of the
 @('lambda') expressions in @(tsee wormhole-eval) and @(tsee wormhole).</p>")

(defxdoc set-write-acl2x
  :parents (books-reference)
  :short "Cause @(tsee certify-book) to write out a @('.acl2x') file"
  :long "@({
  Example Forms:
  (set-write-acl2x nil state)
  (set-write-acl2x t state)
  (set-write-acl2x '(nil) state) ; same as just above, but allow inclusion of
                                 ; uncertified books during certify-book
  (set-write-acl2x '(t) state)
  (set-write-acl2x '(include-book-with-locals) state)
 })

 @({
  General Form:
  (set-write-acl2x val state)
 })

 <p>where @('val') evaluates to @('t'), @('nil'), or a one-element list whose
 element is a legal value for the global @(''ld-skip-proofsp'); see @(see
 ld-skip-proofsp).  The value returned is an error triple, which in the
 non-error case is @('(mv nil v state)'), where @('v') is the value of @('val')
 and @('state') is the result of updating the input @(see state) by assigning
 state global @(''write-acl2x') the value @('v').</p>

 <p>The command @('(set-write-acl2x val state)') assigns the value of @('val')
 to the @(see state) global variable @(''write-acl2x'), affecting whether or
 not @(tsee certify-book) writes out a file with extension @('acl2x'), called a
 ``@('.acl2x') file'' and pronounced ``dot-acl2x file''.  Such a file is read
 or written by @(tsee certify-book) when it is supplied with keyword argument
 @(':acl2x t').  By default, such a call of @('certify-book') reads a
 @('.acl2x') file; but if the value of state global variable @(''write-acl2x')
 is not @('nil'), then @('certify-book') writes a @('.acl2x') file (in which
 case it is illegal to specify a non-@('nil') value for @(tsee certify-book)
 keyword argument @(':pcert')).  Consider for example @('(certify-book \"foo\"
 0 nil :acl2x t)').  By default, this command reads file @('foo.acl2x'), which
 supplies replacements for some forms in @('foo.lisp'), as described later
 below.  But if the value of state global @(''write-acl2x') is not @('nil'),
 then instead, this @('certify-book') command writes such a file
 @('foo.acl2x').</p>

 <p>Before we discuss the function of @('.acl2x') files, we first explain more
 about how a non-@('nil') value of @(see state) global @(''write-acl2x')
 affects the behavior of a command @('(certify-book ... :acl2x t ...)').  A
 significant effect on the behavior is that after processing events in the
 given book, ACL2 writes out a @('.acl2x') file and then returns, skipping the
 other subsequent actions typically performed by @(tsee certify-book): a @(see
 local-incompatibility) check, writing of a @(see certificate) file, and
 possibly @(see compilation).  Another effect is that proofs may be skipped
 when processing @(see events) assuming that the the @('certify-book') command
 does not explicitly specify @(':skip-proofs-okp nil'), as we now explain.  A
 non-@('nil') value of @(''write-acl2x') should either be @('t') or a
 one-element list @('(x)'), where @('x') is a legal value for the @(see state)
 global @(''ld-skip-proofsp') (see @(see ld-skip-proofsp)).  In both cases,
 @('certify-book') will process @(see events) to write out a @('.acl2x') file
 as described above.  But in the latter (list) case, event processing will take
 place according to the value of @('x'): in particular, proofs will be skipped
 when @('x') is not @('nil'), and if moreover @('x') is the symbol
 @('include-book-with-locals'), then only one pass will be made through each
 @(tsee encapsulate) form.  A third effect of a non-@('nil') value of
 @(''write-acl2x'), which is restricted to the list case, is that @(see
 include-book) events encountered during event processing are allowed to
 succeed on uncertified books, something that is prohibited during most calls
 of @(tsee certify-book).</p>

 <p>When @(tsee certify-book) is used to write out a @('.acl2x') file, there is
 typically a subsequent run of @(tsee certify-book) that reads that file.
 Consider how this can work with a book @('foo.lisp').  In the first call of
 @('certify-book'), a file @('foo.acl2x') is written that contains all @(tsee
 make-event) expansions, but @('foo.cert') is not written.  In the second call
 of @('certify-book'), no @(tsee make-event) expansion typically takes place,
 because @('foo.acl2x') supplies the expansions.  The command
 @('(set-write-acl2x t state)') should be evaluated before the first
 certification (though another legal non-@('nil') value may be used in place of
 @('t')), setting the value of @(tsee state) global @(''write-acl2x') to
 @('t'), to enable writing of @('foo.acl2x'); and the command
 @('(set-write-acl2x nil state)') may be evaluated before the second run
 (though this is not necessary in a fresh ACL2 session) in order to complete
 the certification (writing out @('foo.cert')) using @('foo.acl2x') to supply
 the @(tsee make-event) expansions.</p>

 <p>When @(tsee Certify-book) is supplied with keyword argument @(':acl2x t')
 it will read or write the book's @('.acl2x') file; when supplied with
 @(':acl2x nil'), it will not read or write that @('.acl2x') file.  The value
 of @(':acl2x') is @('nil') by default.  The interaction of @(tsee
 certify-book) with the corresponding @('.acl2x') file is as follows.</p>

 <code>
 o If @(':acl2x') is @('t'), then:
   - If @('set-write-acl2x') has been (most recently) called with a value of
     @('t') for its first argument,then ACL2 writes the corresponding
     @('.acl2x') file.
   - If @('set-write-acl2x') has been (most recently) called with a value of
     @('nil') for its first argument, or not called at all, then ACL2 insists
     on a corresponding @('.acl2x') file that is at least as recent as the
     corresponding @('.lisp') file, causing an error otherwise.
  o If @(':acl2x') is @('nil'),then:
   - If @('set-write-acl2x') has been (most recently) called with a value
     @('t') for its first argument, or if argument @(':ttagsx') is supplied,
     then an error occurs.
   - If the @('.acl2x') file exists, then regardless of whether or how
     @('set-write-acl2x') has been called, ACL2 ignores the @('.acl2x') file
     but issues a warning about it.
 </code>

 <p>Suppose you use the two-runs approach: first write a @('.acl2x') file, then
 certify using (reading) that @('.acl2x') file.  Then with scripts such as
 makefiles, then you may wish to provide a single @(tsee certify-book) command
 to use for both runs.  For that purpose, @(tsee certify-book) supports the
 keyword argument @(':ttagsx').  If this argument is supplied and
 @('write-acl2x') is true, then this argument is treated as the @(':ttags')
 argument, overriding a @(':ttags') argument if present.  That is, for the two
 runs, @(':ttagsx') may be used to specify the trust tags used in the first
 certification while @(':ttags') specifies the trust tags, if any (else
 @(':ttags') may be omitted), used in the second certification.  Note: If the
 argument @(':ttagsx') is not supplied, then its value defaults to the
 (explicit or default) value of the @(':ttags') argument.</p>

 <p>The built-in ACL2 Makefile support automatically generates suitable
 dependencies if you create a @('.acl2') file with a @(tsee certify-book) call
 matching the following regular expression, case-independent:</p>

 @({
    (certify-book[^;]*:acl2x t
 })

 <p>For an example @('.acl2') file with a @('certify-book') call matching the
 above pattern, see community books file
 @('books/make-event/double-cert-test-1.acl2').</p>

 <p>Note that @(tsee include-book) is generally not affected by
 @('set-write-acl2x'), other than through the indirect effect on @(tsee
 certify-book).  More precisely: All expansions are stored in the @(see
 certificate) file, so when @(tsee include-book) is applied to a certified
 book, the @('.acl2x') file is not consulted.</p>

 <p>An example of how to put this all together may be found in community book
 @('books/make-event/double-cert-test-1.lisp').  There, we see the following
 form.</p>

 @({
  (make-event
   (progn (defttag :my-ttag)
          (progn! (let ((val (sys-call \"pwd\" nil)))
                    (value (list 'defun 'foo () val))))))
 })

 <p>Imagine that in place of the binding computed using @(tsee sys-call), which
 by the way requires a trust tag, is some computation of your choice (such as
 reading forms from a file) that is used to construct your own event, in place
 of the @(tsee defun) event constructed above.  The @('Makefile') in that
 directory contains the following added dependency, so that file
 @('double-cert-test-1.acl2x') will be created:</p>

 @({
  double-cert-test-1.cert: double-cert-test-1.acl2x
 })

 <p>There is also the file @('double-cert-test-1.acl2') in that directory,
 which contains a single form as follows.</p>

 @({
  (certify-book \"double-cert-test-1\" ? t :ttagsx :all :ttags nil)
 })

 <p>Thus, a call of `make' first creates file @('double-cert-test-1.acl2x'),
 which uses the above @(':ttagsx') argument in order to support the use of
 @(tsee defttag) during @(tsee make-event) expansion.  Then, `make' goes on to
 cause a second certification in which no trust tags are involved.  As a
 result, the parent book @('double-cert-test.lisp') is ultimately certified
 without requiring any trust tags.</p>

 <p>The discussion above is probably sufficient for most users of the two-run
 approach it describes.  We conclude with further details for those who want
 more information.  Those who wish to see a yet lower-level explanation of how
 all this works are invited to read the comment in the ACL2 source code
 entitled ``Essay on .acl2x Files (Double Certification).</p>

 <p>Consider the @('.acl2x') file produced by the first run as described above.
 It contains a single expression, which is an association list whose keys are
 all positive integers, which occur in increasing order.  When the @('.acl2x')
 file is present and at least as recent as the corresponding @('.lisp') file,
 then for a subsequent @(tsee certify-book) with argument @(':acl2x t') and the
 (default) value of @('nil') for @(see state) global @(''write-acl2x'), that
 association list will be applied to the top-level events in the book, as
 follows.  Suppose the entry @('(n . ev)') belongs to the association list in
 the @('.acl2x') file.  Then @('n') is a positive integer, and the @('n')th
 top-level event in the book &mdash; where the @('0')th event is the initial
 @(tsee in-package) form &mdash; will be replaced by @('ev').  In practice,
 @('ev') is the @(tsee make-event) expansion created during certification for
 the @('nth') top-level event in the book; and this will always be the case if
 the @('.acl2x') file is created by @(tsee certify-book) after execution of the
 form @('(set-write-acl2x t state)').  However, you are welcome to associate
 indices manually with any @(see events) you wish into the alist stored in the
 @('.acl2x') file.</p>

 <p>Note: Also see the community book @('make-event/acl2x-help.lisp') for a
 useful utility that can be used to skip proofs during the writing of
 @('.acl2x') files.</p>")

(defxdoc setenv$
  :parents (programming-with-state acl2-built-ins)
  :short "Set an environment variable"
  :long "<p>@('(Setenv$ str val)'), where @('str') and @('val') are strings,
 sets the environment variable @('str') to have value @('val'), for subsequent
 read by @('getenv$') (see @(see getenv$)), and returns @('nil').  Or, if this
 operation is not implemented for the host Common Lisp, an error will
 occur.</p>

 @({
  Example:
  (setenv$ \"FOO\" \"BAR\")
 })

 <p>It may be surprising that @('setenv$') returns @('nil'); indeed, it neither
 takes nor returns the ACL2 @(see state).  The reason is that @(tsee getenv$)
 takes responsibility for trafficking in @(see state); it is defined in the
 logic using the function @(tsee read-acl2-oracle), which (again, in the logic)
 does modify state, by popping an entry from its acl2-oracle field.  @(see
 getenv$).</p>

 <p>As suggested above, a call of @(tsee getenv$) takes into account the most
 recent call of @('setenv$') on the same environment variable.  It may also be
 the case that @('setenv$') modifies the environment of the underlying process;
 for example, we think this is probably the case for most invocations of ACL2
 built on a host Lisp that is CCL, SBCL, or CMUCL, as well as others perhaps.
 If you want to rely on such behavior, however, we advise you to look at source
 code.</p>

 @(def setenv$)")

(defxdoc seventh
  :parents (nth acl2-built-ins)
  :short "Seventh member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc sharp-bang-reader
  :parents (reader packages)
  :short "Package prefix that is not restricted to symbols"
  :long "@({
  Examples:

  ACL2 !>(defpkg \"FOO\" nil)

  Summary
  Form:  ( DEFPKG \"FOO\" ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   \"FOO\"
  ACL2 !>'#!foo(a b)
  (FOO::A FOO::B)
  ACL2 !>'#!foo(a #!acl2 b)
  (FOO::A B)
  ACL2 !>'#!foo(#!acl2 a b)
  (A FOO::B)
  ACL2 !>'#!foo(#!\"ACL2\" a b)
  (A FOO::B)
  ACL2 !>
 })

 <p>The ACL2 reader supports the syntax @('#!pkg-name expr') where
 @('pkg-name') is a string or symbol that names a package known to ACL2.  As
 illustrated above, this syntax nests as one might expect.  In the special case
 that @('expr') is a symbol, @('#!pkg-name expr') is equivalent to
 @('pkg-name::expr').</p>")

(defxdoc sharp-dot-reader
  :parents (reader defconst)
  :short "Read-time evaluation of constants"
  :long "@({
  Example:

  ACL2 !>(defconst *a* '(a b c))

  Summary
  Form:  ( DEFCONST *A* ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   *A*
  ACL2 !>(quote (1 2 #.*a* 3 4))
  (1 2 (A B C) 3 4)
  ACL2 !>
 })

 <p>The ACL2 reader supports the syntax @('#.*a*') where @('*a*') was defined
 by @(tsee defconst).  In this case, the reader treats @('#.*a*') as though it
 were reading the value of @('*a*').  This feature can be useful in conjunction
 with the use of @(tsee evisc-table) to abbreviate large constants, so that the
 abbreviation can be read back in; see @(see evisc-table).</p>

 <p>Remarks.</p>

 <p>(1) The ACL2 reader only supports `@('#.')' as described above, unlike
 Common Lisp.  Older versions (preceding 3.5) used `@('#.')' to abort, but that
 functionality is now carried out by @('(a!)'); see @(see a!).  For a related
 feature that only pops up one level, see @(see p!).</p>

 <p>(2) If you call @(tsee certify-book) on a book that contains a form
 `@('#.*foo*')', the @('*foo*') must already be defined in the @(see world) in
 which you issue the @('certify-book') command.  The reason is that
 @('certify-book') reads the entire book before evaluating its forms.</p>")

(defxdoc sharp-f-reader
  :parents (reader numbers)
  :short "Read a rational number in floating-point (scientific notation)
 syntax"
  :long "@({
 Examples:

 ACL2 !>#f567
 567
 ACL2 !>#f_5_6__7_ ; underscores are allowed, and discarded
 567
 ACL2 !>
 ACL2 !>#f-567
 -567
 ACL2 !>#f+567
 567
 ACL2 !>#f5.67
 567/100
 ACL2 !>#f-5.67
 -567/100
 ACL2 !>#f5.67e3
 5670
 ACL2 !>#f-5.67e3
 -5670
 ACL2 !>#f-5.67e-3
 -567/100000
 ACL2 !>#f.67e2
 67
 ACL2 !>#f-.67e2
 -67
 ACL2 !>#f-.67e+4
 -6700
 ACL2 !>#f-0.67e+4
 -6700
 ACL2 !>#fx101
 257
 ACL2 !>#fx10.1
 257/16
 ACL2 !>#fx10.1p3
 257/2
 ACL2 !>#fx10.1p-4
 257/256
 ACL2 !>#fx-10.1p-4
 -257/256
 ACL2 !>#fx.1p4
 1
 ACL2 !>#fx.1p+8
 16
 ACL2 !>#fx.1p-2
 1/64
 ACL2 !>#fx-0_4p1_0
 -4096
 ACL2 !>
 })

 <p>As illustrated above, we support two forms of this reader: @('#f'),
 indicating base 10 digits, and @('#fx'), indicating base 16 digits.  Let {i}
 be notation representing a sequence of digits and (optionally) underscore
 (@('_')) characters, optionally preceded by a sign (@('-') or @('+')), that
 the ACL2 reader reads as the integer i after discarding underscore characters;
 similarly for {j} and {n}, except that an initial sign is illegal for {j}, and
 for {n} the digits are always base 10 (even in the case of @('#fx')).  Note
 that each such string is terminated at the first character from the input
 channel that is not a digit.  For the @('#f') case we have the following
 semantics.</p>

 @({
 #f{i}          => i
 #f{i}e{n}      => i * 10^n
 #f{i}.{j}      => i + (/ j 10^k) where k is the length of {j}
 #f{i}.{j}e{n}  => (i + (/ j 10^k)) * 10^n where k is the length of {j}
 })

 <p>We have the following similar semantics for the #('#fx') case, except that
 {i} and {j} are now read in base 16.  Note that {n} is still read in base
 10.</p>

 @({
 #fx{i}         => i
 #fx{i}p{n}     => i * 2^n
 #fx{i}.{j}     => i + (/ j 16^k) where k is the length of {j}
 #fx{i}.{j}p{n} => (i + (/ j 16^k)) * 2^n where k is the length of {j}
 })

 <p>We thank Dmitry Nadezhin for pointing us to the following page, which
 explains an analogous ``floating point literal'' syntax for C++:</p>

 @({
 http://en.cppreference.com/w/cpp/language/floating_literal
 })

 <p>Note, however, that in ACL2 we do not support the use of single quote
 (@(''')) as a separator, using underscore (@('_')) instead, which is
 consistent with another reader macro, @('#u') (see @(see sharp-u-reader)).
 Moreover, unlike the syntax described on the page above, the ACL2 @('#f')
 reader allows an initial sign (@('-') or @('+')).  To see why, note that in
 Lisp, the string @('\"-#\"') starts a symbol, for example:</p>

 @({
   ? '-#f23
   |-#F23|
   ?
 })

 <p>Since the ACL2 reader is based on the Lisp reader, it would be awkward to
 provide support to read the string @('\"-#f23\"') as a number, -23.  Instead,
 ACL2 accepts a sign immediately after the initial @('\"#f\"') or
 @('\"#fx\"'):</p>

 @({
 ACL2 !>#f-23
 -23
 ACL2 !>
 })")

(defxdoc sharp-u-reader
  :parents (reader numbers)
  :short "Allow underscore characters in numbers"
  :long "@({
  Example:

  ACL2 !>#ub1000_1000_1000_
  2184
  ACL2 !>#b100010001000
  2184
  ACL2 !>#uo1_1
  9
  ACL2 !>#o11
  9
  ACL2 !>#u34_5
  345
  ACL2 !>#u345
  345
  ACL2 !>345
  345
  ACL2 !>#ux12_a
  298
  ACL2 !>#ux12a
  298
  ACL2 !>#u x12a
  298
  ACL2 !>#x12a
  298
  ACL2 !>#u123_456/7_919
  123456/7919
  ACL2 !>
 })

 <p>The ACL2 reader supports the use of @('#ub'), @('#uo'), and @('#ux') where
 one would otherwise write @('#b'), @('#o'), and @('#x'), respectively (for
 binary, octal, and hexadecimal numerals), but where underscore characters
 (`@('_')') are allowed but ignored.  Also supported is the prefix @('#u') in
 front of a an expression that is a decimal numeral except that underscore
 characters are allowed but ignored.</p>

 <p>The precise specification of @('#u') is as follows.  The ACL2 reader reads
 one expression after the @('#u').  If the result is a number, then that number
 is returned by the reader.  Otherwise the result must be a symbol.  Let @('N')
 be the @(tsee symbol-name) of the symbol; thus @('N') is a string.  If @('N')
 begins with one of the characters `@('B')', `@('O')', or `@('X')', then first
 obtain a string @('S1') by prefixing @('N') with the character, `@('#')';
 otherwise let @('S1') be @('N').  Next, remove all underscore characters
 `@('_')' from @('S1'), obtaining @('S2').  The result is obtained by applying
 the ACL2 reader to @('S2'); that result must be a number, or else an error
 occurs.</p>")

(defxdoc show-bdd
  :parents (bdd)
  :short "Inspect failed BDD proof attempts"
  :long "<p>Attempts to use BDDs (see @(see bdd)), using @(':')@(tsee bdd)
 @(see hints), can fail for various reasons.  Sometimes it is useful to explore
 such failures.  To do so, one may simply execute the form</p>

 @({
  (show-bdd)
 })

 <p>inside the ACL2 loop.  The system's response is generally self-explanatory.
 Perhaps you have already seen @('show-bdd') used in some examples (see @(see
 bdd-introduction) and see @(see if*)).  Here we give some details about
 @('show-bdd').</p>

 <p>@('(Show-bdd)') prints the goal to which the BDD procedure was applied and
 reports the number of nodes created during the @(see BDD) computation,
 followed by additional information depending on whether or not the computation
 ran to completion or aborted (for reasons explained elsewhere; see @(see
 bdd-algorithm)).  If the computation did abort, a backtrace is printed that
 should be useful in understanding where the problem lies.  Otherwise,
 @('(show-bdd)') prints out ``falsifying constraints.''  This list of pairs
 associates @(see term)s with values and suggests how to construct a binding
 list for the variables in the conjecture that will falsify the conjecture.  It
 also prints out the @(see term) that is the result of simplifying the input
 @(see term).  In each of these cases, parts of the object may be hidden during
 printing, in order to avoid creating reams of uninteresting output.  If so,
 the user will be queried about whether he wishes to see the entire object
 (alist or @(see term)), which may be quite large.  The following responses are
 legal:</p>

 <blockquote><p>@(' w') &mdash; Walk around the object with a structure
 editor</p>

 <p>@(' t') &mdash; Print the object in full</p>

 <p>@('nil') &mdash; Do not print any more of the object</p></blockquote>

 <p>@('Show-bdd') actually has four optional arguments, probably rarely used.
 The general form is</p>

 @({
  (show-bdd goal-name goal-ans falsifying-ans term-ans)
 })

 <p>where @('goal-name') is the name of the goal on which the @(':')@(tsee bdd)
 hint was used (or, @('nil') if the system should find such a goal),
 @('goal-ans') is the answer to be used in place of the query for whether to
 print the input goal in full, @('falsifying-ans') is the answer to be used in
 place of the query for whether to print the falsifying constraints in full,
 and @('term-ans') is the answer to be used in place of the query for whether
 to print the resulting @(see term) in full.</p>")

(defxdoc show-bodies
  :parents (definition)
  :short "Show the potential definition bodies"
  :long "@({
  Examples:
  (show-bodies foo)
  :show-bodies foo
 })

 <p>A definition made using @(tsee defun) installs a so-called ``body'' of a
 function symbol, as do certain @(':')@(tsee definition) rules.  Such bodies
 are used in a number of ways, including the application of @(':expand') @(see
 hints); see @(see definition), in particular the discussion of ``body'' there,
 and see @(see hints) for a discussion of the @(':expand') hint.  Also see
 @(see set-body) for how to change which of the available definitions (among
 the original definition and appropriate @(':')@(tsee definition) rules) is the
 one that provides the body.  The @('show-bodies') command displays the
 available such bodies in an appropriate format, starting with the one that is
 currently used as the body.</p>

 @({
  General Forms:
  (show-bodies function-symbol)
  :show-bodies function-symbol
 })")

(defxdoc show-custom-keyword-hint-expansion
  :parents (custom-keyword-hints)
  :short "Print out custom keyword hints when they are expanded"
  :long "@({
    Examples:
    (show-custom-keyword-hint-expansion t)
    (show-custom-keyword-hint-expansion nil)
 })

 @({
    General Form:
    (show-custom-keyword-hint-expansion flg)
 })

 <p>If the value of @('flg') is non-@('nil'), then when custom keyword hints
   are expanded, the system prints the results of each expansion.  This is
   sometimes useful for debugging custom keyword hints and, from time to time,
   may be useful in understanding how a custom hint affects some proof
   attempt.</p>

 <p>The default setting is @('nil').</p>

 <p>For an explanation of how custom keyword hints are processed, see @(see
   custom-keyword-hints).</p>")

(defxdoc show-fc-criteria
  :parents (forward-chaining-reports)
  :short "Print the forward-chaining tracking criteria"
  :long "@({
  Example:  (show-fc-criteria)
 })

 <p>This function prints the list of triples being used to determine what is
 tracked during forward chaining.</p>

 <p>See @(see forward-chaining-reports) for details.</p>")

(defxdoc signature
  :parents (encapsulate)
  :short "How to specify the arity of a constrained function"
  :long "<p>We start with a gentle introduction to signatures, where we pretend
 that there are no single-threaded objects (more on that below &mdash; for now,
 if you don't know anything about single-threaded objects, that's fine!).  Here
 are some simple examples of signatures.</p>

 @({
  ((hd *) => *)
  ((pair * *) => *)
  ((foo * *) => (mv * * *))
 })

 <p>The first of these says that @('hd') is a function of one argument, while
 the other two say that @('pair') and @('foo') are functions that each take two
 arguments.  The first two say that @('hd') and @('pair') return a single
 value.  The third says that @('foo') returns three values, much as the
 following definition returns three values:</p>

 @({
  (defun bar (x y)
    (mv y x (cons x y)))
 })

 <p>Corresponding ``old style'' signatures are as follows.  In each case, a
 function symbol is followed by a list of formal parameters and then either
 @('t'), to denote a single value return, or @('(mv t t t)'), to denote a
 multiple value return (in this case, returning three values).</p>

 @({
  (hd (x) t)
  (pair (x y) t)
  (foo (x y) (mv t t t))
 })

 <p>That concludes our gentle introduction.  The documentation below is more
 general, for example covering single-threaded objects and keyword values such
 as @(':guard').  When reading what follows below, it is sufficient to know
 about single-threaded objects (or ``stobjs'') that each has a unique symbolic
 name and that @(tsee state) is the name of the only built-in single-threaded
 object.  All other stobjs are introduced by the user via @(tsee defstobj) or
 @(tsee defabsstobj).  An object that is not a single-threaded object is said
 to be ``ordinary.''  For a discussion of single-threaded objects, see @(see
 stobj).</p>

 @({
  Examples:
  ((hd *) => *)
  ((hd *) => * :formals (x) :guard (consp x))
  ((printer * state) => (mv * * state))
  ((mach * mach-state * state) => (mv * mach-state))

  General Form:
  ((fn ...) => *)
  ((fn ...) => stobj)
  or
  ((fn ...) => (mv ...))
  or for part1 and part2 as above,
  (part1 => part2 :kwd1 val1 ... :kwdn valn)
 })

 <p>where @('fn') is the constrained function symbol, @('...') is a list of
 asterisks and/or the names of single-threaded objects, @('stobj') is a
 single-threaded object name, and the optional @(':kwdi') and @('vali') are as
 described below.  ACL2 also supports an older style of signature, described
 below after we describe the preferred style.</p>

 <p>Signatures specify three syntactic aspects of a function symbol: (1) the
 ``arity'' or how many arguments the function takes, (2) the ``multiplicity''
 or how many results it returns via @('MV'), and (3) which of those arguments
 and results are single-threaded objects and which objects they are.</p>

 <p>A signature typically has the form @('((fn x1 ... xn) => val)').  Such a
 signature has two parts, separated by the symbol ``=&gt;''.  The first part,
 @('(fn x1 ... xn)'), is suggestive of a call of the constrained function.  The
 number of ``arguments,'' @('n'), indicates the arity of @('fn').  Each @('xi')
 must be a symbol.  If a given @('xi') is the symbol ``*'' then the
 corresponding argument must be ordinary.  If a given @('xi') is any other
 symbol, that symbol must be the name of a single-threaded object and the
 corresponding argument must be that object.  No stobj name may occur twice
 among the @('xi').</p>

 <p>The second part, @('val'), of a signature is suggestive of a term and
 indicates the ``shape'' of the output of @('fn').  If @('val') is a symbol
 then it must be either the symbol ``*'' or the name of a single-threaded
 object.  In either case, the multiplicity of @('fn') is 1 and @('val')
 indicates whether the result is ordinary or a stobj.  Otherwise, @('val') is
 of the form @('(mv y1 ... yk)'), where @('k') &gt; 1.  Each @('yi') must be
 either the symbol ``*'' or the name of a stobj.  Such a @('val') indicates
 that @('fn') has multiplicity @('k') and the @('yi') indicate which results
 are ordinary and which are stobjs.  No stobj name may occur twice among the
 @('yi'), and a stobj name may appear in @('val') only if appears among the
 @('xi').</p>

 <p>A signature may have the form @('((fn x1 ... xn) => val . k)'), where
 @('k') is a @(tsee keyword-value-listp), i.e., an alternating list of keywords
 and values starting with a keyword.  In this case @('((fn x1 ... xn) => val)')
 must be a legal signature as described above.  The legal keywords in @('k')
 are @(':GUARD') and @(':FORMALS') (except that for ACL2(r), also see the
 remark about @(':CLASSICALP') later in this topic).  The value following
 @(':FORMALS') is to be the list of formal parameters of @('fn'), which must be
 consistent with the parameters specified in @('(fn x1 ... xn)'): they must
 both specify the same arity (number of formal parameters) and the same @(see
 stobj) inputs.  The value following @(':GUARD') is a term that is to be the
 @(see guard) of @('fn').  Note that this guard is never actually evaluated,
 and is not subject to the guard verification performed on functions introduced
 by @(tsee defun) (see @(see verify-guards)).  Said differently: this guard
 need not itself have a guard of @('t').  Indeed, the guard is only used for
 attachments; see @(see defattach).  Note that if @(':GUARD') is supplied, then
 @(':FORMALS') must also be supplied as a list of distinct variables that
 includes all variables occurring free in the specified guard.  One final
 observation about guards: if the @(':GUARD') keyword is omitted, then the
 guard defaults to @('T').</p>

 <p>Before ACL2 supported user-declared single-threaded objects there was only
 one single-threaded object: ACL2's built-in notion of @(tsee state).  The
 notion of signature supported then gave a special role to the symbol
 @('state') and all other symbols were considered to denote ordinary objects.
 ACL2 still supports the old form of signature, but it is limited to functions
 that operate on ordinary objects or ordinary objects and @('state').</p>

 @({
  Old Style General Form:
  (fn formals result . k)
 })

 <p>where @('fn') is the constrained function symbol, @('formals') is a
 suitable list of formal parameters for it, @('k') is an optional @(tsee
 keyword-value-listp) (see below), and @('result') is either a symbol denoting
 that the function returns one result or else @('result') is an @(tsee mv)
 expression, @('(mv s1 ... sn)'), where @('n>1'), each @('si') is a symbol,
 indicating that the function returns @('n') results.  At most one of the
 formals may be the symbol @('STATE'), indicating that the corresponding
 argument must be ACL2's built-in @(tsee state).  If @('state') appears in
 @('formals') then @('state') may appear once in @('result').  All ``variable
 symbols'' other than @('state') in old style signatures denote ordinary
 objects, regardless of whether the symbol has been defined to be a
 single-threaded object name!</p>

 <p>The optional @('k') is as described above for newer-style signatures,
 except that the user is also allowed to declare which symbols (besides
 @('state')) are to be considered single-threaded object names.  Thus
 @(':STOBJS') is also a legal keyword.  The form</p>

 @({
  (fn formals result ... :stobjs names ...)
 })

 <p>specifies that @('names') is either the name of a single-threaded object or
 else is a list of such names.  Every name in @('names') must have been
 previously defined as a stobj via @(tsee defstobj) or @(tsee defabsstobj).</p>

 <p>As promised above, we conclude with a remark about an additional keyword,
 @(':CLASSICALP'), that is legal for ACL2(r) (see @(see real)).  The value of
 this keyword must be @('t') (the default) or @('nil'), indicating respectively
 whether @('fn') is classical or not.</p>")

(defxdoc signed-byte-p
  :parents (numbers acl2-built-ins)
  :short "Recognizer for signed integers that fit in a specified bit width"
  :long "<p>@('(Signed-byte-p bits x)') is @('T') when @('bits') is a positive
 integer and @('x') is a signed integer whose 2's complement representation
 fits in a bit-width of @('bits'), i.e., @('-2^(bits-1) <= x <
 2^(bits-1)').</p>

 <p>Note that a @(see type-spec) of @('(signed-byte i)') for a variable @('x')
 in a function's @(tsee declare) form translates to a @(see guard) condition of
 @('(signed-byte-p i x)').</p>

 <p>The @(see guard) for @('signed-byte-p') is @('T').</p>

 @(def signed-byte-p)")

(defxdoc signum
  :parents (numbers acl2-built-ins)
  :short "Indicator for positive, negative, or zero"
  :long "<p>@('(Signum x)') is @('0') if @('x') is @('0'), @('-1') if @('x') is
 negative, and is @('1') otherwise.</p>

 <p>The @(see guard) for @('signum') requires its argument to be rational
 (@(see real), in ACL2(r)) number.</p>

 <p>@('Signum') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 <p>From ``Common Lisp the Language'' page 206, we see a definition of
 @('signum') in terms of @(tsee abs).  As explained elsewhere (see @(see abs)),
 the @(see guard) for @(tsee abs) requires its argument to be a rational (@(see
 real), in ACL2(r)) number; hence, we make the same restriction for
 @('signum').</p>

 @(def signum)")

(defxdoc simple
  :parents (rewrite definition)
  :short "@(':')@(tsee definition) and @(':')@(tsee rewrite) rules used in
  preprocessing"
  :long "@({
  Example of simple rewrite rule:
  (equal (car (cons x y)) x)

  Examples of simple definition:
  (defun file-clock-p (x) (integerp x))
  (defun naturalp (x)
    (and (integerp x) (>= x 0)))
 })

 <p>The theorem prover output sometimes refers to ``simple'' definitions and
 rewrite rules.  These rules can be used by the preprocessor, which is one of
 the theorem prover's ``processes'' understood by the @(':do-not') hint; see
 @(see hints).</p>

 <p>The preprocessor expands certain definitions and uses certain rewrite rules
 that it considers to be ``fast''.  There are two ways to qualify as fast.  One
 is to be an ``abbreviation'', where a rewrite rule with no hypotheses or loop
 stopper is an ``abbreviation'' if the right side contains no more variable
 occurrences than the left side, and the right side does not call the functions
 @(tsee if), @(tsee not) or @(tsee implies).  Definitions and rewrite rules can
 both be abbreviations; the criterion for definitions is similar, except that
 the definition must not be recursive.  The other way to qualify applies only
 to a non-recursive definition, and applies when its body is a disjunction or
 conjunction, according to a perhaps subtle criterion that is intended to avoid
 case splits.</p>")

(defxdoc sixth
  :parents (nth acl2-built-ins)
  :short "Sixth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc skip-proofs
  :parents (events)
  :short "Skip proofs for a given form &mdash; a quick way to introduce unsoundness"
  :long "@({
  Example Form:
  (skip-proofs
    (defun foo (x)
      (if (atom x) nil (cons (car x) (foo (reverse (cdr x)))))))

  General Form:
  (skip-proofs form)
 })

 <p>where @('form') is processed as usual except that the proof obligations
 usually generated are merely assumed.</p>

 <p>Normally @('form') is an event; see @(see events).  If you want to put
 @('skip-proofs') around more than one event, consider the following (see @(see
 progn)): @('(skip-proofs (progn event1 event2 ... eventk))').</p>

 <p>WARNING: @('Skip-proofs') allows inconsistent @(see events) to be admitted
 to the logic.  Use it at your own risk!</p>

 <p>Sometimes in the development of a formal model or proof it is convenient to
 skip the proofs required by a given event.  By embedding the event in a
 @('skip-proofs') form, you can avoid the proof burdens generated by the event,
 at the risk of introducing unsoundness.  Below we list four illustrative
 situations in which you might find @('skip-proofs') useful.</p>

 <p>1. The termination argument for a proposed function definition is
 complicated.  You presume you could admit it, but are not sure that your
 definition has the desired properties.  By embedding the @(tsee defun) event
 in a @('skip-proofs') you can ``admit'' the function and experiment with
 theorems about it before undoing (see @(see ubt)) and then paying the price of
 its admission.  Note however that you might still have to supply a measure.
 The set of formals used in some valid measure, known as the ``measured
 subset'' of the set of formals, is used by ACL2's induction heuristics and
 therefore needs to be suitably specified.  You may wish to specify the special
 measure of @('(:? v1 ... vk)'), where @('(v1 ... vk)') enumerates the measured
 subset.</p>

 <p>2. You intend eventually to verify the @(see guard)s for a definition but
 do not want to take the time now to pursue that.  By embedding the @(tsee
 verify-guards) event in a @('skip-proofs') you can get the system to behave as
 though the @(see guard)s were verified.</p>

 <p>3. You are repeatedly recertifying a book while making many experimental
 changes.  A certain @(tsee defthm) in the book takes a very long time to prove
 and you believe the proof is not affected by the changes you are making.  By
 embedding the @(tsee defthm) event in a @('skip-proofs') you allow the theorem
 to be assumed without proof during the experimental recertifications.</p>

 <p>4. You are constructing a proof top-down and wish to defer the proof of a
 @(tsee defthm) until you are convinced of its utility.  You can embed the
 @('defthm') in a @('skip-proofs').  Of course, you may find later (when you
 attempt prove the theorem) that the proposed @('defthm') is not a theorem.</p>

 <p>Unsoundness or Lisp errors may result if the presumptions underlying a use
 of @('skip-proofs') are incorrect.  Therefore, @('skip-proofs') must be
 considered a dangerous (though useful) tool in system development.</p>

 <p>Roughly speaking, a @(tsee defthm) embedded in a @('skip-proofs') is
 essentially a @(tsee defaxiom), except that it is not noted as an axiom for
 the purposes of functional instantiation (see @(see lemma-instance)).  But a
 skipped @(tsee defun) is much more subtle since not only is the definitional
 equation being assumed but so are formulas relating to termination and type.
 The situation is also difficult to characterize if the @('skip-proofs') @(see
 events) are within the scope of an @(tsee encapsulate) in which constrained
 functions are being introduced.  In such contexts no clear logical story is
 maintained; in particular, constraints aren't properly tracked for
 definitions.  A proof script involving @('skip-proofs') should be regarded as
 work-in-progress, not as a completed proof with some unproved assumptions.  A
 @('skip-proofs') event represents a promise by the author to admit the given
 event without further axioms.  In other words, @('skip-proofs') should only be
 used when the belief is that the proof obligations are indeed theorems in the
 existing ACL2 logical @(see world).</p>

 <p>ACL2 allows the certification of @(see books) containing @('skip-proofs')
 @(see events) by providing the keyword argument @(':skip-proofs-okp t') to the
 @(tsee certify-book) command.  This is contrary to the spirit of certified
 @(see books), since one is supposedly assured by a valid @(see certificate)
 that a book has been ``blessed.''  But certification, too, takes the view of
 @('skip-proofs') as ``work-in-progress'' and so allows the author of the book
 to promise to finish.  When such @(see books) are certified, a warning to the
 author is printed, reminding him or her of the incurred obligation.  When
 @(see books) containing @('skip-proofs') are included into a session, a
 warning to the user is printed, reminding the user that the book is in fact
 incomplete and possibly inconsistent.  This warning is in fact an error if
 @(':skip-proofs-okp') is @('nil') in the @(tsee include-book) form; see @(see
 include-book).</p>

 <p>We conclude with a technical note.  @('Skip-proofs') works by binding the
 @(tsee ld) special @(tsee ld-skip-proofsp) to @('t') unless it is already
 bound to a non-@('nil') value; see @(see ld-skip-proofsp).</p>")

(defxdoc sleep
  :parents (programming)
  :short "Sleep for some number of seconds"
  :long "<p>The call @('(sleep n)') returns @('nil').  However, it takes
  approximately @('n') seconds of real time for this call to return.</p>

 <p>The @(see guard) for @('sleep') requires its argument to be a non-negative
 rational number.</p>

 <p>@('Sleep') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def sleep)")

(defxdoc slow-alist-warning
  :parents (fast-alists)
  :short "Warnings issued when @(tsee fast-alists) are used inefficiently"
  :long "<p>Obtaining hash-table performance from @(tsee hons-get) requires one
 to follow a certain discipline.  If this discipline is violated, you may see
 the following \"slow alist warning\".</p>

 @({
 *****************************************************************
 Fast alist discipline violated in HONS-ACONS.
 See :DOC slow-alist-warning to suppress or break on this warning.
 *****************************************************************
 })

 <p>This warning means that the alist you are extending or accessing does not
 have a valid hash table associated with it, and hence any accesses must be
 carried out with @(tsee hons-assoc-equal) instead of @('gethash').</p>

 <p>You can control whether or not you get a warning and, if so, whether or not
 a break (an error from which you can continue) ensues.  For instance:</p>

 @({
   (set-slow-alist-action :warning)  ; warn on slow access (default)
   (set-slow-alist-action :break)    ; warn and also call break$
   (set-slow-alist-action nil)       ; do not warn or break
 })

 <p>The above forms expand to @(tsee table) @(see events), so they can be
 embedded in @(tsee encapsulate)s and @(see books), wrapped in @(tsee local),
 and so on.</p>

 <p>We conclude by showing how slow alist warnings can occur naturally,
 together with a couple of possible solutions.  First consider the rather
 trivial example; the labels A1, A2, etc. are explained later.</p>

 @({
 ; (A1) Create a hash-table HT1 and associate it with the resulting alist.
 (assign a (hons-acons 'fn1 1 nil))

 ; (A2) Create a hash-table HT2 and associate it with the resulting alist.
 ; (Minor observation: HT1 is no longer accessible.)
 (assign a (hons-acons 'fn1 1 nil))

 ; (B1) Update HT2 and associate it with the resulting alist.  Thus, H2 is
 ; no longer associated with (@ a).
 (assign b (hons-acons 'fn2 2 (@ a)))

 ; (B2) Fast alist warning: discipline is violated because (@ a) no longer
 ; has a backing hash-table.
 (assign b (hons-acons 'fn2 2 (@ a)))

 ; (C1) Fast alist warning: discipline is violated because (@ b) does not
 ; have a backing hash-table.
 (assign c (hons-acons 'fn3 3 (@ b)))

 ; (C2) Fast alist warning: discipline is violated because (@ b) does not
 ; have a backing hash-table.
 (assign c (hons-acons 'fn3 3 (@ b)))
 })

 <p>Now consider the following related example (in a fresh session), involving
 three @(tsee encapsulate) events labeled A, B, and C.</p>

 @({
 (encapsulate nil (defconst *a* (hons-acons 'fn1 1 nil))) ; (A)
 (encapsulate nil (defconst *b* (hons-acons 'fn2 2 *a*))) ; (B)
 (encapsulate nil (defconst *c* (hons-acons 'fn3 3 *b*))) ; (C)
 })

 <p>Each of these @('encapsulate') events generates two calls of @(tsee
 hons-acons): one in the first pass of the @('encapsulate') and one in the
 second pass.  With a little reflection you can see the connection between the
 two sequences of events above: @('encapsulate') A makes assignments analogous
 to A1 (in its first pass) and A2 (in its second pass); similarly for B, B1, B2
 and for C, C1, C2.  Thus, we get slow alist warnings on the second pass of B
 and on both passes of C.</p>

 <p>The simplest way to fix this problem is to call @(tsee make-fast-alist),
 which is essentially a no-op when its argument is already a fast alist.</p>

 @({
 (encapsulate nil (defconst *a* (make-fast-alist (hons-acons 'fn1 1 nil))))
 (encapsulate nil (defconst *b* (make-fast-alist (hons-acons 'fn2 2 *a*))))
 (encapsulate nil (defconst *c* (make-fast-alist (hons-acons 'fn3 3 *b*))))
 })

 <p>We still see warnings in pass 2 of the second and third encapsulates,
 created by calls of @(tsee hons-acons) exactly as before.  However, the
 results of those two calls are converted to fast alists by
 @('make-fast-alist'); so after each @('encapsulate'), the value of the defined
 constant is indeed a fast alist.  A problem still persists: the second and
 third @(tsee defconst) event each steal the fast-alist value of the previous
 @('defconst').  That's a problem that we won't try to solve here; we will just
 focus on how to ensure that the value of @('*c*') is a fast alist.</p>

 <p>The following alternate solution has the advantage of avoiding the expense
 of reconstituting the fast alist during pass 2 of each of the @('defconst')
 events.  (We continue to use @(tsee encapsulate) since otherwise the issue at
 hand dissolves.)</p>

 @({
 (encapsulate nil (make-event `(defconst *a* ',(hons-acons 'fn1 1 nil))))
 (encapsulate nil (make-event `(defconst *b* ',(hons-acons 'fn2 2 *a*))))
 (encapsulate nil (make-event `(defconst *c* ',(hons-acons 'fn3 3 *b*))))
 })

 <p>These uses of @(tsee make-event) cause each fast alist from pass 1 to be
 saved and then reused in pass 2.  There are no fast-alist warnings, and we
 avoid the expense of @(tsee make-fast-alist).</p>")

(defxdoc slow-array-warning
  :parents (arrays)
  :short "A warning or error issued when @(see arrays) are used inefficiently"
  :long "<p>If you use ACL2 @(see arrays) you may sometimes see a <b>slow
 array</b> warning.  We explain below what that warning means and some likely
 ``mistakes'' it may signify.</p>

 <p>First, we note that you can control whether or not you get a warning and,
 if so, whether or not a break (error from which you can continue; see @(see
 break$)) ensues:</p>

 @({
  (assign slow-array-action :warning) ; warn on slow array access (default)
  (assign slow-array-action :break)   ; warn as above, and then call break$
  (assign slow-array-action nil) ; do not warn or break on slow array access
 })

 <p>If you are using ACL2 arrays, then you probably care about performance, in
 which case it is probably best to avoid the @('nil') setting.  Below we assume
 the default behavior: a warning, but no break.</p>

 <p>The discussion in the documentation for @(see arrays) defines what we mean
 by the semantic value of a name.  As noted there, behind the scenes ACL2
 maintains the invariant that with some names there is associated a pair
 consisting of an ACL2 array @('alist'), called the semantic value of the name,
 and an equivalent raw lisp array.  Access to ACL2 array elements, as in
 @('(aref1 name alist i)'), is executed in constant time when the array alist
 is the semantic value of the name, because we can just use the corresponding
 raw lisp array to obtain the answer.  @(tsee Aset1) and @(tsee compress1)
 modify the raw lisp array appropriately to maintain the invariant.</p>

 <p>If @(tsee aref1) is called on a name and alist, and the alist is not the
 then-current semantic value of the name, the correct result is computed but it
 requires linear time because the alist must be searched.  When this happens,
 @(tsee aref1) prints a <b>slow array</b> warning message to the comment
 window.  @(tsee Aset1) behaves similarly because the array it returns will
 cause the <b>slow array</b> warning every time it is used.</p>

 <p>From the purely logical perspective there is nothing ``wrong'' about such
 use of @(see arrays) and it may be spurious to print a warning message.  But
 because @(see arrays) are generally used to achieve efficiency, the <b>slow
 array</b> warning often means the user's intentions are not being realized.
 Sometimes merely performance expectations are not met; but the message may
 mean that the functional behavior of the program is different than
 intended.</p>

 <p>Here are some ``mistakes'' that might cause this behavior.  In the
 following we suppose the message was printed by @(tsee aset1) about an array
 named @('name').  Suppose the alist supplied @(tsee aset1) is @('alist').</p>

 <p>(1) @(tsee Compress1) was never called on @('name') and @('alist').  That
 is, perhaps you created an alist that is an @(tsee array1p) and then proceeded
 to access it with @(tsee aref1) but never gave ACL2 the chance to create a raw
 lisp array for it.  After creating an alist that is intended for use as an
 array, you must do @('(compress1 name alist)') and pass the resulting
 @('alist'') as the array.</p>

 <p>(2) @('Name') is misspelled.  Perhaps the array was compressed under the
 name @(''delta-1') but accessed under @(''delta1')?</p>

 <p>(3) An @(tsee aset1) was done to modify @('alist'), producing a new array,
 @('alist''), but you subsequently used @('alist') as an array.  Inspect all
 @('(aset1 name ...)') occurrences and make sure that the alist modified is
 never used subsequently (either in that function or any other).  It is good
 practice to adopt the following syntactic style.  Suppose the alist you are
 manipulating is the value of the local variable @('alist').  Suppose at some
 point in a function definition you wish to modify @('alist') with @(tsee
 aset1).  Then write</p>

 @({
  (let ((alist (aset1 name alist i val))) ...)
 })

 <p>and make sure that the subsequent function body is entirely within the
 scope of the @(tsee let).  Any uses of @('alist') subsequently will refer to
 the new alist and it is impossible to refer to the old alist.  Note that if
 you write</p>

 @({
   (foo (let ((alist (aset1 name alist i val))) ...)  ; arg 1
        (bar alist))                                  ; arg 2
 })

 <p>you have broken the rules, because in @('arg 1') you have modified
 @('alist') but in @('arg 2') you refer to the old value.  An appropriate
 rewriting is to lift the @(tsee let) out:</p>

 @({
   (let ((alist (aset1 name alist alist i val)))
     (foo ...                                         ; arg 1
          (bar alist)))                               ; arg 2
 })

 <p>Of course, this may not mean the same thing.</p>

 <p>(4) A function which takes @('alist') as an argument and modifies it with
 @(tsee aset1) fails to return the modified version.  This is really the same
 as (3) above, but focuses on function interfaces.  If a function takes an
 array @('alist') as an argument and the function uses @(tsee aset1) (or a
 subfunction uses @(tsee aset1), etc.), then the function probably ``ought'' to
 return the result produced by @(tsee aset1).  The reasoning is as follows.  If
 the array is passed into the function, then the caller is holding the array.
 After the function modifies it, the caller's version of the array is obsolete.
 If the caller is going to make further use of the array, it must obtain the
 latest version, i.e., that produced by the function.</p>")

(defxdoc solution-to-simple-example
  :parents (annotated-acl2-scripts)
  :short "Solution to a simple example"
  :long "<p>To see a statement of the problem solved below, see @(see
 annotated-acl2-scripts) (in particular the end of that topic).</p>

 <p>Here is a sequence of ACL2 @(see events) that illustrates the use of ACL2
 to make definitions and prove theorems.  We will introduce the notion of the
 fringe of a tree, as well as the notion of a leaf of a tree, and then prove
 that the members of the fringe are exactly the leaves.</p>

 <p>We begin by defining the fringe of a tree, where we identify trees simply
 as @(see cons) structures, with @(see atom)s at the leaves.  The definition is
 recursive, breaking into two cases.  If @('x') is a @(see cons), then the
 @('fringe') of @('x') is obtained by appending together the @('fringe')s of
 the @(tsee car) and @(tsee cdr) (left and right child) of @('x').  Otherwise,
 @('x') is an @(see atom) and its @('fringe') is the one-element list
 containing only @('x').</p>

 @({
    (defun fringe (x)
      (if (consp x)
          (append (fringe (car x))
                  (fringe (cdr x)))
        (list x)))
 })

 <p>Now that @('fringe') has been defined, let us proceed by defining the
 notion of an atom appearing as a ``leaf'', with the goal of proving that the
 leaves of a tree are exactly the members of its @('fringe').</p>

 @({
    (defun leaf-p (atm x)
      (if (consp x)
          (or (leaf-p atm (car x))
              (leaf-p atm (cdr x)))
        (equal atm x)))
 })

 <p>The main theorem is now as follows.  Note that the rewrite rule below uses
 the equivalence relation @(tsee iff) (see @(see equivalence)) rather than
 @(tsee equal), since @(tsee member) returns the tail of the given list that
 begins with the indicated member, rather than returning a Boolean.  (Use
 @(':pe member') to see the definition of @(tsee member).)</p>

 @({
    (defthm leaf-p-iff-member-fringe
      (iff (leaf-p atm x)
           (member-equal atm (fringe x))))
 })")

(defxdoc spec-mv-let
  :parents (parallel-programming acl2-built-ins)
  :short "Modification of @(tsee mv-let) supporting speculative and parallel execution"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism), and see @(see parallel-programming), which has a disclaimer.</p>

 @({
  Example Form:
  (defun pfib-with-step-count (x)
    (declare (xargs :mode :program))
    (if (or (zp x) (< x 33))
        (fib-with-step-count x)
      (spec-mv-let
       (a cnt1)
       (pfib-with-step-count (- x 1))
       (mv-let (b cnt2)
               (pfib-with-step-count (- x 2))
               (if t
                   (mv (+ a b)
                       (+ 1 cnt1 cnt2))
                 (mv \"speculative result is always needed\"
                     -1))))))

  General Form:
  (spec-mv-let
   (v1 ... vn)  ; bind distinct variables
   <spec>       ; evaluate speculatively; return n values
   (mv-let      ; or, use mv?-let if k=1 below
    (w1 ... wk) ; bind distinct variables
    <eager>     ; evaluate eagerly
    (if <test>  ; use results from <spec> if true
        <typical-case> ; may mention v1 ... vn
      <abort-case>)))  ; does not mention v1 ... vn
 })

 <p>Our design of @('spec-mv-let') is guided by its use in ACL2 source code to
 parallelize part of ACL2's proof process, in the experimental parallel
 extension of ACL2.  The user can think of @('spec-mv-let') as a speculative
 version of @(tsee mv-let).  (In ordinary ACL2, the semantics agree with this
 description but without speculative or parallel execution.)</p>

 <p>Evaluation of the above general form proceeds as suggested by the comments.
 First, @('<spec>') is executed speculatively.  Control then passes immediately
 to the @(tsee mv-let) call, without waiting for the result of evaluating
 @('<spec>').  The variables @('(w1 ... wk)') are bound to the result of
 evaluating @('<eager>'), and then @('<test>') is evaluated.  If the value of
 @('<test>') is true, then the values of @('(v1 ... vn)') are needed, and
 @('<typical-case>') blocks until they are available.  If the value of
 @('<test>') is false, then the values of @('(v1 ... vn)') are not needed, and
 the evaluation of @('<spec>') may be aborted.</p>

 <p>The calls to @('mv-let') and to @('if') displayed above in the General Form
 are an essential part of the design of @('spec-mv-let'), and are thus
 required.</p>

 <p>The following definition of @('fib-with-step-count') completes the example
 above:</p>

 @({
  (defun fib-with-step-count (x)
  (declare (xargs :mode :program))
  (cond ((<= x 0)
         (mv 0 1))
        ((= x 1) (mv 1 1))
        (t (mv-let (a cnt1)
                   (fib-with-step-count (- x 1))
                   (mv-let (b cnt2)
                           (fib-with-step-count (- x 2))
                           (mv (+ a b)
                               (+ 1 cnt1 cnt2)))))))
 })")

(defxdoc special-cases-for-rewrite-rules
  :parents (introduction-to-the-theorem-prover)
  :short "Convenient short forms for rewrite rule formulas"
  :long "<p>In principle, every rewrite rule is made from a formula of this
 shape:</p>

 <code>
 (IMPLIES (AND <i>hyp1</i> ... <i>hypk</i>)
          (<i>eqv</i> <i>lhs</i> <i>rhs</i>))
 </code>

 <p>where <i>eqv</i> is either @('EQUAL') or @('IFF') and the result of
 expanding any abbreviations in <i>lhs</i> is the application of some function
 symbol other than @('IF').</p>

 <p>* In the special case where there is only one <i>hyp</i> term, i.e.,
 <i>k</i>=1, the @('(AND') <i>hyp1</i>@(')') can be written <i>hyp1</i>.</p>

 <p>* In the special case where there are no <i>hyp</i> terms, <i>k</i>=0, the
 @('(AND)') term is logically just @('T') and the whole @('IMPLIES') can be
 dropped; such a formula may be written as an unconditional @('EQUAL') or
 @('IFF') term.</p>

 <p>* If you build a rewrite rule from a formula that concludes with @('(NOT')
 <i>x</i>@(')'), it is treated as though it were @('(EQUAL') <i>x</i>
 @('NIL)'), which is logically equivalent to what you typed.</p>

 <p>* If you build a rewrite rule from a formula that concludes with an
 @('AND'), ACL2 will build a rewrite rule for each conjunct of the @('AND').
 This is because</p>

 @({
  (IMPLIES hyp (AND concl1 concl2))
 })

 <p>is propositionally equivalent to</p>

 @({
  (AND (IMPLIES hyp concl1)
       (IMPLIES hyp concl2)).
 })

 <p>However, if you use an @('OR')-expression as a hypothesis, ACL2 does
 <i>not</i> do the dual transformation.  Thus, @('(IMPLIES (OR hyp1 hyp2)
 concl)') generates one rewrite rule.</p>

 <p>* Finally, if you build a rewrite rule from a formula that does not
 conclude with an @('EQUAL'), an @('IFF'), a @('NOT'), or an @('AND,') but with
 some other term, say, <i>lhs</i>, then ACL2 acts like you typed @('(IFF')
 <i>lhs</i> @('T)'), which is logically equivalent to what you typed.</p>

 <p>Thus, regardless of what you type, every rule has <i>k</i> hypotheses.  For
 unconditional rules, <i>k</i> is 0 and the hypotheses are vacuously true.
 Whether or not you write an @('EQUAL') or an @('IFF') in the conclusion, every
 rule is either an equality or a propositional equivalence, every rule has a
 left-hand side, and every rule has a right-hand side.</p>

 <p>Use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-rewrite-rules-part-1).</p>")

(defxdoc specific-kinds-of-formulas-as-rewrite-rules
  :parents (introduction-to-the-theorem-prover)
  :short "Advice about how to handle commonly occurring formulas as rewrite rules"
  :long "<p>Below we give you some guidelines for handling specific, commonly
 occurring situations.</p>

 <p>* <b>Associativity</b>: If a function @('f') is associative, prove</p>

 @({
  (equal (f (f x y) z) (f x (f y z)))
 })

 <p>ACL2 will use this to flatten @('f')-nests ``to the right.''</p>

 <p>* <b>Commutativity</b>: If a function @('f') is commutative, prove both</p>

 @({
  (equal (f x y) (f y x))
 })

 <p>and</p>

 @({
  (equal (f x (f y z)) (f y (f x z)))
 })

 <p>ACL2's heuristics will use these rules to order the arguments
 alphabetically, so that @('(f B (f D (f A C)))') becomes @('(f A (f B (f C
 D)))').</p>

 <p>* <b>Distributivity</b>: If you have a pair of functions @('f') and @('g')
 so that @('(f x (g y z))') is @('(g (f x y) (f x z))') or some other form of
 distributivity is provable, arrange your rules to move the lighter function
 symbol up and the heavier one toward the variable symbols.  For example, our
 arithmetic libraries drive multiplication through addition, producing sums of
 products rather than products of sums.</p>

 <p>* <b>Identity and Other Laws</b>: Prove the obvious identity and zero laws
 (or at least anticipate that you might need them down the road) so as to
 eliminate operators.</p>

 <p>* <b>Get Rid of Tail Recursive Functions</b>: A corollary to the above
 advice concerns tail recursive functions that use auxiliary variables.  New
 users often define concepts using tail recursions, accumulating partial
 results in auxiliary variables, because creating such functions is similar to
 programming with @('while') loops.  Expert users will use tail recursion when
 necessary for execution efficiency.  But tail recursive functions are messy to
 reason about: their auxiliary variables have to be properly initialized to
 make the functions compute the expected results, but to state inductively
 provable properties of tail recursive functions you must identify the
 invariants on those auxiliary variables.  This problem tends not to happen
 with <i>primitive recursive functions</i>.  A primitive recursive function is
 one that recurs down one variable and holds all the other variables constant
 in recursion.  Most tail-recursive functions can be written elegantly as
 primitive recursive functions, though one might have to ignore the
 programmer's desire to make things efficient and define auxiliary functions to
 appropriately transform the value returned by the recursive call.  The classic
 example is reverse defined in terms of the auxiliary function @('append')
 versus reverse defined tail recursively with an accumulator.  By introducing
 @('append') you introduce a concept about which you can state lemmas and
 decompose the proofs of properties of reverse.  So if your problem involves
 tail recursive functions with auxiliary variables, define the primitive
 recursive version, prove that the tail recursive function is equivalent to the
 primitive recursive one, and arrange the rewrite rule to eliminate the tail
 recursive function.</p>

 <p>* <b>Get Rid of Mutually Recursive Functions</b>: Similarly, if you have
 used @('mutual-recursion') to introduce a clique of mutually recursive
 functions, @('f1'), @('f2'), ..., you will find that to reason about any one
 function in the nest you have to reason about all of them.  Any mutually
 recursive function can be defined in a singly recursive way.  So do that and
 then prove a rewrite rule that gets rid of all the mutually recursive
 functions by proving</p>

 @({
  (and (equal (f1 ...) (g1 ...))
       (equal (f2 ...) (g2 ...))
       ...)
 })

 <p>where the @('gi') are singly recursive.  You may need to appeal to a trick
 to define the @('gi'): define a singly recursive function that takes a flag
 argument and mimics whichever mutually recursive function the flag specifies.
 See @(see mutual-recursion) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> and
 see @(see mutual-recursion-proof-example) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.</p>

 <p>If you got to this documentation page from the tutorial discussion of
 rewrite rules, use your browser's <b>Back Button</b> now to return to @(see
 introduction-to-rewrite-rules-part-2).</p>")

(defxdoc specious-simplification
  :parents (miscellaneous)
  :short "Nonproductive proof steps"
  :long "<p>Occasionally the ACL2 theorem prover reports that the current goal
 simplifies to itself or to a set including itself.  Such simplifications are
 said to be ``specious'' and are ignored in the sense that the theorem prover
 acts as though no simplification were possible and tries the next available
 proof technique.  Specious simplifications are almost always caused by
 forcing.</p>

 <p>The simplification of a formula proceeds primarily by the local application
 of @(':')@(tsee rewrite), @(':')@(tsee type-prescription), and other rules to
 its various subterms.  If no rewrite rules apply, the formula cannot be
 simplified and is passed to the next ACL2 proof technique, which is generally
 the elimination of destructors.  The experienced ACL2 user pays special
 attention to such ``maximally simplified'' formulas; the presence of
 unexpected terms in them indicates the need for additional rules or the
 presence of some conflict that prevents existing rules from working
 harmoniously together.</p>

 <p>However, consider the following interesting possibility: local rewrite
 rules apply but, when applied, reproduce the goal as one of its own subgoals.
 How can rewrite rules apply and reproduce the goal?  Of course, one way is for
 one rule application to undo the effect of another, as when commutativity is
 applied twice in succession to the same term.  Another kind of example is when
 two rules conflict and undermine each other.  For example, under suitable
 hypotheses, @('(length x)') might be rewritten to @('(+ 1 (length (cdr x)))')
 by the @(':')@(tsee definition) of @(tsee length) and then a @(':')@(tsee
 rewrite) rule might be used to ``fold'' that back to @('(length x)').
 Generally speaking the presence of such ``looping'' rewrite rules causes
 ACL2's simplifier either to stop gracefully because of heuristics such as that
 described in the documentation for @(tsee loop-stopper) or to cause a stack
 overflow because of indefinite recursion.</p>

 <p>A more insidious kind of loop can be imagined: two rewrites in different
 parts of the formula undo each other's effects ``at a distance,'' that is,
 without ever being applied to one another's output.  For example, perhaps the
 first hypothesis of the formula is simplified to the second, but then the
 second is simplified to the first, so that the end result is a formula
 propositionally equivalent to the original one but with the two hypotheses
 commuted.  This is thought to be impossible unless forcing or case-splitting
 occurs, but if those features are exploited (see @(see force) and see @(see
 case-split)) it can be made to happen relatively easily.</p>

 <p>Here is a simple example.  Declare @('foo') to be a function of one
 argument returning one result:</p>

 @({
  (defstub p1 (x) t)
 })

 <p>Prove the following silly rule:</p>

 @({
  (defthm bad
    (implies (case-split (p1 x))
             (p1 x)))
 })

 <p>Now suppose we try the following.</p>

 @({
  (thm (p1 x))
 })

 <p>The @(see rewrite) rule @('bad') will rewrite @('(p1 x)') to @('t'), but it
 will be unable to prove the hypothesis @('(case-split (p1 x))').  As a result,
 the prover will spawn a new goal, to prove @('(p1 x)').  However, since this
 new goal is the same as the original goal, ACL2 will recognize the
 simplification as <i>specious</i> and consider the attempted simplification to
 have failed.</p>

 <p>In other words, despite the rewriting, no progress was made!  In more
 common cases, the original goal may simplify to a set of subgoals, one of
 which includes the original goal.</p>

 <p>If ACL2 were to adopt the new set of subgoals, it would loop indefinitely.
 Therefore, it checks whether the input goal is a member of the output
 subgoals.  If so, it announces that the simplification is ``specious'' and
 pretends that no simplification occurred.</p>

 <p>``Maximally simplified'' formulas that produce specious simplifications are
 maximally simplified in a very technical sense: were ACL2 to apply every
 applicable rule to them, no progress would be made.  Since ACL2 can only apply
 every applicable rule, it cannot make further progress with the formula.  But
 the informed user can perhaps identify some rule that should not be applied
 and make it inapplicable by disabling it, allowing the simplifier to apply all
 the others and thus make progress.</p>

 <p>When specious simplifications are a problem it might be helpful to @(see
 disable) all forcing (including @(see case-split)s) and resubmit the formula
 to observe whether forcing is involved in the loop or not.  See @(see force).
 The commands</p>

 @({
  ACL2 !>:disable-forcing
  and
  ACL2 !>:enable-forcing
 })

 <p>@(see disable) and @(see enable) the pragmatic effects of both @('force')
 and @('case-split').  If the loop is broken when forcing is @(see disable)d,
 then it is very likely some @(see force)d hypothesis of some rule is
 ``undoing'' a prior simplification.  The most common cause of this is when we
 @(see force) a hypothesis that is actually false but whose falsity is somehow
 temporarily hidden (more below).  To find the offending rule, compare the
 specious simplification with its non-specious counterpart and look for rules
 that were speciously applied that are not applied in the non-specious case.
 Most likely you will find at least one such rule and it will have a @(tsee
 force)d hypothesis.  By disabling that rule, at least for the subgoal in
 question, you may allow the simplifier to make progress on the subgoal.</p>")

(defxdoc splitter
  :parents (debugging)
  :short "Reporting of rules whose application may have caused case splits"
  :long "<p>When the ACL2 rewriter applies a rule to a term, a goal might
 simplify to more than one subgoal.  A rule with such an application is called
 a ``splitter''.  Here, we explain the output produced for splitters when proof
 output is enabled (see @(see set-inhibit-output-lst)) and such reporting is
 turned on (as it is by default) &mdash; that is, when the value of
 @('(')@(tsee splitter-output)@(')') is true.</p>

 <p>See @(see set-splitter-output) for how to turn off, or on, the reporting of
 splitters.  Also see @(see set-case-split-limitations) for information on how
 to control case splits.  Note that since splitters are rule applications,
 splitter output is not generated for case splits that are caused by other than
 rules, such as the mere presence of calls of the function symbol, @(tsee if),
 in the goal.</p>

 <p>We begin by describing three types of splitters.</p>

 <blockquote>

 <p>@('if-intro'): The rule application may have introduced a call of @('IF'),
 in the sense discussed at the end below.</p>

 <p>@('case-split'): For the application of a rule with hypothesis of the form
 @('(case-split <hyp>)'), @('<hyp>') did not simplify to true or false.</p>

 <p>@('immed-forced'): For the application of a rule with hypothesis of the
 form @('(force <hyp>)'), @('<hyp>') did not simplify to true or false, where
 immediate-force-modep is enabled (see @(see
 immediate-force-modep)).</p></blockquote>

 <p>These three annotations &mdash; @('if-intro'), @('case-split'), and
 @('immed-forced') &mdash; may be used in proof output and summaries for
 describing rule applications, as discussed below.  A fourth annotation,
 @('forced'), may also be used in proof output to indicate the application of a
 rule with hypothesis of the form @('(force <hyp>)') when @('<hyp>') did not
 simplify to true or false, where immediate-force-modep is disabled (see @(see
 immediate-force-modep)).  We don't consider such uses of @(tsee force) to be
 splitters, because they do not cause case splits (though they do produce goals
 to prove after lower-case ``q.e.d.'' is printed); see @(see force).</p>

 <p>There are three kinds of output affected by splitters, illustrated in turn
 below using examples.</p>

 <blockquote><p>(a) During the proof, @(see gag-mode) and raw proof format (see
 @(see set-raw-proof-format)) off<br></br>

 (b) During the proof, @(see gag-mode) or raw proof format on<br></br>

 (c) Summary</p></blockquote>

 <p>Of course, (a) and (b) are skipped if proof output is inhibited, and (c) is
 skipped if summary output is inhibited; see @(see set-inhibit-output-lst).</p>

 <p>(a) During the proof, @(see gag-mode) and raw proof format (see @(see
 set-raw-proof-format)) off</p>

 <p>With @(see gag-mode) off (or when using @(':')@(tsee pso), @(':')@(tsee
 psof), or @(':')@(tsee psog)) one normally gets an English commentary.  The
 following output indicates that at least one application of each rule @('F')
 and @('G') is of type @('if-intro'), at least one application of rules @('G')
 and @('R1') are of type @('case-split'), and at least one application of rule
 @('R3') is of type @('immed-forced').  If @(see immediate-force-modep) is off
 then ``@('immed-forced')'' would be replaced by ``@('forced')''.</p>

 @({
    This simplifies, using the :definitions F (if-intro), G (case-split and
    if-intro) and H and the :rewrite rules R1, R2 (case-split), and
    R3 (immed-forced), to the following two conjectures.
 })

 <p>Note that any such printing of ``@('forced')'' is done even if
 @('(splitter-output)') is false.</p>

 <p>(b) During the proof, @(see gag-mode) or raw proof format on</p>

 <p>With @(see gag-mode) or raw proof format (see @(see set-raw-proof-format))
 on, the proof output is abbreviated.  However, in these cases ``Splitter
 Notes'' are printed so that one can still get important information to help
 control large case splits (by disabling splitter rules as appropriate).  These
 are printed at the point when a goal splits into subgoals.  Here, for example,
 is the Splitter Note that corresponds to the output shown in (a) above.  It
 shows the goal whose simplification has produced a split into more than one
 subgoal, and it shows how many subgoals have been created.</p>

 @({
  Splitter note (see :DOC splitter) for Subgoal *1/2.2.1' (2 subgoals).
    case-split: ((:DEFINITION G) (:REWRITE R2))
    immed-forced: ((:REWRITE R3))
    if-intro: ((:DEFINITION G) (:DEFINITION F))
 })

 <p>No such splitter notes are printed for the use of @(tsee force) (when @(see
 immediate-force-modep) is off).</p>

 <p>(c) Summary</p>

 <p>Here is a possible summary corresponding to our running example.  In the
 summary, ``Splitter rules'' is omitted if there are no splitter rules, and a
 splitter type is only mentioned if there is at least one corresponding
 splitter rule.</p>

 @({
  Summary
  Form:  ( THM ...)
  Rules: ((:DEFINITION F)
          (:DEFINITION G)
          (:DEFINITION H)
          (:REWRITE R1)
          (:REWRITE R2)
          (:REWRITE R3))
  Splitter rules (see :DOC splitter):
    case-split: ((:DEFINITION G) (:REWRITE R2))
    immed-forced: ((:REWRITE R3))
    if-intro: ((:DEFINITION G) (:DEFINITION F))
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.00)
  Prover steps counted:  145
 })

 <p>No indication for ``@('forced')'' is given for ``Splitter rules''.  (As
 discussed earlier above, the @(tsee force)d hypotheses are not considered
 relevant for determining splitter rule applications unless @(see
 immediate-force-modep) is on.)</p>

 <p>We conclude by giving the criteria for a @(see rewrite) or @(see
 definition) rule application to be a splitter of type @('if-intro').</p>

 <ul>

 <li>Reporting of splitter rules is on, i.e., the value of @('(')@(tsee
 splitter-output)@(')') is true.</li>

 <li>At least two subgoals are created, even before considering subgoals
 generated by hypotheses that are calls of @(tsee case-split) or @(tsee
 force).</li>

 <li>The term to which the rule is applied is at the top level, rather than
 being encountered when trying to establish the hypothesis of a rule.</li>

 <li>The rule is a @(see rewrite) rule, a @(see definition) rule, or a @(see
 meta) rule.</li>

 <li>There is a call of the function symbol @('IF') in the right-hand side of
 the @(see rewrite) rule; or, in the case of a @(see definition) rule, in the
 body of the definition; or, in the case of a @(see meta) rule, in the result
 of applying the metafunction.</li>

 <li>There is a call of the function symbol @('IF') in the result of
 rewriting: the right-hand side (for a @(see rewrite) rule), the definition
 body (for a @(see definition) rule), or the metafunction application (for a
 @(see meta) rule).</li>

 </ul>

 <p>Any rule application meeting the above criteria will be considered a
 splitter of type @('if-intro'), even if the call does not actually cause a
 case split.  For example, if you are proving @('(implies (hyp x) (conc x))')
 and rule R rewrites @('(hyp x)') to @('(if (h1 x) (h2 x) nil)'), which is
 really the term @('(and (h1 x) (h2 x))'), then R may be labeled as a splitter
 rule.  If you want to find the causes of case-splitting, the list of
 @('if-intro') splitters can help you narrow your search, but may include
 irrelevant rules as well.</p>

 <p>Finally, note that you may see splits not attributed to splitters.  We
 believe that this will be uncommon during simplification, though it can occur
 for example when a call of @('IF') is in the body of a @(tsee LET) expression,
 i.e., in a call of a @(tsee LAMBDA) expression.  But splits caused by other
 processes, notably destructor elimination (see @(see elim)), will typically
 not be attributed to splitters.</p>")

(defxdoc splitter-output
  :parents (splitter)
  :short "Status for reporting of @(see splitter) rules"
  :long "<p>See @(see splitter) for a discussion of splitter rules.  See @(see
 set-splitter-output) for how to turn off, or on, the reporting of splitter
 rules.  When splitter-output is off, because either @('prove') output is
 inhibited
 (see @(see set-inhibit-output-lst)) or @('(')@(tsee set-splitter-output)@('
 nil)') has been invoked, then the value of @('(splitter-output)') is @('nil').
 Otherwise, such reporting is on and the value is non-@('nil').</p>")

(defxdoc standard-char-listp
  :parents (characters lists acl2-built-ins)
  :short "Recognizer for a true list of standard characters"
  :long "<p>@('(standard-char-listp x)') is true if and only if @('x') is a
 null-terminated list all of whose members are standard @(see characters).  See
 @(see standard-char-p).</p>

 <p>@('Standard-char-listp') has a @(see guard) of @('t').</p>

 @(def standard-char-listp)")

(defxdoc standard-char-p
  :parents (characters acl2-built-ins)
  :short "Recognizer for standard characters"
  :long "<p>@('(Standard-char-p x)') is true if and only if @('x') is a
 ``standard'' character, i.e., a member of the list @('*standard-chars*').
 This list includes @('#\\Newline') and @('#\\Space') @(see characters), as
 well as the usual punctuation and alphanumeric @(see characters).</p>

 <p>@('Standard-char-p') has a @(see guard) requiring its argument to be a
 character.</p>

 <p>@('Standard-char-p') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def standard-char-p)")

(defxdoc standard-co
  :parents (io acl2-built-ins)
  :short "The character output channel to which @(tsee ld) prints"
  :long "<p>@('Standard-co') is an @(tsee ld) special (see @(see ld)).  The
 accessor is @('(standard-co state)') and the updater is @('(set-standard-co
 val state)').  @('Standard-co') must be an open character output channel.  It
 is to this channel that @(tsee ld) prints the @(see prompt), the form to be
 evaluated, and the results.  The event @(see command)s such as @(tsee defun),
 @(tsee defthm), etc., which print extensive commentary do not print to
 @('standard-co') but rather to a different channel, @(tsee proofs-co), so that
 you may redirect this commentary while still interacting via @('standard-co').
 See @(see proofs-co).</p>

 <p>``Standard-co'' stands for ``standard character output.'' The initial value
 of @('standard-co') is the same as the value of @(tsee *standard-co*) (see
 @(see *standard-co*)).</p>")

(defxdoc standard-oi
  :parents (io acl2-built-ins)
  :short "The standard object input ``channel''"
  :long "<p>@('Standard-oi') is an @(tsee ld) special (see @(see ld)).  The
 accessor is @('(standard-oi state)') and the updater is @('(set-standard-oi
 val state)').  @('Standard-oi') must be an open object input channel, a true
 list of objects, or a list of objects whose last @(tsee cdr) is an open object
 input channel.  It is from this source that @(tsee ld) takes the input forms
 to process.  When @(tsee ld) is called, if the value specified for
 @('standard-oi') is a string or a list of objects whose last @(tsee cdr) is a
 string, then @(tsee ld) treats the string as a file name and opens an object
 input channel from that file, where the connected book directory (see @(see
 cbd)) is used to resolve relative pathnames.  The channel opened by @(tsee ld)
 is closed by @(tsee ld) upon termination.</p>

 <p>``Standard-oi'' stands for ``standard object input.'' The read-eval-print
 loop in @(tsee ld) reads the objects in @('standard-oi') and treats them as
 forms to be evaluated.  The initial value of @('standard-oi') is the same as
 the value of @(tsee *standard-oi*) (see @(see *standard-oi*)).</p>")

(defxdoc standard-part
  :parents (real)
  :short "ACL2(r) function mapping limited numbers to standard numbers"
  :long "<p>@('(Standard-part x)') is, for a given @(tsee i-limited) number
 @('x'), the unique real number infinitesimally close (see @(see i-close)) to
 @('x').  This function is only defined in ACL2(r) (see @(see real)).</p>")

(defxdoc standard-string-alistp
  :parents (alists acl2-built-ins)
  :short "Recognizer for association lists with standard strings as keys"
  :long "<p>@('(Standard-string-alistp x)') is true if and only if @('x') is a
 list of pairs of the form @('(cons key val)') where @('key') is a string all
 of whose characters are standard (see @(see standard-char-p)).</p>

 <p>@('Standard-string-alistp') has a @(see guard) of @('t').</p>

 @(def standard-string-alistp)")

(defxdoc standardp
  :parents (real)
  :short "ACL2(r) recognizer for standard objects"
  :long "<p>@('(Standardp x)') is true if and only if @('x') is a ``standard''
 object.  This notion of ``standard'' comes from non-standard analysis and is
 discussed in Ruben Gamboa's dissertation.  In brief, all the familiar objects
 are standard: e.g., the familiar real numbers are standard, but non-zero
 infinitesimals are not standard, and the familiar integers are standard, but
 not those that exceed every integer that you can express in the usual way (1,
 2, 3, and so on).  Similarly, the familiar lists are standard, but not so a
 list that contains a large number of integers, where ``large'' means more than
 the standard integers.  The set of standard numbers is closed under the usual
 arithmetic operations, hence the sum of a standard number and a non-zero
 infinitesimal is not standard, though it is what is called ``limited'' (see
 @(see i-limited)).</p>

 <p>This predicate is only defined in ACL2(r) (see @(see real)).</p>")

(defxdoc start-proof-tree
  :parents (proof-tree)
  :short "Start displaying proof trees during proofs"
  :long "<p>Also see @(see proof-tree) and see @(see stop-proof-tree).  Note
 that @(':start-proof-tree') works by removing @(''')@(tsee proof-tree) from
 the @('inhibit-output-lst'); see @(see set-inhibit-output-lst).</p>

 <p>Explanations of proof tree displays may be found elsewhere: see @(see
 proof-tree).  In a nutshell: @(':start-proof-tree') causes proof tree display
 to be turned on, once it has been turned off by @(':')@(tsee
 stop-proof-tree).</p>

 <p>Do not attempt to invoke @('start-proof-tree') during an interrupt in the
 middle of a proof.</p>")

(defxdoc startup
  :parents (acl2-tutorial)
  :short "How to start using ACL2; the ACL2 @(see command) loop"
  :long "<p>When you start up ACL2, you'll probably find yourself inside the
 ACL2 @(see command) loop, as indicated by the following @(see prompt).</p>

 @({
    ACL2 !>
 })

 <p>If not, you should type @('(LP)').  See @(see lp), which has a lot more
 information about the ACL2 @(see command) loop.</p>

 <p>You should now be in ACL2.  The current ``@(see default-defun-mode)'' is
 @(':')@(tsee logic); the other mode is @(':')@(tsee program), which would
 cause the letter @('p') to be printed in the @(see prompt).  @(':')@(tsee
 Logic) means that any function we define is not only executable but also is
 axiomatically defined in the ACL2 logic.  See @(see defun-mode) and see @(see
 default-defun-mode).  For example we can define a function @('my-cons') as
 follows.  (You may find it useful to start up ACL2 and submit this and other
 @(see command)s below to the ACL2 @(see command) loop, as we won't include
 output below.)</p>

 @({
    ACL2 !>(defun my-cons (x y) (cons x y))
 })

 <p>An easy theorem may then be proved: the @(tsee car) of @('(my-cons a b)')
 is A.</p>

 @({
    ACL2 !>(defthm car-my-cons (equal (car (my-cons a b)) a))
 })

 <p>You can place raw Lisp forms to evaluate at start-up into file
 @('acl2-init.lsp') in your home directory, except on Windows systems.  For
 example, if you put the following into @('acl2-init.lsp'), then ACL2 will
 print \"HI\" when it starts up.</p>

 @({
  (print \"HI\")
 })

 <p>But be careful; all bets are off when you submit forms to raw Lisp, so this
 capability should only be used when you are hacking or when you are setting
 some Lisp parameters (e.g., @('(setq si::*notify-gbc* nil)') to turn off
 garbage collection notices in GCL).</p>

 <p>Notice that unlike Nqthm, the theorem @(see command) is @(tsee defthm)
 rather than @('prove-lemma').  See @(see defthm), which explains (among other
 things) that the default is to turn theorems into @(see rewrite) rules.</p>

 <p>Various keyword commands are available to query the ACL2 ``@(see world)'',
 or database.  For example, we may view the definition of @('my-cons') by
 invoking a command to print @(see events), as follows.</p>

 @({
    ACL2 !>:pe my-cons
 })

 <p>Also see @(see pe).  We may also view all the lemmas that @(see rewrite)
 @(see term)s whose top function symbol is @(tsee car) by using the following
 command, whose output will refer to the lemma @('car-my-cons') proved
 above.</p>

 @({
    ACL2 !>:pl car
 })

 <p>Also see @(see pl).  Finally, we may print all the @(see command)s back
 through the initial @(see world) as follows.</p>

 @({
    ACL2 !>:pbt 0
 })

 <p>See @(see history) for a list of commands, including these, for viewing the
 current ACL2 @(see world).</p>

 <p>Continue with the @(see documentation) for @(see annotated-acl2-scripts) to
 see a simple but illustrative example in the use of ACL2 for reasoning about
 functions.</p>")

(defxdoc state
  :parents (programming)
  :short "The von Neumannesque ACL2 state object"
  :long "<p>Note: If you are interested in programming with state, see @(see
 programming-with-state) after reading the information below.</p>

 <p>The ACL2 state object is used extensively in programming the ACL2 system,
 and has been used in other ACL2 programs as well.  However, most users,
 especially those interested in specification and verification (as opposed to
 programming <i>per se</i>), need not be aware of the role of the state object
 in ACL2, and will not write functions that use it explicitly.  We say more
 about this point at the end of this documentation topic.</p>

 <p>The ACL2 state object is an example of a single-threaded object or @(see
 stobj).  ACL2 allows the user to define new single-threaded objects.
 Generally, ACL2 may need to access the ACL2 state but should not (cannot)
 change it except via a certain set of approved functions such as @(tsee defun)
 and @(tsee defthm).  If you need a state-like object to which you have
 complete rights, you may want a @(see stobj).</p>

 <p>Key to the idea of our @('state') is the notion of single-threadedness.
 For an explanation, see @(see stobj).  The upshot of it is that @('state') is
 a variable symbol with severe restrictions on its use, so that it can be
 passed into only certain functions in certain slots, and must be returned by
 those functions that ``modify'' it.  Henceforth, we do not discuss
 single-threaded objects in general (which the user can introduce with @(tsee
 defstobj) and @(tsee defabsstobj)) but one in particular, namely ACL2's
 @('state') object.</p>

 <p>The <i>global table</i> is perhaps the most visible portion of the state
 object.  Using the interface functions @('@') and @('assign'), a user may bind
 global variables to the results of function evaluations (much as an Nqthm user
 exploits the Nqthm utility @('r-loop')).  See @(see @), and see @(see assign).
 A particularly interesting global is @(''current-acl2-world'), whose value is
 the ACL2 logical @(see world).</p>

 <p>ACL2 supports several facilities of a truly von Neumannesque state machine
 character, including file @(see io) and global variables.  Logically speaking,
 the state is a true list of the 14 components described below.  There is a
 ``current'' state object at the top-level of the ACL2 @(see command) loop.
 This object is understood to be the value of what would otherwise be the free
 variable @('state') appearing in top-level input.  When any @(see command)
 returns a state object as one of its values, that object becomes the new
 current state.  But ACL2 provides von Neumann style speed for state operations
 by maintaining only one physical (as opposed to logical) state object.
 Operations on the state are in fact destructive.  This implementation does not
 violate the applicative semantics because we enforce certain draconian
 syntactic rules regarding the use of state objects.  For example, one cannot
 ``hold on'' to an old state, access the components of a state arbitrarily, or
 ``modify'' a state object without passing it on to subsequent state-sensitive
 functions.</p>

 <p>Every routine that uses the state facilities (e.g. does @(see io), or calls
 a routine that does @(see io)), must be passed a ``state object.'' And a
 routine must return a state object if the routine modifies the state in any
 way.  Rigid syntactic rules governing the use of state objects are enforced by
 the function @('translate'), through which all ACL2 user input first passes.
 State objects can only be ``held'' in the formal parameter @('state'), never
 in any other formal parameter and never in any structure (excepting a
 multiple-value return list field which is always a state object).  State
 objects can only be accessed with the primitives we specifically permit.
 Thus, for example, one cannot ask, in code to be executed, for the length of
 @('state') or the @(tsee car) of @('state').  In the statement and proof of
 theorems, there are no syntactic rules prohibiting arbitrary treatment of
 state objects.</p>

 <p>Logically speaking, a state object is a true list whose members are as
 follows:</p>

 <blockquote>

 <p>@('Open-input-channels'), an alist with keys that are symbols in package
 @('\"ACL2-INPUT-CHANNEL\"').  The value (@(tsee cdr)) of each pair has the
 form @('((:header type file-name open-time) . elements)'), where @('type') is
 one of @(':character'), @(':byte'), or @(':object') and @('elements') is a
 list of things of the corresponding @('type'), i.e. characters, integers of
 type @('(mod 255)'), or lisp objects in our theory.  @('File-name') is a
 string.  @('Open-time') is an integer.  See @(see io).</p>

 <p>@('Open-output-channels'), an alist with keys that are symbols in package
 @('\"ACL2-OUTPUT-CHANNEL\"').  The value of a pair has the form @('((:header
 type file-name open-time) .  current-contents)').  See @(see io).</p>

 <p>@('Global-table'), an alist associating symbols (to be used as ``global
 variables'') with values.  See @(see @), and see @(see assign).</p>

 <p>@('T-stack'), a list of arbitrary objects accessed and changed by the
 functions @('aref-t-stack') and @('aset-t-stack').</p>

 <p>@('32-bit-integer-stack'), a list of arbitrary 32-bit-integers accessed and
 changed by the functions @('aref-32-bit-integer-stack') and
 @('aset-32-bit-integer-stack').</p>

 <p>@('Big-clock-entry'), an integer, that is used logically to bound the
 amount of effort spent to evaluate a quoted form.</p>

 <p>@('Idates'), a list of dates and times, used to implement the function
 @('print-current-idate'), which prints the date and time.</p>

 <p>@('Acl2-oracle'), a list of objects, used for example to implement the
 functions that let ACL2 report how much time was used, but inaccessible to the
 user.  See @(tsee read-acl2-oracle) and also see @(tsee
 with-prover-time-limit).</p>

 <p>@('File-clock'), an integer that is increased on every file opening and
 closing, and is used to maintain the consistency of the @(tsee io)
 primitives.</p>

 <p>@('Readable-files'), an alist whose keys have the form @('(string type
 time)'), where @(tsee string) is a file name and @('time') is an integer.  The
 value associated with such a key is a list of characters, bytes, or objects,
 according to @('type').  The @('time') field is used in the following way:
 when it comes time to open a file for input, we will only look for a file of
 the specified name and @('type') whose time field is that of @('file-clock').
 This permits us to have a ``probe-file'' aspect to @('open-file'): one can ask
 for a file, find it does not exist, but come back later and find that it does
 now exist.</p>

 <p>@('Written-files'), an alist whose keys have the form @('(string type time1
 time2)'), where @(tsee string) is a file name, @('type') is one of
 @(':character'), @(':byte') or @(':object'), and @('time1') and @('time2') are
 integers.  @('Time1') and @('time2') correspond to the @('file-clock') time at
 which the channel for the file was opened and closed.  This field is
 write-only; the only operation that affects this field is
 @('close-output-channel'), which @(tsee cons)es a new entry on the front.</p>

 <p>@('Read-files'), a list of the form @('(string type time1 time2)'), where
 @(tsee string) is a file name and @('time1') and @('time2') were the times at
 which the file was opened for reading and closed.  This field is write
 only.</p>

 <p>@('Writeable-files'), an alist whose keys have the form @('(string type
 time)').  To open a file for output, we require that the name, type, and time
 be on this list.</p>

 <p>@('List-all-package-names-lst'), a list of @('true-listps').  Roughly
 speaking, the @(tsee car) of this list is the list of all package names known
 to this Common Lisp right now and the @(tsee cdr) of this list is the value of
 this @('state') variable after you look at its @(tsee car).  The function,
 @('list-all-package-names'), which takes the state as an argument, returns the
 @(tsee car) and @(tsee cdr)s the list (returning a new state too).  This
 essentially gives ACL2 access to what is provided by CLTL's
 @('list-all-packages').  @(tsee Defpkg) uses this feature to ensure that the
 about-to-be-created package is new in this lisp.  Thus, for example, in
 @('akcl') it is impossible to create the package @('\"COMPILER\"') with @(tsee
 defpkg) because it is on the list, while in Lucid that package name is not
 initially on the list.</p>

 <p>@('User-stobj-alist'), an alist which associates user-defined
 single-threaded objects (see @(see stobj)) with their values.</p></blockquote>

 <p>We recommend avoiding the use of the state object when writing ACL2 code
 intended to be used as a formal model of some system, for several reasons.
 First, the state object is complicated and contains many components that are
 oriented toward implementation and are likely to be irrelevant to the model in
 question.  Second, there is currently not much support for reasoning about
 ACL2 functions that manipulate the state object, beyond their logical
 definitions.  Third, the documentation about state is not as complete as one
 might wish.</p>

 <p>User-defined single-threaded objects offer the speed of @('state') while
 giving the user complete access to all the fields.  See @(see stobj).</p>

 <p>Again, if you are interested in programming with state see @(see
 programming-with-state).</p>")

(defxdoc state-global-let*
  :parents (programming-with-state acl2-built-ins)
  :short "Bind @(see state) global variables"
  :long "<p>See @(see programming-with-state) for requisite background on
 programming with the ACL2 @(see state).</p>

 @({
  Example Forms:
  (state-global-let*
   ((inhibit-output-lst *valid-output-names*))
   (thm (equal x x)))

  (state-global-let*
   ((fmt-hard-right-margin 1000 set-fmt-hard-right-margin)
    (fmt-soft-right-margin 1000 set-fmt-soft-right-margin))
   (mini-proveall))

  General Form:
  (state-global-let* ((var1 form1) ; or (var1 form1 set-var1)
                      ...
                      (vark formk) ; or (vark formk set-vark)
                     )
                     body)
 })

 <p>where: each @('vari') is a variable; each @('formi') is an expression whose
 value is a single ordinary object (i.e. not multiple values, and not @(see
 state) or any other @(see stobj)); @('set-vari'), if supplied, is a function
 with @(see signature) @('((set-vari * state) => state)'); and @('body') is an
 expression that evaluates to an @(see error-triple).  Each @('formi') is
 evaluated in order, starting with @('form1'), and with each such binding the
 state global variable @('vari') is bound to the value of @('formi'),
 sequentially in the style of @(tsee let*).  More precisely, then meaning of
 this form is to set (in order) the global values of the indicated @(see state)
 global variables @('vari') to the values of @('formi') using @(tsee
 f-put-global), execute @('body'), restore the @('vari') to their previous
 values (but see the discussion of setters below), and return the triple
 produced by body (with its state as modified by the restoration).  The
 restoration is guaranteed even in the face of aborts.  The ``bound'' variables
 may initially be unbound in state and restoration means to make them unbound
 again.</p>

 <p>Still referring to the General Form above, let @('old-vali') be the value
 of state global variable @('vari') at the time @('vari') is about to be
 assigned the value of @('formi').  If @('set-vari') is not supplied, then as
 suggested above, the following form is evaluated at the conclusion of the
 evaluation of the @('state-global-let*') form, whether or not an error has
 occurred: @('(f-put-global 'vari 'old-vali state)').  However, if
 @('set-vari') is supplied, then instead the form evaluated will be
 @('(set-vari 'old-vali state)').  This capability is particularly useful if
 @('vari') is untouchable (see @(see push-untouchable)), since the above call
 of @(tsee f-put-global) is illegal.</p>

 <p>Note that the scope of the bindings of a @('state-global-let*') form is the
 body of that form.  This may seem obvious, but to drive the point home, let's
 consider the following example (see @(see set-print-base) and see @(see
 set-print-radix)).</p>

 @({
  ACL2 !>(state-global-let* ((print-base 16 set-print-base)
                             (print-radix t set-print-radix))
                            (mv nil 10 state))
   10
  ACL2 !>
 })

 <p>Why wasn't the result printed as @('#xA')?  The reason is that the result
 was printed after evaluation of the entire form had completed.  If you want to
 see @('#xA'), do the printing in the scope of the bindings, for example as
 follows.</p>

 @({
  ACL2 !>(state-global-let* ((print-base 16 set-print-base)
                             (print-radix t set-print-radix))
                            (pprogn (fms \"~x0~%\"
                                         (list (cons #0 10))
                                         *standard-co* state nil)
                                    (mv nil 10 state)))

  #xA
   10
  ACL2 !>
 })")

(defxdoc stobj
  :parents (programming)
  :short "Single-threaded objects or ``von Neumann bottlenecks''"
  :long "<p>In ACL2, a ``single-threaded object'' is a data structure whose use
 is so syntactically restricted that only one instance of the object need ever
 exist and its fields can be updated by destructive assignments.</p>

 <p>Note: Novices are advised to avoid using single-threaded objects, perhaps
 instead using @(see std::defaggregate) or community book
 @('books/data-structures/structures.lisp').  At the least, consider using
 @('(')@(tsee set-verify-guards-eagerness)@(' 0)') to avoid @(see guard)
 verification.</p>

 <p>The documentation in this section is laid out in the form of a tour that
 visits the documented topics in a reasonable order.  We recommend that you
 follow the tour the first time you read about stobjs.  The list of all stobj
 topics is shown below.  The tour starts immediately afterwards.  Also see
 @(see defstobj) and, for so-called abstract stobjs, see @(see
 defabsstobj).</p>

 <p>As noted, a ``single-threaded object'' is a data structure whose use is so
 syntactically restricted that only one instance of the object need ever exist.
 Updates to the object must be sequentialized.  This allows us to update its
 fields with destructive assignments without wrecking the axiomatic semantics
 of update-by-copy.  For this reason, single-threaded objects are sometimes
 called ``von Neumann bottlenecks.''</p>

 <p>From the logical perspective, a single-threaded object is an ordinary ACL2
 object, e.g., composed of integers and conses.  Logically speaking, ordinary
 ACL2 functions are defined to allow the user to ``access'' and ``update'' its
 fields.  Logically speaking, when fields in the object, obj, are ``updated''
 with new values, a new object, obj', is constructed.</p>

 <p>But suppose that by syntactic means we could ensure that there were no more
 references to the ``old'' object, obj.  Then we could create obj' by
 destructively modifying the memory locations involved in the representation of
 obj.  The syntactic means is pretty simple but draconian: the only reference
 to obj is in the variable named @('OBJ').</p>

 <p>The consequences of this simple rule are far-reaching and require some
 getting used to.  For example, if @('OBJ') has been declared as a
 single-threaded object name, then the following consequences ensue (but see
 the discussion of congruent stobjs below for a slight relaxation).</p>

 <ul>

 <li>@('OBJ') is a top-level global variable that contains the current object,
 obj.</li>

 <li>If a function uses the formal parameter @('OBJ'), the only ``actual
 expression'' that can be passed into that slot is the variable @('OBJ'), not
 merely a term that ``evaluates to an obj''; thus, such functions can only
 operate on the current object.  So for example, instead of @('(FOO
 (UPDATE-FIELD1 3 ST))') write @('(LET ((ST (UPDATE-FIELD1 3 ST))) (FOO
 ST))').</li>

 <li>The accessors and updaters have a formal parameter named @('OBJ'), so by
 the rule just above, those functions can only be applied to the current
 object.  The recognizer is the one exception to the rule: it may be applied
 either the @('OBJ') or to an ordinary (non-stobj) object.</li>

 <li>The ACL2 primitives, such as @('CONS'), @('CAR') and @('CDR'), may not be
 applied to the variable @('OBJ').  Thus, for example, obj may not be consed
 into a list (which would create another pointer to it) or accessed or copied
 via ``unapproved'' means.</li>

 <li>The updaters return a ``new @('OBJ') object'', i.e., obj'; thus, when an
 updater is called, the only variable which can hold its result is
 @('OBJ').</li>

 <li>If a function calls an @('OBJ') updater, it must return an @('OBJ')
 object (either as the sole value returned, or in @('(mv ... OBJ ...)'); see
 @(see mv)).</li>

 <li>When a top-level expression involving @('OBJ') returns an @('OBJ')
 object, that object becomes the new current value of @('OBJ').</li>

 </ul>

 <p>There are other functional languages supporting single-threadedness, for
 example Haskell's ``monads'' and Clean's ``uniqueness type system''.  Of
 course, ACL2 provides a theorem prover that can prove theorems that involve
 such constructs.</p>

 <p>Note that the syntactic restrictions noted above are enforced only when
 single-threaded objects are encountered directly in the top-level loop or are
 used in function definitions; the accessor and update functions for
 single-threaded objects may be used without restriction in formulas to be
 proved.  Since function evaluation is sometimes necessary during proofs, ACL2
 must be able to evaluate these functions on logical constants representing the
 object, even when the constant is not ``the current object.''  Thus, ACL2
 supports both the efficient von Neumann semantics and the clean applicative
 semantics, and uses the first in contexts where execution speed is paramount
 and the second during proofs.</p>

 <p>@(tsee Defstobj) and @(tsee defabsstobj) @(see events) introduce stobjs.
 See @(see defstobj) for more details about stobjs.  In particular, a
 relatively advanced notion of ``congruent stobjs'' is discussed there.  The
 idea is to allow a stobj, @('st2'), of the same ``shape'' as a given stobj,
 @('st1'), to be used in place of @('st1').  Other @(tsee defstobj) keywords
 allow inlining and renaming of stobj accessors and updaters.</p>

 <p>But we are getting ahead of ourselves.  To start the stobj tour, see @(see
 stobj-example-1).</p>")

(defxdoc stobj-example-1
  :parents (stobj)
  :short "An example of the use of single-threaded objects"
  :long "<p>Suppose we want to sweep a tree and (1) count the number of
 interior nodes, (2) count the number of tips and (3) keep a record of every
 tip we encounter that is an integer.  We could use a single-threaded object as
 our ``accumulator''.  Such an object would have three fields, one holding the
 number of nodes seen so far, one holding the number of tips, and one holding
 all the integer tips seen.</p>

 <p>The following event declares @('counters') to be a single-threaded
 object.</p>

 @({
  (defstobj counters
    (NodeCnt     :type integer :initially 0)
    (TipCnt      :type integer :initially 0)
    (IntTipsSeen :type t       :initially nil))
 })

 <p>It has three fields, @('NodeCnt'), @('TipCnt'), and @('IntTipsSeen').  (As
 always in ACL2, capitalization is irrelevant in simple symbol names, so the
 first name could be written @('nodecnt') or @('NODECNT'), etc.) Those are the
 name of the accessor functions for the object.  The corresponding update
 functions are named @('update-NodeCnt'), @('update-TipCnt') and
 @('update-IntTipsSeen').</p>

 <p>If you do not like the default function names chosen above, there is a
 feature in the @(tsee defstobj) event that allows you to specify other
 names.</p>

 <p>If you want to see the ACL2 definitions of all the functions defined by
 this event, look at @(see stobj-example-1-defuns).</p>

 <p>If, after this event, we evaluate the top-level ``global variable''
 @('counters') in the ACL2 read-eval-print loop we get:</p>

 @({
  ACL2 !>counters
  <counters>
 })

 <p>Note that the value printed is ``@('<counters>')''.  Actually, the value of
 @('counters') in the logic is @('(0 0 NIL)').  But ACL2 always prints
 single-threaded objects in this non-informative way because they are usually
 so big that to do otherwise would be unpleasant.</p>

 <p>Had you tried to evaluate the ``global variable'' @('counters') before
 declaring it a single-threaded object, ACL2 would have complained that it does
 not support global variables.  So a lesson here is that once you have declared
 a new single-threaded object your top-level forms can reference it.  In
 versions of ACL2 prior to Version 2.4 the only variable enjoying this status
 was @('STATE').  single-threaded objects are a straightforward generalization
 of the long-implemented von Neumann @(tsee state) feature of ACL2.</p>

 <p>We can access the fields of @('counters') as with:</p>

 @({
  ACL2 !>(NodeCnt counters)
  0
  ACL2 !>(IntTipsSeen counters)
  NIL
 })

 <p>and we can set the fields of @('counters') as with:</p>

 @({
  ACL2 !>(update-NodeCnt 3 counters)
  <counters>
  ACL2 !>(NodeCnt counters)
  3
 })

 <p>Observe that when we evaluate an expression that returns a counter object,
 that object becomes the ``current value'' of @('counters').</p>

 <p>Here is a function that ``converts'' the @('counters') object to its
 ``ordinary'' representation:</p>

 @({
  (defun show-counters (counters)
    (declare (xargs :stobjs (counters)))
    (list (NodeCnt counters)
          (TipCnt counters)
          (IntTipsSeen counters)))
 })

 <p>Observe that we <i>must</i> declare, at the top of the @('defun'), that we
 mean to use the formal parameter @('counters') as a single-threaded object!
 If we did not make this declaration, the body of @('show-counters') would be
 processed as though @('counters') were an ordinary object.  An error would be
 caused because the accessors used above cannot be applied to anything but the
 single-threaded object @('counters').  If you want to know why we insist on
 this declaration, see @(see declare-stobjs).</p>

 <p>When @('show-counters') is admitted, the following message is printed:</p>

 @({
  Since SHOW-COUNTERS is non-recursive, its admission is trivial.  We
  observe that the type of SHOW-COUNTERS is described by the theorem
  (AND (CONSP (SHOW-COUNTERS COUNTERS))
       (TRUE-LISTP (SHOW-COUNTERS COUNTERS))).
  We used primitive type reasoning.

  (SHOW-COUNTERS COUNTERS) => *.

  The guard conjecture for SHOW-COUNTERS is trivial to prove.
  SHOW-COUNTERS is compliant with Common Lisp.
 })

 <p>The line above containing the ``=&gt;'' is called the ``signature'' of
 @('show-counters'); it conveys the information that the first argument is the
 single-threaded object @('counters') and the only result is an ordinary
 object.  Here is an example of another signature:</p>

 @({
  (PROCESSOR * * COUNTERS) => (MV * COUNTERS)
 })

 <p>which indicates that the function @('PROCESSOR') (which we haven't shown
 you) takes three arguments, the third of which is the @('COUNTERS') stobj, and
 returns two results, the second of which is the modified @('COUNTERS').</p>

 <p>Returning to the admission of @('show-counters') above, the last sentence
 printed indicates that the @(tsee guard) conjectures for the function were
 proved.  When some argument of a function is declared to be a single-threaded
 object via the @('xargs') @(':stobj'), we automatically add (conjoin) to the
 guard the condition that the argument satisfy the recognizer for that
 single-threaded object.  In the case of @('show-counters') the guard is
 @('(countersp counters)').</p>

 <p>Here is an example of @('show-counters') being called:</p>

 @({
  ACL2 !>(show-counters counters)
  (3 0 NIL)
 })

 <p>This is what we would see had we set the @('NodeCnt') field of the initial
 value of @('counters') to @('3'), as we did earlier in this example.</p>

 <p>We next wish to define a function to reset the @('counters') object.  We
 could define it this way:</p>

 @({
  (defun reset-counters (counters)
    (declare (xargs :stobjs (counters)))
    (let ((counters (update-NodeCnt 0 counters)))
      (let ((counters (update-TipCnt 0 counters)))
        (update-IntTipsSeen nil counters))))
 })

 <p>which ``successively'' sets the @('NodeCnt') field to @('0'), then the
 @('TipCnt') field to @('0'), and then the @('IntTipsSeen') field to @('nil')
 and returns the resulting object.</p>

 <p>However, the nest of @('let') expressions is tedious and we use this
 definition instead.  This definition exploits a macro, here named ``@('seq')''
 (for ``sequentially'') which evaluates each of the forms given, binding their
 results successively to the stobj name given.</p>

 @({
  (defun reset-counters (counters)
    (declare (xargs :stobjs (counters)))
    (seq counters
         (update-NodeCnt 0 counters)
         (update-TipCnt 0 counters)
         (update-IntTipsSeen nil counters)))
 })

 <p>This definition is syntactically identical to the one above, after macro
 expansion.  Our definition of @('seq') is shown below and is not part of
 native ACL2.</p>

 @({
  (defmacro seq (stobj &rest rst)
    (cond ((endp rst) stobj)
          ((endp (cdr rst)) (car rst))
          (t `(let ((,stobj ,(car rst)))
               (seq ,stobj ,@(cdr rst))))))
 })

 <p>The signature printed for @('reset-counters') is</p>

 @({
  (RESET-COUNTERS COUNTERS) => COUNTERS.
 })

 <p>Here is an example.</p>

 @({
  ACL2 !>(show-counters counters)
  (3 0 NIL)
  ACL2 !>(reset-counters counters)
  <counters>
  ACL2 !>(show-counters counters)
  (0 0 NIL)
 })

 <p>Here finally is a function that uses @('counters') as a single-threaded
 accumulator to collect the desired information about the tree @('x').</p>

 @({
  (defun sweep-tree (x counters)
    (declare (xargs :stobjs (counters)))
    (cond ((atom x)
           (seq counters
                (update-TipCnt (+ 1 (TipCnt counters)) counters)
                (if (integerp x)
                    (update-IntTipsSeen (cons x (IntTipsSeen counters))
                                    counters)
                  counters)))
          (t (seq counters
                  (update-NodeCnt (+ 1 (NodeCnt counters)) counters)
                  (sweep-tree (car x) counters)
                  (sweep-tree (cdr x) counters)))))
 })

 <p>We can paraphrase this definition as follows.  If @('x') is an atom, then
 increment the @('TipCnt') field of @('counters') and <i>then</i>, if @('x') is
 an integer, add @('x') to the @('IntTipsSeen') field, and return
 @('counters').  On the other hand, if @('x') is not an atom, then increment
 the @('NodeCnt') field of @('counters'), and <i>then</i> sweep the @('car') of
 @('x') and <i>then</i> sweep the @('cdr') of @('x') and return the result.</p>

 <p>Here is an example of its execution.  We have displayed the input tree in
 full dot notation so that the number of interior nodes is just the number of
 dots.</p>

 @({
  ACL2 !>(sweep-tree '((((a . 1) . (2 . b)) . 3)
                       . (4 . (5 . d)))
                     counters)
  <counters>
  ACL2 !>(show-counters counters)
  (7 8 (5 4 3 2 1))
  ACL2 !>(reset-counters counters)
  <counters>
  ACL2 !>(show-counters counters)
  (0 0 NIL)
 })

 <p>The @('counters') object has two integer fields and a field whose type is
 unrestricted.  single-threaded objects support other types of fields, such as
 arrays.  We deal with that in the @(see stobj-example-2).  But we recommend
 that you first consider the implementation issues for the @('counters')
 example (in @(see stobj-example-1-implementation)) and then consider the proof
 issues (in @(see stobj-example-1-proofs)).</p>

 <p>To continue the stobj tour, see @(see stobj-example-2).</p>")

(defxdoc stobj-example-1-defuns
  :parents (stobj)
  :short "The defuns created by the @('counters') stobj"
  :long "<p>Consider the event shown in @(see stobj-example-1):</p>

 @({
  (defstobj counters
    (NodeCnt     :type integer :initially 0)
    (TipCnt      :type integer :initially 0)
    (IntTipsSeen :type t       :initially nil))
 })

 <p>Here is a complete list of the defuns added by the event.</p>

 <p>The careful reader will note that the @('counters') argument below is
 <i>not</i> declared with the @(':stobjs') @('xarg') even though we insist that
 the argument be a stobj in calls of these functions.  This ``mystery'' is
 explained below.</p>

 @({
  (defun NodeCntp (x)                 ;;; Recognizer for 1st field
    (declare (xargs :guard t :verify-guards t))
    (integerp x))

  (defun TipCntp (x)                  ;;; Recognizer for 2nd field
    (declare (xargs :guard t :verify-guards t))
    (integerp x))

  (defun IntTipsSeenp (x)             ;;; Recognizer for 3rd field
    (declare (xargs :guard t :verify-guards t) (ignore x))
    t)

  (defun countersp (counters)         ;;; Recognizer for object
    (declare (xargs :guard t :verify-guards t))
    (and (true-listp counters)
         (= (length counters) 3)
         (NodeCntp (nth 0 counters))
         (TipCntp (nth 1 counters))
         (IntTipsSeenp (nth 2 counters))
         t))

  (defun create-counters ()           ;;; Creator for object
    (declare (xargs :guard t :verify-guards t))
    (list '0 '0 'nil))

  (defun NodeCnt (counters)           ;;; Accessor for 1st field
    (declare (xargs :guard (countersp counters) :verify-guards t))
    (nth 0 counters))

  (defun update-NodeCnt (v counters)  ;;; Updater for 1st field
    (declare (xargs :guard
                    (and (integerp v)
                         (countersp counters))
                    :verify-guards t))
    (update-nth 0 v counters))

  (defun TipCnt (counters)            ;;; Accessor for 2nd field
    (declare (xargs :guard (countersp counters) :verify-guards t))
    (nth 1 counters))

  (defun update-TipCnt (v counters)   ;;; Updater for 2nd field
    (declare (xargs :guard
                    (and (integerp v)
                         (countersp counters))
                    :verify-guards t))
    (update-nth 1 v counters))

  (defun IntTipsSeen (counters)       ;;; Accessor for 3rd field
    (declare (xargs :guard (countersp counters) :verify-guards t))
    (nth 2 counters))

  (defun update-IntTipsSeen (v counters) ;;; Updater for 3rd field
    (declare (xargs :guard (countersp counters) :verify-guards t))
    (update-nth 2 v counters))
 })

 <p>Observe that there is a recognizer for each of the three fields and then a
 recognizer for the @('counters') object itself.  Then, for each field, there
 is an accessor and an updater.</p>

 <p>Observe also that the functions are guarded so that they expect a
 @('countersp') for their @('counters') argument and an appropriate value for
 the new field values.</p>

 <p>You can see all of the @('defuns') added by a @('defstobj') event by
 executing the event and then using the @(':pcb!') command on the stobj name.
 E.g.,</p>

 @({
  ACL2 !>:pcb! counters
 })

 <p>will print the defuns above.</p>

 <p>We now clear up the ``mystery'' mentioned above.  Note, for example in
 @('TipCnt'), that the formal @('counters') is used.  From the discussion in
 @(see stobj-example-1) it has been made clear that @('TipCnt') can only be
 called on the @('counters') object.  And yet, in that same discussion it was
 said that an argument is so treated only if it it declared among the
 @(':stobjs') in the definition of the function.  So why doesn't @('TipCnt')
 include something like @('(declare (xargs :stobjs (counters)))')?</p>

 <p>The explanation of this mystery is as follows.  At the time @('TipCnt') was
 defined, during the introduction of the @('counters') stobj, the name
 ``@('counters')'' was not yet a single-threaded object.  The introduction of a
 new single-threaded object occurs in three steps: (1) The new primitive
 recognizers, accessors, and updaters are introduced as ``ordinary functions,''
 producing their logical axiomatizations.  (2) The executable-counterparts are
 defined in raw Lisp to support destructive updating.  (3) The new name is
 declared a single-threaded object to ensure that all future use of these
 primitives respects the single-threadedness of the object.  The functions
 defined as part of the introduction of a new single-threaded object are the
 only functions in the system that have undeclared stobj formals other than
 @('state').</p>

 <p>You may return to @(see stobj-example-1) here.</p>")

(defxdoc stobj-example-1-implementation
  :parents (stobj)
  :short "The implementation of the @('counters') stobj"
  :long "<p>the event</p>

 @({
  (defstobj counters
    (NodeCnt     :type integer :initially 0)
    (TipCnt      :type integer :initially 0)
    (IntTipsSeen :type t       :initially nil))
 })

 <p>discussed in @(see stobj-example-1), creates a Common Lisp object to
 represent the current value of @('counters').  That object is created by
 evaluating either of the following ``raw'' (non-ACL2) Common Lisp forms:</p>

 @({
  (create-counters)

  (vector (make-array 1 :element-type 'integer
                        :initial-element '0)
          (make-array 1 :element-type 'integer
                        :initial-element '0)
          'nil)
 })

 <p>and the value is stored in the Common Lisp global variable named
 @('*the-live-counters*').</p>

 <p>Thus, the @('counters') object is an array of length three.  The first two
 elements are arrays of size 1 and are used to hold the @('NodeCnt') and
 @('TipCnt') fields.  The third element is the @('IntTipsSeen') field.  The
 first two fields are represented by arrays so that we can implement the
 @('integer') type specification efficiently.  Generally, integers are
 ``boxed'' in some Common Lisp implementations, for example, GCL.  Creating a
 new integer requires creating a new box to put it in.  But in some lisps,
 including GCL, the integers inside arrays of integers are not boxed.</p>

 <p>The function @('NodeCnt') is defined in raw Lisp as:</p>

 @({
  (defun NodeCnt (counters)
    (the integer
         (aref (the (simple-array integer (1))
                    (svref counters 0))
               0)))
 })

 <p>Observe that the form @('(svref counters 0)') is evaluated to get an array
 of size 1, which is followed by a call of @('aref') to access the 0th element
 of that array.</p>

 <p>The function @('update-NodeCnt') is defined in raw Lisp as:</p>

 @({
  (defun update-NodeCnt (v counters)
    (declare (type integer v))
    (progn
     (setf (aref (the (simple-array integer (1))
                      (svref counters 0))
                 0)
           (the integer v))
     counters))
 })

 <p>Note that when this function is called, it does not create a new vector of
 length three, but ``smashes'' the existing one.</p>

 <p>One way to see all the raw Lisp functions defined by a given @('defstobj')
 is to evaluate the @('defstobj') event and then evaluate, in the ACL2 loop,
 the expression @('(nth 4 (global-val 'cltl-command (w state)))').  Those
 functions that contain @('(DECLARE (STOBJ-INLINE-FN T))') will generate @(tsee
 defabbrev) forms because the @(':inline') keyword of @(tsee defstobj) was
 supplied the value @('t').  The rest will generate @(tsee defun)s.</p>

 <p>We now recommend that you look at @(see stobj-example-1-proofs).</p>")

(defxdoc stobj-example-1-proofs
  :parents (stobj)
  :short "Some proofs involving the @('counters') stobj"
  :long "<p>Consider again the event</p>

 @({
  (defstobj counters
    (NodeCnt     :type integer :initially 0)
    (TipCnt      :type integer :initially 0)
    (IntTipsSeen :type t       :initially nil))
 })

 <p>discussed in @(see stobj-example-1), followed by the definition</p>

 @({
  (defun reset-counters (counters)
    (declare (xargs :stobjs (counters)))
    (seq counters
         (update-NodeCnt 0 counters)
         (update-TipCnt 0 counters)
         (update-IntTipsSeen nil counters)))
 })

 <p>which, because of the @('seq') macro in @(see stobj-example-1), is just
 syntactic sugar for</p>

 @({
  (defun reset-counters (counters)
    (declare (xargs :stobjs (counters)))
    (let ((counters (update-NodeCnt 0 counters)))
      (let ((counters (update-TipCnt 0 counters)))
        (update-IntTipsSeen nil counters)))).
 })

 <p>Here is a simple theorem about @('reset-counters').</p>

 @({
  (defthm reset-counters-is-constant
    (implies (countersp x)
             (equal (reset-counters x)
                    '(0 0 nil))))
 })

 <p>Before we talk about how to prove this theorem, note that the theorem is
 unusual in two respects.</p>

 <p>First, it calls @('reset-counters') on an argument other than the variable
 @('counters')!  That is allowed in theorems; logically speaking, the stobj
 functions are indistinguishable from ordinary functions.  Their use is
 syntactically restricted only in @('defun')s, which might be compiled and run
 in raw Lisp.  Those restrictions allow us to implement stobj modification
 destructively.  But logically speaking, @('reset-counters') and other stobj
 ``modifying'' functions just create new objects, constructively.</p>

 <p>Second, the theorem above explicitly provides the hypothesis that
 @('reset-counters') is being applied to an object satisfying @('countersp').
 Such a hypothesis is not always required: @('reset-counters') is total and
 will do something no matter what @('x') is.  But in this particular case, the
 result is not @(''(0 0 nil)') unless @('x') is, at least, a true-list of
 length three.</p>

 <p>To make a long story short, to prove theorems about stobj functions you
 behave in exactly the way you would to prove the same theorems about the same
 functions defined without the stobj features.</p>

 <p>How can we prove the above theorem?  Unfolding the definition of
 @('reset-counters') shows that @('(reset-counters x)') is equal to</p>

 @({
  (update-IntTipsSeen nil
    (update-TipCnt 0
      (update-NodeCnt 0 x)))
 })

 <p>which in turn is</p>

 @({
  (update-nth 2 nil
   (update-nth 1 0
    (update-nth 0 0 x))).
 })

 <p>Opening up the definition of @('update-nth') reduces this to</p>

 @({
  (list* 0 0 nil (cdddr x)).
 })

 <p>This is clearly equal to @(''(0 0 nil)'), provided we know that @('(cdddr
 x)') is @('nil').</p>

 <p>Unfortunately, that last fact requires a lemma.  The most specific lemma we
 could provide is</p>

 @({
  (defthm special-lemma-for-counters
    (implies (countersp x)
             (equal (cdddr x) nil)))
 })

 <p>but if you try to prove that lemma you will find that it requires some
 reasoning about @('len') and @('true-listp').  Furthermore, the special lemma
 above is of interest only for @('counters').</p>

 <p>The following lemma about @('len') is the one we prefer.</p>

 @({
  (defthm equal-len-n
    (implies (syntaxp (quotep n))
             (equal (equal (len x) n)
                    (if (integerp n)
                        (if (< n 0)
                            nil
                          (if (equal n 0)
                              (atom x)
                            (and (consp x)
                                 (equal (len (cdr x)) (- n 1)))))
                      nil))))
 })

 <p>This lemma will simplify any equality in which a @('len') expression is
 equated to any explicitly given constant <i>n</i>, e.g., @('3'), reducing the
 equation to a conjunction of @('consp') terms about the first <i>n</i>
 @('cdr')s.</p>

 <p>If the above lemma is available then ACL2 immediately proves</p>

 @({
  (defthm reset-counters-is-constant
    (implies (countersp x)
             (equal (reset-counters x)
                    '(0 0 nil))))
 })

 <p>The point is presumably well made: proving theorems about single-threaded
 object accessors and updaters is no different than proving theorems about
 other recursively defined functions on lists.</p>

 <p>As we have seen, operations on @(see stobj)s turn into definitions
 involving @(tsee nth) and @(tsee update-nth) in the logic.  Here are two
 lemmas, both due to Matt Wilding, that are useful for simplifying terms
 involving @('nth') and @('update-nth'), which are therefore useful in
 reasoning about single-threaded objects.</p>

 @({
  (defthm update-nth-update-nth-same
    (implies (equal (nfix i1) (nfix i2))
             (equal (update-nth i1 v1 (update-nth i2 v2 l))
                    (update-nth i1 v1 l))))

  (defthm update-nth-update-nth-diff
    (implies (not (equal (nfix i1) (nfix i2)))
             (equal (update-nth i1 v1 (update-nth i2 v2 l))
                    (update-nth i2 v2 (update-nth i1 v1 l))))
    :rule-classes ((:rewrite :loop-stopper ((i1 i2)))))
 })

 <p>We now recommend that you see @(see stobj-example-2).</p>")

(defxdoc stobj-example-2
  :parents (stobj)
  :short "An example of the use of arrays in single-threaded objects"
  :long "<p>The following event</p>

 @({
  (defstobj ms
    (pcn  :type integer                  :initially 0)
    (mem  :type (array integer (100000)) :initially -1)
    (code :type t                        :initially nil))
 })

 <p>introduces a single-threaded object named @('ms') (which stands for
 ``machine state'').  The object has three fields, a @('pcn') or program
 counter, a @('mem') or memory, and a @('code') field.</p>

 <p>The @('mem') field is occupied by an object initially of type @('(array
 integer (100000))').  Logically speaking, this is a list of length
 @('100000'), each element of which is an integer.  But in the underlying
 implementation of the @('ms') object, this field is occupied by a raw Lisp
 array, initially of size 100000.</p>

 <p>You might expect the above @('defstobj') to define the accessor function
 @('mem') and the updater @('update-mem').  <i>That does not happen!</i>.</p>

 <p>The above event defines the accessor function @('memi') and the updater
 @('update-memi').  These functions do not access/update the @('mem') field of
 the @('ms') object; they access/update the individual elements of the array in
 that field.</p>

 <p>In particular, the logical definitions of the two functions are:</p>

 @({
  (defun memi (i ms)
    (declare (xargs :guard
                    (and (msp ms)
                         (integerp i)
                         (<= 0 i)
                         (< i (mem-length ms)))))
    (nth i (nth 1 ms)))

  (defun update-memi (i v ms)
    (declare (xargs :guard
                    (and (msp ms)
                         (integerp i)
                         (<= 0 i)
                         (< i (mem-length ms))
                         (integerp v))))
    (update-nth-array 1 i v ms))
 })

 <p>For example, to access the 511th (0-based) memory location of the current
 @('ms') you could evaluate:</p>

 @({
  ACL2 !>(memi 511 ms)
  -1
 })

 <p>The answer is @('-1') initially, because that is the above-specified
 initial value of the elements of the @('mem') array.</p>

 <p>To set that element you could do</p>

 @({
  ACL2 !>(update-memi 511 777 ms)
  <ms>
  ACL2 !>(memi 511 ms)
  777
 })

 <p>The raw Lisp implementing these two functions is shown below.</p>

 @({
  (defun memi (i ms)
    (declare (type (and fixnum (integer 0 *)) i))
    (the integer
         (aref (the (simple-array integer (*))
                    (svref ms 1))
               (the (and fixnum (integer 0 *)) i))))

  (defun update-memi (i v ms)
    (declare (type (and fixnum (integer 0 *)) i)
             (type integer v))
    (progn
     (setf (aref (the (simple-array integer (*))
                      (svref ms 1))
                 (the (and fixnum (integer 0 *)) i))
           (the integer v))
     ms))
 })

 <p>If you want to see the raw Lisp supporting a @('defstobj'), execute the
 @('defstobj') and then evaluate the ACL2 form @('(nth 4 (global-val
 'cltl-command (w state)))').</p>

 <p>To continue the stobj tour, see @(see stobj-example-3).</p>")

(defxdoc stobj-example-3
  :parents (stobj)
  :short "Another example of a single-threaded object"
  :long "<p>The event</p>

 @({
  (defstobj $s
    (x :type integer :initially 0)
    (a :type (array (integer 0 9) (3)) :initially 9 :resizable t))
 })

 <p>introduces a stobj named @('$S').  The stobj has two fields, @('X') and
 @('A').  The @('A') field is an array.  The @('X') field contains an integer
 and is initially 0.  The @('A') field contains a list of integers, each
 between 0 and 9, inclusively.  (Under the hood, this ``list'' is actually
 implemented as an array.)  Initially, the @('A') field has three elements,
 each of which is 9.</p>

 <p>This event introduces the following sequence of function definitions:</p>

 @({
  (DEFUN XP (X) ...)               ; recognizer for X field
  (DEFUN AP (X) ...)               ; recognizer of A field
  (DEFUN $SP ($S) ...)             ; top-level recognizer for stobj $S
  (DEFUN CREATE-$S NIL ...)        ; creator for stobj $S
  (DEFUN X ($S) ...)               ; accessor for X field
  (DEFUN UPDATE-X (V $S) ...)      ; updater for X field
  (DEFUN A-LENGTH ($S) ...)        ; length of A field
  (DEFUN RESIZE-A (K $S) ...)      ; resizer for A field
  (DEFUN AI (I $S) ...)            ; accessor for A field at index I
  (DEFUN UPDATE-AI (I V $S) ...)   ; updater for A field at index I
 })

 <p>Here is the definition of @('$SP'):</p>

 @({
  (DEFUN $SP ($S)
    (DECLARE (XARGS :GUARD T :VERIFY-GUARDS T))
    (AND (TRUE-LISTP $S)
         (= (LENGTH $S) 2)
         (XP (NTH 0 $S))
         (AP (NTH 1 $S))
         T))
 })

 <p>This reveals that in order to satisfy @('$SP') an object must be a true
 list of length 2 whose first element satisfies @('XP') and whose second
 satisfies @('AP').  By printing the definition of @('AP') one learns that it
 requires its argument to be a true list, each element of which is an integer
 between 0 and 9.</p>

 <p>The initial value of stobj @('$S') is given by zero-ary ``creator''
 function @('CREATE-$S').  Creator functions may only be used in limited
 contexts.  See @(see with-local-stobj).</p>

 <p>Here is the definition of @('UPDATE-AI'), the updater for the @('A') field
 at index @('I'):</p>

 @({
  (DEFUN UPDATE-AI (I V $S)
    (DECLARE (XARGS :GUARD
                    (AND ($SP $S)
                         (INTEGERP I)
                         (<= 0 I)
                         (< I (A-LENGTH $S))
                         (AND (INTEGERP V) (<= 0 V) (<= V 9)))
                    :VERIFY-GUARDS T))
    (UPDATE-NTH-ARRAY 1 I V $S))
 })

 <p>By definition @('(UPDATE-NTH-ARRAY 1 I V $S)') is @('(UPDATE-NTH 1
 (UPDATE-NTH I V (NTH 1 $S)) $S)').  This may be a little surprising but should
 be perfectly clear.</p>

 <p>First, ignore the guard, since it is irrelevant in the logic.  Reading from
 the inside out, @('(UPDATE-AI I V $S)') extracts @('(NTH 1 $S)'), which is
 array @('a') of @('$S').  (Recall that @(tsee NTH) is 0-based.)  The next
 higher expression in the definition above, @('(UPDATE-NTH I V a)'),
 ``modifies'' @('a') by setting its @('I')th element to @('V').  Call this
 @('a'').  The next higher expression, @('(UPDATE-NTH 1 a' $S)'), ``modifies''
 @('$S') by setting its 1st component to @('a'').  Call this result @('$s'').
 Then @('$s'') is the result returned by @('UPDATE-AI').</p>

 <p>So the first useful observation is that from the perspective of the logic,
 the type ``restrictions'' on stobjs are irrelevant.  They are ``enforced'' by
 ACL2's guard mechanism, not by the definitions of the updater functions.</p>

 <p>As one might also imagine, the accessor functions do not really ``care,''
 logically, whether they are applied to well-formed stobjs or not.  For
 example, @('(AI I $S)') is defined to be @('(NTH I (NTH 1 $S))').</p>

 <p>Thus, you will not be able to prove that (AI 2 $S) is an integer.  That
 is,</p>

 @({
  (integerp (AI 2 $S))
 })

 <p>is not a theorem, because @('$S') may not be well-formed.</p>

 <p>Now @('(integerp (AI 2 $S))') will always evaluate to @('T') in the
 top-level ACL2 command loop, because we insist that the current value of the
 stobj @('$S') always satisfies @('$SP') by enforcing the guards on the
 updaters, independent of whether guard checking is on or off; see @(see
 set-guard-checking).  But in a theorem @('$S') is just another variable,
 implicitly universally quantified.</p>

 <p>So @('(integerp (AI 2 $S))') is not a theorem because it is not true when
 the variable @('$S') is instantiated with, say,</p>

 @({
  '(1 (0 1 TWO))
 })

 <p>because, logically speaking, @('(AI 2 '(1 (0 1 TWO)))') evaluates to the
 symbol @('TWO').  That is,</p>

 @({
  (equal (AI 2 '(1 (0 1 TWO))) 'TWO)
 })

 <p>is true.</p>

 <p>However,</p>

 @({
  (implies (and ($SP $S) (< 2 (A-LENGTH $S))) (integerp (AI 2 $S)))
 })

 <p>is a theorem.  To prove it, you will have to prove a lemma about @('AP').
 The following will do:</p>

 @({
  (defthm ap-nth
    (implies (and (AP x)
                  (integerp i)
                  (<= 0 i)
                  (< i (len x)))
             (integerp (nth i x)))).
 })

 <p>Similarly,</p>

 @({
  (implies (and (integerp i)
                (<= 0 i)
                (< i (A-LENGTH $S))
                (integerp v)
                (<= 0 v)
                (<= v 9))
           ($SP (UPDATE-AI i v $S)))
 })

 <p>is not a theorem until you add the additional hypothesis @('($SP $S)').  To
 prove the resulting theorem, you will need a lemma such as the following.</p>

 @({
  (defthm ap-update-nth
    (implies (and (AP a)
                  (integerp v)
                  (<= 0 v)
                  (<= v 9)
                  (integerp i)
                  (<= 0 i)
                  (< i (len a)))
             (AP (update-nth i v a))))
 })

 <p>The moral here is that from the logical perspective, you must provide the
 hypotheses that, as a programmer, you think are implicit on the structure of
 your stobjs, and you must prove their invariance.  This is a good area for
 further support, perhaps in the form of a library of macros.</p>

 <p><i>Resizing Array Fields</i></p>

 <p>Recall the specification of the array field, @('A') for the stobj @('$S')
 introduced above:</p>

 @({
  (a :type (array (integer 0 9) (3)) :initially 9 :resizable t)
 })

 <p>Logically, this field is a list, initially of length 3.  Under the hood,
 this field is implemented using a Common Lisp array with 3 elements.  In some
 applications, one may wish to lengthen an array field, or even (to reclaim
 space) to shrink an array field.  The @(tsee defstobj) event provides
 functions to access the current length of an array field and to change the
 array field, with default names obtained by suffixing the field name with
 ``@('LENGTH-')'' or prefixing it with ``@('RESIZE-'),'' respectively.  The
 following log shows the uses of these fields in the above example.</p>

 @({
  ACL2 !>(A-LENGTH $S)
  3
  ACL2 !>(RESIZE-A 10 $S) ; change length of A to 10
  <$s>
  ACL2 !>(A-LENGTH $S)
  10
  ACL2 !>(AI 7 $S)        ; new elements get value from :initially
  9
  ACL2 !>(RESIZE-A 2 $S)  ; truncate A down to first 2 elements
  <$s>
  ACL2 !>(A-LENGTH $S)
  2
  ACL2 !>(AI 7 $S)        ; error:  access past array bound

  ACL2 Error in TOP-LEVEL:  The guard for the function symbol AI, which
  is (AND ($SP $S) (INTEGERP I) (<= 0 I) (< I (A-LENGTH $S))), is violated
  by the arguments in the call (AI 7 $S).

  ACL2 !>
 })

 <p>Here are the definitions of the relevant functions for the above example;
 also see @(see resize-list).</p>

 @({
  (DEFUN A-LENGTH ($S)
    (DECLARE (XARGS :GUARD ($SP $S) :VERIFY-GUARDS T))
    (LEN (NTH 1 $S)))

  (DEFUN RESIZE-A (K $S)
    (DECLARE (XARGS :GUARD ($SP $S) :VERIFY-GUARDS T))
    (UPDATE-NTH 1
                (RESIZE-LIST (NTH 1 $S) K 9)
                $S))
 })

 <p>It is important to note that the implementation of array resizing in ACL2
 involves copying the entire array into a newly allocated space and thus can be
 quite costly if performed often.  This approach was chosen in order to make
 array access and update as efficient as possible, with the suspicion that for
 most applications, array access and update are considerably more frequent than
 resizing (especially if the programmer is aware of the relative costs
 beforehand).</p>

 <p>It should also be noted that computations of lengths of stobj array fields
 should be fast (constant-time) in all or most Common Lisp implementations.</p>

 <p>Finally, if @(':resizable t') is not supplied as shown above, then an
 attempt to resize the array will result in an error.  If you do not intend to
 resize the array, it is better to omit the @(':resizable') option (or to
 supply @(':resizable nil')), since then the length function will be defined to
 return a constant, namely the initial length, which can simplify guard proofs
 (compare with the definition of @('A-LENGTH') above).</p>

 <p>This completes the tour through the documentation of @(see stobj)s.
 However, you may now wish to read the documentation for the event that
 introduces a new single-threaded object; see @(see defstobj).</p>")

(defxdoc stop-proof-tree
  :parents (proof-tree)
  :short "Stop displaying proof trees during proofs"
  :long "<p>Also see @(see proof-tree) and see @(see start-proof-tree).  Note
 that @(':stop-proof-tree') works by adding @(''')@(tsee proof-tree) to the
 @('inhibit-output-lst'); see @(see set-inhibit-output-lst).</p>

 <p>Proof tree displays are explained in the documentation for @(see
 proof-tree).  @(':Stop-proof-tree') causes proof tree display to be turned
 off.</p>

 <p>It is permissible to submit the form @('(stop-proof-tree)') during a break.
 Thus, you can actually turn off proof tree display in the middle of a proof by
 interrupting ACL2 and submitting the form @('(stop-proof-tree)') in raw
 Lisp.</p>")

(defxdoc string
  :parents (strings acl2-built-ins)
  :short "@(see coerce) to a string"
  :long "<p>@('(String x)') @(see coerce)s @('x') to a string.</p>

 <p>The @(see guard) for @('string') requires its argument to be a string, a
 symbol, or a character.</p>

 <ul>
 <li>If @('x') is already a string, then it is returned unchanged.</li>
 <li>If @('x') is a symbol, then its @(tsee symbol-name) is returned.</li>
 <li>If @('x') is a character, the corresponding one-character string is returned.</li>
 </ul>

 <p>Note: this is a rather low-level operation that doesn't support coercing
 numbers or conses into strings.  If you want to turn numbers into strings, see
 functions such as @(see str::natstr), or more generally the @(see
 str::numbers) functions.  For conses, see the @(see str::pretty-printing)
 routines such as @(see str::pretty).</p>

 <p>@('String') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def string)")

(defxdoc string-append
  :parents (strings acl2-built-ins)
  :short "@(see concatenate) two strings"
  :long "<p>@('String-append') takes two arguments, which are both strings (if
 the @(see guard) is to be met), and returns a string obtained by concatenating
 together the @(see characters) in the first string followed by those in the
 second.  Also see @(see concatenate), noting that the macro call</p>

 @({
  (concatenate 'string str1 str2).
 })

 <p>expands to the call</p>

 @({
  (string-append str1 str2).
 })

 @(def string-append)")

(defxdoc string-downcase
  :parents (strings acl2-built-ins)
  :short "In a given string, turn upper-case @(see characters) into lower-case"
  :long "<p>For a string @('x'), @('(string-downcase x)') is the result of
 applying @(tsee char-downcase) to each character in @('x').</p>

 <p>The @(see guard) for @('string-downcase') requires its argument to be a
 string containing only standard characters.</p>

 <p>@('String-downcase') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def string-downcase)")

(defxdoc string-equal
  :parents (strings acl2-built-ins)
  :short "String equality without regard to case"
  :long "<p>For strings @('str1') and @('str2'), @('(string-equal str1 str2)')
 is true if and only @('str1') and @('str2') are the same except perhaps for
 the cases of their @(see characters).</p>

 <p>The @(see guard) on @('string-equal') requires that its arguments are
 strings consisting of standard characters (see @(see
 standard-char-listp)).</p>

 <p>@('String-equal') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def string-equal)")

(defxdoc string-listp
  :parents (strings lists acl2-built-ins)
  :short "Recognizer for a true list of strings"
  :long "<p>The predicate @('string-listp') tests whether its argument is a
 @(tsee true-listp) of strings.</p>

 @(def string-listp)")

(defxdoc string-upcase
  :parents (strings acl2-built-ins)
  :short "In a given string, turn lower-case @(see characters) into upper-case"
  :long "<p>For a string @('x'), @('(string-upcase x)') is the result of
 applying @(tsee char-upcase) to each character in @('x').</p>

 <p>The @(see guard) for @('string-upcase') requires its argument to be a
 string containing only standard characters.</p>

 <p>@('String-upcase') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def string-upcase)")

(defxdoc string<
  :parents (strings acl2-built-ins)
  :short "Less-than test for strings"
  :long "<p>@('(String< str1 str2)') is non-@('nil') if and only if the string
 @('str1') precedes the string @('str2') lexicographically, where character
 inequalities are tested using @(tsee char<).  When non-@('nil'), @('(string<
 str1 str2)') is the first position (zero-based) at which the strings differ.
 Here are some examples.</p>

 @({
  ACL2 !>(string< \"abcd\" \"abu\")
  2
  ACL2 !>(string< \"abcd\" \"Abu\")
  NIL
  ACL2 !>(string< \"abc\" \"abcde\")
  3
  ACL2 !>(string< \"abcde\" \"abc\")
  NIL
 })

 <p>The @(see guard) for @('string<') specifies that its arguments are
 strings.</p>

 <p>@('String<') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def string<)")

(defxdoc string<=
  :parents (strings acl2-built-ins)
  :short "Less-than-or-equal test for strings"
  :long "<p>@('(String<= str1 str2)') is non-@('nil') if and only if the string
 @('str1') precedes the string @('str2') lexicographically or the strings are
 equal.  When non-@('nil'), @('(string<= str1 str2)') is the first
 position (zero-based) at which the strings differ, if they differ, and
 otherwise is their common length.  See @(see string<).</p>

 <p>The @(see guard) for @('string<=') specifies that its arguments are
 strings.</p>

 <p>@('String<=') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def string<=)")

(defxdoc string>
  :parents (strings acl2-built-ins)
  :short "Greater-than test for strings"
  :long "<p>@('(String> str1 str2)') is non-@('nil') if and only if @('str2')
 precedes @('str1') lexicographically.  When non-@('nil'), @('(string> str1
 str2)') is the first position (zero-based) at which the strings differ.  See
 @(see string<).</p>

 <p>@('String>') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def string>)")

(defxdoc string>=
  :parents (strings acl2-built-ins)
  :short "Less-than-or-equal test for strings"
  :long "<p>@('(String>= str1 str2)') is non-@('nil') if and only if the string
 @('str2') precedes the string @('str1') lexicographically or the strings are
 equal.  When non-@('nil'), @('(string>= str1 str2)') is the first
 position (zero-based) at which the strings differ, if they differ, and
 otherwise is their common length.  See @(see string>).</p>

 <p>The @(see guard) for @('string>=') specifies that its arguments are
 strings.</p>

 <p>@('String>=') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def string>=)")

(defxdoc stringp
  :parents (strings acl2-built-ins)
  :short "Recognizer for strings"
  :long "<p>@('(stringp x)') is true if and only if @('x') is a string.</p>")

(defxdoc strings
  :parents (programming)
  :short "Strings are atomic objects that contain character sequences,
 like @('\"Hello World\"')."
  :long "<p>See the @(see std/strings) library for many additional string
 functions and lemmas about the built-in string functions.</p>")

(defxdoc strip-cars
  :parents (alists acl2-built-ins)
  :short "Collect up all first components of pairs in a list"
  :long "<p>@('(strip-cars x)') is the list obtained by walking through the
 list @('x') and collecting up all first components (@(tsee car)s).  This
 function is implemented in a tail-recursive way, despite its logical
 definition.</p>

 <p>@('(strip-cars x)') has a @(see guard) of @('(alistp x)').</p>

 @(def strip-cars)")

(defxdoc strip-cdrs
  :parents (alists acl2-built-ins)
  :short "Collect up all second components of pairs in a list"
  :long "<p>@('(strip-cdrs x)') has a @(see guard) of @('(alistp x)'), and
 returns the list obtained by walking through the list @('x') and collecting up
 all second components (@(tsee cdr)s).  This function is implemented in a
 tail-recursive way, despite its logical definition.</p>

 @(def strip-cdrs)")

(defxdoc strong-rewrite-rules
  :parents (introduction-to-the-theorem-prover)
  :short "Formulating good rewrite rules"
  :long "<p>Suppose you notice the following term in a Key Checkpoint:</p>

 @({
  (MEMBER (CAR A) (REV B)).
 })

 <p>You might think of two theorems for handling this term, which we'll call
 the ``weak'' and ``strong'' version of @('member-rev').</p>

 @({
  (defthm member-rev-weak
    (implies (member e b)
             (member e (rev b)))).

  (defthm member-rev-strong
    (iff (member e (rev b))
         (member e b))).
 })

 <p>The ``strong'' version logically implies the ``weak'' version and so
 deserves the adjective.  (Recall that ``<i>p</i> &lt;---&gt; <i>q</i>'' is
 just ``<i>p</i> ---&gt; <i>q</i>'' and ``<i>q</i> ---&gt; <i>p</i>.''  So the
 strong version quite literally says everything the weak version does and then
 some.)</p>

 <p>But the ``strong'' version also produces a <i>better</i> rewrite rule.
 Here are the rules generated from these two formulas, phrased as directives to
 ACL2's simplifier:</p>

 <p>@('member-rev-weak'): If you ever see an instance of @('(MEMBER e (REV
 b))'), backchain to @('(MEMBER e b)') (i.e., turn your attention to that term)
 and if you can show that it is true, replace @('(MEMBER e (REV b))') by
 @('T').</p>

 <p>@('member-rev-strong'): If you ever see an instance of @('(MEMBER e (REV
 b))'), replace it by @('(MEMBER e b)').</p>

 <p>Technical Note: Actually, both rules concern <i>propositional</i>
 occurrences of the ``target'' expression, @('(MEMBER e (REV b))'), i.e.,
 occurrences of the target in which its truth value is the only thing of
 relevance.  (Recall that @('(MEMBER x y)') returns the tail of @('y') starting
 with @('x')!  Evaluate some simple @('MEMBER') expressions, like @('(MEMBER 3
 '(1 2 3 4 5))') to see what we mean.)  Both theorems tell us about
 circumstances in which the target is non-@('NIL') (i.e., ``true'') without
 telling us its identity.  But ACL2 keeps track of when the target is in a
 propositional occurrence and can use such rules to rewrite the target to
 propositionally equivalent terms.</p>

 <p>So the strong version is better because it will always eliminate @('(MEMBER
 e (REV b))') in favor of @('(MEMBER e b)').  That simpler expression may be
 further reduced if the context allows it.  But in any case, the strong version
 eliminates @('REV') from the problem.  The weak version only eliminates
 @('REV') when a side-condition can be proved.</p>

 <p>While either version may permit us to prove the Key Checkpoint that
 ``suggested'' the rule, the strong version is a better rule to have in the
 database going forward.</p>

 <p>For example, suppose @('NATS-BELOW') returns the list of natural numbers
 below its argument.  Imagine two alternative scenarios in which a key
 checkpoint is about to arise involving this term:</p>

 @({
  (MEMBER K (REV (NATS-BELOW J)))
 })

 <p><b>Scenario 1</b> is when you've got the strong version in your database:
 it will rewrite the key checkpoint term to</p>

 @({
  (MEMBER K (NATS-BELOW J))
 })

 <p>and that's what you'll see in the printed checkpoint unless other rules
 reduce it further.</p>

 <p><b>Scenario 2</b> is when you have only the weak version in your database:
 the weak rule will attempt to reduce the term above to @('T') and will, if
 there are sufficient rules and hypotheses about @('K')'s membership in
 @('(NATS-BELOW J)').  But if no such rules or hypotheses are available, you'll
 be confronted with a key checkpoint involving</p>

 @({
  (MEMBER K (REV (NATS-BELOW J)))
 })

 <p>and <i>it will not be obvious</i> that the problem would go away if you
 could establish that @('K') is in @('(NATS-BELOW J)').  Clearly, Scenario 1 is
 better.</p>

 <p>We recommend that you now practice formulating strong versions of rules
 suggested by terms you might see.  See @(see
 practice-formulating-strong-rules).</p>

 <p>When you are finished with that, use your browser's <b>Back Button</b> to
 return to @(see introduction-to-key-checkpoints).</p>")

(defxdoc sublis
  :parents (alists acl2-built-ins)
  :short "Substitute an alist into a tree"
  :long "<p>@('(Sublis alist tree)') is obtained by replacing every leaf of
 @('tree') with the result of looking that leaf up in the association list
 @('alist').  However, a leaf is left unchanged if it is not found as a key in
 @('alist').</p>

 <p>Leaves are looked up using the function @(tsee assoc).  The @(see guard)
 for @('(sublis alist tree)') requires @('(eqlable-alistp alist)').  This @(see
 guard) ensures that the @(see guard) for @(tsee assoc) will be met for each
 lookup generated by @('sublis').</p>

 <p>@('Sublis') is defined in Common Lisp.  See any Common Lisp documentation
 for more information.</p>

 @(def sublis)")

(defxdoc subseq
  :parents (lists strings acl2-built-ins)
  :short "Subsequence of a string or list"
  :long "<p>For any natural numbers @('start') and @('end'), where @('start')
 @('<=') @('end') @('<=') @('(length seq)'), @('(subseq seq start end)') is the
 subsequence of @('seq') from index @('start') up to, but not including, index
 @('end').  @('End') may be @('nil'), in which case it is treated as though it
 is @('(length seq)'), i.e., we obtain the subsequence of @('seq') from index
 @('start') all the way to the end.</p>

 <p>The @(see guard) for @('(subseq seq start end)') is that @('seq') is a true
 list or a string, @('start') and @('end') are integers (except, @('end') may
 be @('nil'), in which case it is treated as @('(length seq)') for the rest of
 this discussion), and @('0') @('<=') @('start') @('<=') @('end') @('<=')
 @('(length seq)').</p>

 <p>@('Subseq') is a Common Lisp function.  See any Common Lisp documentation
 for more information.  Note: In Common Lisp the third argument of @('subseq')
 is optional, but in ACL2 it is required, though it may be @('nil') as
 explained above.</p>

 @(def subseq)")

(defxdoc subsetp
  :parents (lists acl2-built-ins)
  :short "Test if every @(tsee member) of one list is a @(tsee member) of the other"
  :long "@({
  General Forms:
  (subsetp x y)
  (subsetp x y :test 'eql)   ; same as above (eql as equality test)
  (subsetp x y :test 'eq)    ; same, but eq is equality test
  (subsetp x y :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Subsetp x y)') is true if and only if every @(tsee member) of the list
 @('x') is a @('member') of the list @('y').  The optional keyword, @(':TEST'),
 has no effect logically, but provides the test (default @(tsee eql)) used for
 comparing members of the two lists.</p>

 <p>The @(see guard) for a call of @('subsetp') depends on the test.  In all
 cases, both arguments must satisfy @(tsee true-listp).  If the test is @(tsee
 eql), then one of the arguments must satisfy @(tsee eqlable-listp).  If the
 test is @(tsee eq), then one of the arguments must satisfy @(tsee
 symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('subsetp') and its variants:</p>

 <blockquote><p>@('(subsetp-eq x lst)') is equivalent to @('(subsetp x lst
 :test 'eq)');</p>

 <p>@('(subsetp-equal x lst)') is equivalent to @('(subsetp x lst :test
 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('subsetp-equal').</p>

 @(def subsetp-equal)

 <p>@('Subsetp') is defined by Common Lisp.  See any Common Lisp documentation
 for more information.</p>")

(defxdoc subst
  :parents (conses acl2-built-ins)
  :short "A single substitution into a tree"
  :long "<p>@('(Subst new old tree)') is obtained by substituting @('new') for
 every occurrence of @('old') in the given tree.</p>

 <p>Equality to @('old') is determined using the function @(tsee eql).  The
 @(see guard) for @('(subst new old tree)') requires @('(eqlablep old)'), which
 ensures that the @(see guard) for @(tsee eql) will be met for each comparison
 generated by @('subst').</p>

 <p>@('Subst') is defined in Common Lisp.  See any Common Lisp documentation
 for more information.</p>

 @(def subst)")

(defxdoc substitute
  :parents (lists strings acl2-built-ins)
  :short "Substitute into a string or a list, using @(tsee eql) as test"
  :long "<p>@('(Substitute new old seq)') is the result of replacing each
 occurrence of @('old') in @('seq'), which is a list or a string, with
 @('new').</p>

 <p>The guard for @('substitute') requires that either @('seq') is a string and
 @('new') is a character, or else: @('seq') is a @(tsee true-listp) such that
 either all of its members are @(tsee eqlablep) or @('old') is
 @('eqlablep').</p>

 <p>@('Substitute') is a Common Lisp function.  See any Common Lisp
 documentation for more information.  Since ACL2 functions cannot take keyword
 arguments (though macros can), the test used in @('substitute') is
 @('eql').</p>

 @(def substitute)")

(defxdoc subversive-inductions
  :parents (miscellaneous)
  :short "Why we restrict @(see encapsulate)d recursive functions"
  :long "<p>See @(see subversive-recursions).</p>")

(defxdoc subversive-recursions
  :parents (miscellaneous)
  :short "Why we restrict @(see encapsulate)d recursive functions"
  :long "<p>Subtleties arise when one of the ``constrained'' functions, @('f'),
 introduced in the @(see signature) of an @(tsee encapsulate) event, is
 involved in the termination argument for a non-local recursively defined
 function, @('g'), in that @('encapsulate').  During the processing of the
 encapsulated events, @('f') is locally defined to be some witness function,
 @('f'').  Properties of @('f'') are explicitly proved and exported from the
 encapsulate as the constraints on the undefined function @('f').  But if
 @('f') is used in a recursive @('g') defined within the encapsulate, then the
 termination proof for @('g') may use properties of @('f'') &mdash; the witness
 &mdash; that are not explicitly set forth in the constraints stated for
 @('f').</p>

 <p>Such recursive @('g') are said be ``subversive'' because if naively treated
 they give rise to unsound induction schemes or (via functional instantiation)
 recurrence equations that are impossible to satisfy.  We illustrate what could
 go wrong below.</p>

 <p>Subversive recursions are not banned outright.  Instead, they are treated
 as part of the constraint.  That is, in the case above, the definitional
 equation for @('g') becomes one of the constraints on @('f').  This is
 generally a severe restriction on future functional instantiations of @('f').
 In addition, ACL2 removes from its knowledge of @('g') any suggestions about
 legal inductions to ``unwind'' its recursion.</p>

 <p>What should you do?  Often, the simplest response is to move the offending
 recursive definition, e.g., @('g'), out of the encapsulate.  That is,
 introduce @('f') by constraint and then define @('g') as an ``independent''
 event.  You may need to constrain ``additional'' properties of @('f') in order
 to admit @('g'), e.g., constrain it to reduce some ordinal measure.  However,
 by separating the introduction of @('f') from the admission of @('g') you will
 clearly identify the necessary constraints on @('f'), functional
 instantiations of @('f') will be simpler, and @('g') will be a useful function
 which suggests inductions to the theorem prover.</p>

 <p>Note that the functions introduced in the @(see signature) should not even
 occur ancestrally in the termination proofs for non-local recursive functions
 in the encapsulate.  That is, the constrained functions of an encapsulate
 should not be reachable in the dependency graph of the functions used in the
 termination arguments of recursive functions in encapsulate.  If they are
 reachable, their definitions become part of the constraints.</p>

 <p>The following event illustrates the problem posed by subversive
 recursions.</p>

 @({
  (encapsulate
    (((f *) => *))
    (local (defun f (x) (cdr x)))
    (defun g (x)
      (if (consp x) (not (g (f x))) t)))
 })

 <p>Suppose, contrary to how ACL2 works, that the encapsulate above were to
 introduce no constraints on @('f') on the bogus grounds that the only use of
 @('f') in the encapsulate is in an admissible function.  We discuss the
 plausibility of this bogus argument in a moment.</p>

 <p>Then it would be possible to prove the theorem:</p>

 @({
  (defthm f-not-identity
    (not (equal (f '(a . b)) '(a . b)))
    :rule-classes nil
    :hints ((\"Goal\" :use (:instance g (x '(a . b))))))
 })

 <p>simply by observing that if @('(f '(a . b))') were @(''(a . b)'), then
 @('(g '(a . b))') would be @('(not (g '(a . b)))'), which is impossible.</p>

 <p>But then we could functionally instantiate @('f-not-identity'), replacing
 @('f') by the identity function, to prove @('nil')!  This is bad.</p>

 @({
  (defthm bad
    nil
    :rule-classes nil
    :hints
    ((\"Goal\" :use (:functional-instance f-not-identity (f identity)))))
 })

 <p>This sequence of events was legal in versions of ACL2 prior to Version 1.5.
 When we realized the problem we took steps to make it illegal.  However, our
 steps were insufficient and it was possible to sneak in a subversive function
 (via mutual recursion) as late as Version 2.3.</p>

 <p>We now turn to the plausibility of the bogus argument above.  Why might one
 even be tempted to think that the definition of @('g') above poses no
 constraint on @('f')?  Here is a very similar encapsulate.</p>

 @({
  (encapsulate (((f *) => *))
    (local (defun f (x) (cdr x)))
    (defun map (x)
      (if (consp x)
          (cons (f x) (map (cdr x)))
        nil)))
 })

 <p>Here @('map') plays the role of @('g') above.  Like @('g'), @('map') calls
 the constrained function @('f').  But @('map') truly does not constrain
 @('f').  In particular, the definition of @('map') could be moved ``out'' of
 the encapsulate so that @('map') is introduced afterwards.  The difference
 between @('map') and @('g') is that the constrained function plays no role in
 the termination argument for the one but does for the other.</p>

 <p>As a ``user-friendly'' gesture, ACL2 implicitly moves @('map')-like
 functions out of encapsulations; logically speaking, they are introduced after
 the encapsulation.  This simplifies the constraint.  When the constraint
 cannot be thus simplified the user is advised, via the ``infected'' warning,
 to phrase the encapsulation in the simplest way possible.  See @(see
 infected-constraints).</p>

 <p>The lingering bug between Versions 1.5 and 2.3 mentioned above was due to
 our failure to detect the @('g')-like nature of some functions when they were
 defined in mutually recursively cliques with other functions.  The singly
 recursive case was recognized.  The bug arose because our detection
 ``algorithm'' was based on the ``suggested inductions'' left behind by
 successful definitions.  We failed to recall that mutually-recursive
 definitions do not, as of this writing, make any suggestions about inductions
 and so did not leave any traces of their subversive natures.</p>

 <p>We conclude by elaborating on the criterion ``involved in the termination
 argument'' mentioned at the outset.  Suppose that function @('f') is
 recursively defined in an @(tsee encapsulate), where the body of @('f') has no
 ``ancestor'' among the functions introduced in the signature of that @(tsee
 encapsulate), i.e.: the body contains no call of a signature function, no call
 of a function whose body calls a signature function, and so on.  Then ACL2
 treats @('f') as though it is defined in front of that @('encapsulate') form;
 so @('f') is not @('constrained') by the encapsulate, and its definition is
 hence certainly not subversive in the sense discussed above.  But suppose to
 the contrary that some function introduced in the signature is an ancestor of
 the body of @('f').  Then the definition of @('f') is subversive if moreover,
 its termination proof obligation has an ancestor among the signature
 functions.  Now, that proof obligation involves terms from the first argument
 of selected calls of @('IF'), as well as recursive calls; for a detailed
 discussion, see @(see rulers).  The important point here is that for the
 recursive calls, only the arguments in ``measured'' positions are relevant to
 the termination proof obligation.  Consider the following example.</p>

 @({
    (encapsulate
     (((h *) => *))
     (local (defun h (n) n))
     (defun f (i n)
       (if (zp i)
           n
         (f (1- i) (h n)))))
 })

 <p>ACL2 heuristically picks the measure @('(acl2-count i)') for the definition
 of @('f'); thus, @('i') is the only ``measured formal'' of @('f').  Since
 @('i') is the first formal of @('f'), then for the recursive call of @('f'),
 only the first argument contributes to the termination proof obligation: in
 this case, @('(1- i)') but not @('(h n)').  Thus, even though @('h') is a
 signature function, the definition of @('f') is not considered to be
 subversive; an induction scheme is thus stored for @('f').  (This restriction
 to measured formal positions of recursive calls, for determining subversive
 definitions, is new in Version_3.5 of ACL2.)</p>")

(defxdoc symbol-<
  :parents (symbols acl2-built-ins)
  :short "Less-than test for symbols"
  :long "<p>@('(symbol-< x y)') is non-@('nil') if and only if either the
 @(tsee symbol-name) of the symbol @('x') lexicographically precedes the @(tsee
 symbol-name) of the symbol @('y') (in the sense of @(tsee string<)) or else
 the @(tsee symbol-name)s are equal and the @(tsee symbol-package-name) of
 @('x') lexicographically precedes that of @('y') (in the same sense).  So for
 example, @('(symbol-< 'abcd 'abce)') and @('(symbol-< 'acl2::abcd
 'foo::abce)') are true.</p>

 <p>The @(see guard) for @('symbol') specifies that its arguments are
 symbols.</p>

 @(def symbol-<)")

(defxdoc symbol-alistp
  :parents (alists acl2-built-ins)
  :short "Recognizer for association lists with symbols as keys"
  :long "<p>@('(Symbol-alistp x)') is true if and only if @('x') is a list of
 pairs of the form @('(cons key val)') where @('key') is a @(tsee symbolp).</p>

 @(def symbol-alistp)")

(defxdoc symbol-listp
  :parents (symbols lists acl2-built-ins)
  :short "Recognizer for a true list of symbols"
  :long "<p>The predicate @('symbol-listp') tests whether its argument is a
 true list of symbols.</p>

 @(def symbol-listp)")

(defxdoc symbol-name
  :parents (symbols acl2-built-ins)
  :short "The name of a symbol (a string)"
  :long "<p>Completion Axiom (@('completion-of-symbol-name')):</p>

 @({
  (equal (symbol-name x)
         (if (symbolp x)
             (symbol-name x)
           \"\"))
 })

 <p>@(see Guard) for @('(symbol-name x)'):</p>

 @({
  (symbolp x)
 })")

(defxdoc symbol-package-name
  :parents (symbols packages acl2-built-ins)
  :short "The name of the package of a symbol (a string)"
  :long "<p>WARNING: While @('symbol-package-name') behaves properly on all
 ACL2 objects, it may give surprising results when called in raw Lisp.  For
 more details see @(see pkg-imports), in particular the discussion there of the
 @('\"COMMON-LISP\"') package.</p>

 <p>Completion Axiom (@('completion-of-symbol-package-name')):</p>

 @({
  (equal (symbol-package-name x)
         (if (symbolp x)
             (symbol-package-name x)
           \"\"))
 })

 <p>@(see Guard) for @('(symbol-package-name x)'):</p>

 @({
  (symbolp x)
 })

 <p>Note: @('Symbol-package-name') may diverge from the name of the symbol's
 package in raw Lisp, in the case that this package is the main Lisp package.
 For example, in GCL @('(symbol-package-name 'car)') evaluates to
 \"COMMON-LISP\" even though the actual package name for the symbol, @('car'),
 is \"LISP\".</p>")

(defxdoc symbolp
  :parents (symbols acl2-built-ins)
  :short "Recognizer for symbols"
  :long "<p>@('(symbolp x)') is true if and only if @('x') is a symbol.</p>")

(defxdoc symbols
  :parents (programming)
  :short "Symbols in ACL2 and operations on them"
  :long "<p>Symbols are a basic datatype in ACL2 and Common Lisp.  Every symbol
  has two components: its name (see @(see symbol-name)) and its package name
  (see @(see symbol-package-name)).</p>")

(defxdoc syntax
  :parents (miscellaneous)
  :short "The syntax of ACL2 is that of Common Lisp"
  :long "<p>For the details of ACL2 syntax, see CLTL.  For examples of ACL2
 syntax, use @(':')@(tsee pe) to print some of the ACL2 system code.  For
 example:</p>

 @({
  :pe assoc-equal
  :pe dumb-occur
  :pe var-fn-count
  :pe add-linear-variable-to-alist
 })

 <p>There is no comprehensive description of the ACL2 syntax yet, except that
 found in CLTL.  Also see @(see term).</p>")

(defxdoc syntaxp
  :parents (rewrite definition linear meta)
  :short "Attach a heuristic filter on a rule"
  :long "<p>A call of @('syntaxp') in the hypothesis of a @(':')@(tsee
 rewrite), @(':')@(tsee definition), or @(':')@(tsee linear) rule is treated
 specially, as described below.  Similar treatment is given to the evaluation
 of a @(':')@(tsee meta) rule's hypothesis function call.</p>

 <p>For example, consider the @(':')@(tsee rewrite) rule created from the
 following formula.</p>

 @({
  Example:
  (IMPLIES (SYNTAXP (NOT (AND (CONSP X)
                              (EQ (CAR X) 'NORM))))
           (EQUAL (LXD X)
                  (LXD (NORM X)))).
 })

 <p>The @('syntaxp') hypothesis in this rule will allow the rule to be applied
 to @('(lxd (trn a b))') but will not allow it to be applied to @('(lxd (norm
 a))').</p>

 @({
  General Form:
  (SYNTAXP test)
 })

 <p>@('Syntaxp') always returns @('t') and so may be added as a vacuous
 hypothesis.  However, when relieving the hypothesis, the test ``inside'' the
 @('syntaxp') form is actually treated as a meta-level proposition about the
 proposed instantiation of the rule's variables and that proposition must
 evaluate to true (non-@('nil')) to ``establish'' the @('syntaxp')
 hypothesis.</p>

 <p>Note that the test of a @('syntaxp') hypothesis does not, in general, deal
 with the meaning or semantics or values of the terms, but rather with their
 syntactic forms.  In the example above, the @('syntaxp') hypothesis allows the
 rule to be applied to every target of the form @('(lxd u)'), provided @('u')
 is not of the form @('(norm v)').  Observe that without this syntactic
 restriction the rule above could loop, producing a sequence of increasingly
 complex targets @('(lxd a)'), @('(lxd (norm a))'), @('(lxd (norm (norm a)))'),
 etc.  An intuitive reading of the rule might be ``@('norm') the argument of
 @('lxd') unless it has already been @('norm')ed.''</p>

 <p>Note also that a @('syntaxp') hypothesis deals with the syntactic form used
 internally by ACL2, rather than that seen by the user.  In some cases these
 are the same, but there can be subtle differences with which the writer of a
 @('syntaxp') hypothesis must be aware.  You can use @(':')@(tsee trans) to
 display this internal representation.</p>

 <p>There are two types of @('syntaxp') hypotheses.  The simpler type may be a
 hypothesis of a @(':')@(tsee rewrite), @(':')@(tsee definition), or
 @(':')@(tsee linear) rule provided @('test') contains at least one variable
 but no free variables (see @(see free-variables)).  In particular, @('test')
 may not use @(see stobj)s; any stobj name will be treated as an ordinary
 variable.  The case of @(':')@(tsee meta) rules is similar to the above,
 except that it applies to the result of applying the hypothesis metafunction.
 (Later below we will describe the second type, an <i>extended</i> @('syntaxp')
 hypothesis, which may use @(tsee state).)</p>

 <p>We illustrate the use of simple @('syntaxp') hypotheses by slightly
 elaborating the example given above.  Consider a @(':')@(tsee rewrite)
 rule:</p>

 @({
  (IMPLIES (AND (RATIONALP X)
                (SYNTAXP (NOT (AND (CONSP X)
                                   (EQ (CAR X) 'NORM)))))
           (EQUAL (LXD X)
                  (LXD (NORM X))))
 })

 <p>How is this rule applied to @('(lxd (trn a b))')?  First, we form a
 substitution that instantiates the left-hand side of the conclusion of the
 rule so that it is identical to the target term.  In the present case, the
 substitution replaces @('x') with @('(trn a b)').</p>

 @({
  (LXD X) ==> (LXD (trn a b)).
 })

 <p>Then we backchain to establish the hypotheses, in order.  Ordinarily this
 means that we instantiate each hypothesis with our substitution and then
 attempt to rewrite the resulting instance to true.  Thus, in order to relieve
 the first hypothesis above, we rewrite</p>

 @({
  (RATIONALP (trn a b)).
 })

 <p>If this rewrites to true, we continue.</p>

 <p>Of course, many users are aware of some exceptions to this general
 description of the way we relieve hypotheses.  For example, if a hypothesis
 contains a ``free-variable'' &mdash; one not bound by the current substitution
 &mdash; we attempt to extend the substitution by searching for an instance of
 the hypothesis among known truths.  See @(see free-variables).  @(tsee Force)d
 hypotheses are another exception to the general rule of how hypotheses are
 relieved.</p>

 <p>Hypotheses marked with @('syntaxp'), as in @('(syntaxp test)'), are also
 exceptions.  We instantiate such a hypothesis; but instead of rewriting the
 instantiated instance, we evaluate the instantiated @('test').  More
 precisely, we evaluate @('test') in an environment in which its variable
 symbols are bound to the quotations of the terms to which those variables are
 bound in the instantiating substitution.  So in the case in point, we (in
 essence) evaluate</p>

 @({
  (NOT (AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))).
 })

 <p>This clearly evaluates to @('t').  When a @('syntaxp') test evaluates to
 true, we consider the @('syntaxp') hypothesis to have been established; this
 is sound because logically @('(syntaxp test)') is @('t') regardless of
 @('test').  If the test evaluates to @('nil') (or fails to evaluate because of
 @(see guard) violations) we act as though we cannot establish the hypothesis
 and abandon the attempt to apply the rule; it is always sound to give up.</p>

 <p>The acute reader will have noticed something odd about the form</p>

 @({
  (NOT (AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))).
 })

 <p>When relieving the first hypothesis, @('(RATIONALP X)'), we substituted
 @('(trn a b)') for @('X'); but when relieving the second hypothesis,
 @('(SYNTAXP (NOT (AND (CONSP X) (EQ (CAR X) 'NORM))))'), we substituted the
 quotation of @('(trn a b)') for @('X').  Why the difference?  Remember that in
 the first hypothesis we are talking about the value of @('(trn a b)') &mdash;
 is it rational &mdash; while in the second one we are talking about its
 syntactic form.  Remember also that Lisp, and hence ACL2, evaluates the
 arguments to a function before applying the function to the resulting
 values. Thus, we are asking ``Is the list @('(trn a b)') a @(tsee consp) and
 if so, is its @(tsee car) the symbol @('NORM')?''  The @('quote')s on both
 @('(trn a b)') and @('NORM') are therefore necessary.  One can verify this by
 defining @('trn') to be, say @(tsee cons), and then evaluating forms such
 as</p>

 @({
  (AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))
  (AND (CONSP (trn a b)) (EQ (CAR (trn a b)) NORM))
  (AND (CONSP (trn 'a 'b)) (EQ (CAR (trn 'a 'b)) NORM))
  (AND (CONSP '(trn a b)) (EQ '(CAR (trn a b)) ''NORM))
 })

 <p>at the top-level ACL2 prompt.</p>

 <p>See @(see syntaxp-examples) for more examples of the use of
 @('syntaxp').</p>

 <p>An extended @('syntaxp') hypothesis is similar to the simple type described
 above, but it uses two additional variables, @('mfc') and @('state'), which
 must not be bound by the left hand side or an earlier hypothesis of the rule.
 They must be the last two variables mentioned by @('form'); first @('mfc'),
 then @('state').  These two variables give access to the functions
 @('mfc-')xxx; see @(see extended-metafunctions).  As described there, @('mfc')
 is bound to the so-called metafunction-context and @('state') to ACL2's @(tsee
 state).  See @(see syntaxp-examples) for an example of the use of these
 extended @('syntaxp') hypotheses.</p>

 <p>We conclude with an example illustrating an error that may occur if you
 forget that a @('syntaxp') hypothesis will be evaluated in an environment
 where variables are bound to syntactic terms, not to values.  Consider the
 following @(see stobj) introduction (see @(see defstobj)).</p>

 @({
    (defstobj st
      (fld1 :type (signed-byte 3) :initially 0)
      fld2)
 })

 <p>The following @('syntaxp') hypothesis is ill-formed for evaluation.
 Indeed, ACL2 causes an error because it anticipates that when trying to
 relieve the @('syntaxp') hypothesis of this rule, ACL2 would be evaluating
 @('(fld1 st)') where @('st') is bound to a term, not to an actual @('stobj')
 as required by the function @('fld1').  The error message is intended to
 explain this problem.</p>

 @({
    ACL2 !>(defthm bad
             (implies (syntaxp (quotep (fld1 st)))
                      (equal (stp st)
                             (and (true-listp st)
                                  (equal (len st) 2)
                                  (fld1p (car st))))))

    ACL2 Error in ( DEFTHM BAD ...):  The form (QUOTEP (FLD1 ST)), from
    a SYNTAXP hypothesis, is not suitable for evaluation in an environment
    where its variables are bound to terms.  See :DOC SYNTAXP.  Here is
    further explanation:
         The form ST is being used, as an argument to a call of FLD1, where
    the single-threaded object of that name is required.  But in the current
    context, the only declared stobj name is STATE.  Note:  this error
    occurred in the context (FLD1 ST).

    Summary
    Form:  ( DEFTHM BAD ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

    ACL2 Error in ( DEFTHM BAD ...):  See :DOC failure.

    ******** FAILED ********
    ACL2 !>
 })

 <p>Presumably the intention was to rewrite the term @('(stp st)') when the
 @('fld1') component of @('st') is seen to be an explicit constant.  As
 explained elsewhere (see @(see free-variables)), we can obtain the result of
 rewriting @('(fld1 st)') by binding a fresh variable to that term using
 @('EQUAL'), as follows.</p>

 @({
    (defthm good
      (implies (and (equal f (fld1 st))
                    (syntaxp (quotep f)))
               (equal (stp st)
                      (and (true-listp st)
                           (equal (len st) 2)
                           (fld1p (car st))))))
 })

 <p>The event above is admitted by ACL2.  We can see it in action by disabling
 the definition of @('stp') so that only the rule above, @('good'), is
 available for reasoning about @('stp').</p>

 @({
    (in-theory (disable stp))
 })

 <p>Then the proof fails for the following, because the @('syntaxp') hypothesis
 of the rule, @('good'), fails: @('(quotep f)') evaluates to @('nil') when
 @('f') is bound to the term @('(fld1 st)').</p>

 @({
    (thm (stp st))
 })

 <p>However, the proof succeeds for the next form, as we explain below.</p>

 @({
    (thm (stp (list 3 rest)))
 })

 <p>Consider what happens in that case when rule @('good') is applied to the
 term @('(stp (list 3 rest))').  (See @(see free-variables) for relevant
 background.)  The first hypothesis of @('good') binds the variable @('f') to
 the result of rewriting @('(fld1 st)'), where @('st') is bound to the
 (internal form of) the term @('(list 3 rest)') &mdash; and that result is
 clearly the term, @(''3').  Then the @('syntaxp') hypothesis is successfully
 relieved, because the evaluation of @('(quotep f)') returns @('t') in the
 environment that binds @('f') to @(''3').</p>")

(defxdoc syntaxp-examples
  :parents (syntaxp)
  :short "Examples pertaining to syntaxp hypotheses"
  :long "<p>See @(see syntaxp) for a basic discussion of the use of
 @('syntaxp') to control rewriting.</p>

 <p>A common syntactic restriction is</p>

 @({
  (SYNTAXP (AND (CONSP X) (EQ (CAR X) 'QUOTE)))
 })

 <p>or, equivalently,</p>

 @({
  (SYNTAXP (QUOTEP X)).
 })

 <p>A rule with such a hypothesis can be applied only if @('x') is bound to a
 specific constant.  Thus, if @('x') is @('23') (which is actually represented
 internally as @('(quote 23)')), the test evaluates to @('t'); but if @('x')
 prints as @('(+ 11 12)') then the test evaluates to @('nil') (because @('(car
 x)') is the symbol @(tsee binary-+)).  We see the use of this restriction in
 the rule</p>

 @({
  (implies (and (syntaxp (quotep c))
                (syntaxp (quotep d)))
           (equal (+ c d x)
                  (+ (+ c d) x))).
 })

 <p>If @('c') and @('d') are constants, then the @(tsee executable-counterpart)
 of @(tsee binary-+) will evaluate the sum of @('c') and @('d').  For instance,
 under the influence of this rule</p>

 @({
  (+ 11 12 foo)
 })

 <p>rewrites to</p>

 @({
  (+ (+ 11 12) foo)
 })

 <p>which in turn rewrites to @('(+ 23 foo)').  Without the syntactic
 restriction, this rule would loop with the built-in rules
 @('ASSOCIATIVITY-OF-+') or @('COMMUTATIVITY-OF-+').</p>

 <p>We here recommend that the reader try the affects of entering expressions
 such as the following at the top level ACL2 prompt.</p>

 @({
  (+ 11 23)
  (+ '11 23)
  (+ '11 '23)
  (+ ''11 ''23)
  :trans (+ 11 23)
  :trans (+ '11 23)
  :trans (+ ''11 23)
  :trans (+ c d x)
  :trans (+ (+ c d) x)
 })

 <p>We also recommend that the reader verify our claim above about looping by
 trying the affect of each of the following rules individually.</p>

 @({
  (defthm good
     (implies (and (syntaxp (quotep c))
                   (syntaxp (quotep d)))
              (equal (+ c d x)
                     (+ (+ c d) x))))

  (defthm bad
     (implies (and (acl2-numberp c)
                   (acl2-numberp d))
              (equal (+ c d x)
                     (+ (+ c d) x))))
 })

 <p>on (the false) theorems:</p>

 @({
  (thm
    (equal (+ 11 12 x) y))

  (thm
    (implies (and (acl2-numberp c)
                  (acl2-numberp d)
                  (acl2-numberp x))
             (equal (+ c d x) y))).
 })

 <p>One can use @(':')@(tsee brr), perhaps in conjunction with @(tsee
 cw-gstack), to investigate any looping.</p>

 <p>Here is a simple example showing the value of rule @('good') above.
 Without @('good'), the @('thm') form below fails.</p>

 @({
  (defstub foo (x) t)

  (thm (equal (foo (+ 3 4 x)) (foo (+ 7 x))))
 })

 <p>The next three examples further explore the use of @('quote') in @(tsee
 syntaxp) hypotheses.</p>

 <p>We continue the examples of @(tsee syntaxp) hypotheses with a rule from
 community book @('books/finite-set-theory/set-theory.lisp').  We will not
 discuss here the meaning of this rule, but it is necessary to point out that
 @('(ur-elementp nil)') is true in this book.</p>

 @({
  (defthm scons-nil
    (implies (and (syntaxp (not (equal a ''nil)))
                  (ur-elementp a))
             (= (scons e a)
                (scons e nil)))).
 })

 <p>Here also, @(tsee syntaxp) is used to prevent looping.  Without the
 restriction, @('(scons e nil)') would be rewritten to itself since
 @('(ur-elementp nil)') is true.<br></br>

 Question: Why the use of two quotes in @('''nil')?<br></br>

 Hints: @('Nil') is a constant just as 23 is.  Try @(':trans (cons a nil)'),
 @(':trans (cons 'a 'nil)'), and @(':trans (cons ''a ''nil)').  Also, don't
 forget that the arguments to a function are evaluated before the function is
 applied.</p>

 <p>The next two rules move negative constants to the other side of an
 inequality.</p>

 @({
  (defthm |(< (+ (- c) x) y)|
    (implies (and (syntaxp (quotep c))
                  (syntaxp (< (cadr c) 0))
                  (acl2-numberp y))
             (equal (< (+ c x) y)
                    (< (fix x) (+ (- c) y)))))

  (defthm |(< y (+ (- c) x))|
    (implies (and (syntaxp (quotep c))
                  (syntaxp (< (cadr c) 0))
                  (acl2-numberp y))
             (equal (< y (+ c x))
                    (< (+ (- c) y) (fix x)))))
 })

 <p>Questions: What would happen if @('(< (cadr c) '0)') were used?  What about
 @('(< (cadr c) ''0)')?</p>

 <p>One can also use @('syntaxp') to restrict the application of a rule to a
 particular set of variable bindings as in the following taken from the @(see
 ihs) library.</p>

 @({
  (encapsulate ()

    (local
     (defthm floor-+-crock
       (implies
        (and (real/rationalp x)
             (real/rationalp y)
             (real/rationalp z)
             (syntaxp (and (eq x 'x) (eq y 'y) (eq z 'z))))
        (equal (floor (+ x y) z)
               (floor (+ (+ (mod x z) (mod y z))
                         (* (+ (floor x z) (floor y z)) z)) z)))))

    (defthm floor-+
      (implies
       (and (force (real/rationalp x))
            (force (real/rationalp y))
            (force (real/rationalp z))
            (force (not (equal z 0))))
       (equal (floor (+ x y) z)
              (+ (floor (+ (mod x z) (mod y z)) z)
                 (+ (floor x z) (floor y z))))))

    )
 })

 <p>We recommend the use of @(':')@('brr') to investigate the use of
 @('floor-+-crock').</p>

 <p>Another useful restriction is defined by</p>

 @({
  (defun rewriting-goal-literal (x mfc state)

    ;; Are we rewriting a top-level goal literal, rather than rewriting
    ;; to establish a hypothesis from a rewrite (or other) rule?

    (declare (ignore x state))
    (null (access metafunction-context mfc :ancestors))).
 })

 <p>We use this restriction in the rule</p>

 @({
  (defthm |(< (* x y) 0)|
      (implies (and (syntaxp (rewriting-goal-literal x mfc state))
                    (rationalp x)
                    (rationalp y))
               (equal (< (* x y) 0)
                      (cond ((equal x 0)
                             nil)
                            ((equal y 0)
                             nil)
                            ((< x 0)
                             (< 0 y))
                            ((< 0 x)
                             (< y 0))))))
 })

 <p>which has been found to be useful, but which also leads to excessive
 thrashing in the linear arithmetic package if used indiscriminately.</p>

 <p>See @(see extended-metafunctions) for information on the use of @('mfc')
 and @('metafunction-context').</p>")

(defxdoc sys-call
  :parents (interfacing-tools acl2-built-ins)
  :short "Make a system call to the host operating system"
  :long "@({
  Example Forms:
  (sys-call \"cp\" '(\"foo.lisp\" \"foo-copied.lisp\"))
  (prog2$ (sys-call \"cp\" '(\"foo.lisp\" \"foo-copied.lisp\"))
          (sys-call-status state))
 })

 <p>The first argument of @('sys-call') is a command for the host operating
 system, and the second argument is a list of strings that are the arguments
 for that command.  In GCL and perhaps some other lisps, you can put the
 arguments with the command; but this is not the case, for example, in Allegro
 CL running on Linux.</p>

 <p>The use of @(tsee prog2$) above is optional, but illustrates how to get the
 return status.  See @(see sys-call-status).  @('Sys-call') itself always
 returns @('nil').</p>

 <p>For related utilities, see @(see sys-call*) and @(see sys-call+).  Both of
 those utilities return a suitable status (rather than requiring a separate
 call of a separate function, @(tsee sys-call-status), as described later
 below).  Also, @('sys-call+') returns the command's output, but (like
 @('sys-call')) @('sys-call*') does not.  An important distinction is that both
 @('sys-call+') and @('sys-call*') make their calls to the operating system
 during proofs, unlike @('sys-call') as we now explain.</p>

 <p>@('Sys-call') does not invoke the operating system when it is invoked
 inside the theorem prover or @(see proof-builder).  The following example,
 from Eric Smith, illustrates this point: presumably we only want to reason
 about the return value, not write a file during a proof!</p>

 @({
 (defttag foo)
 (thm (equal (sys-call \"touch\" (list \"/tmp/XXX\"))
             nil)
      :hints ((\"Goal\" :in-theory (disable (:type-prescription sys-call)))))
 })

 <p>Through Version_7.4, running this example did indeed create file
 @('/tmp/XXX') if that file did not already exist.  Now, the @(see
 executable-counterpart) of @('sys-call') is disabled, which avoids that
 specific behavior.  Moreover: even with that executable-counterpart enabled,
 no file is created; @('sys-call') returns @('nil') without invoking the
 operating system.  If such an evaluation attempt occurs during invocation of a
 @(see clause-processor) or @(see meta)function, then an error will be
 signaled.</p>

 @({
  General Form:
  (sys-call cmd args)
 })

 <p>This function logically returns @('nil').  However, it makes the indicated
 call to the host operating system, as described above (not during a proof),
 using a function supplied ``under the hood'' by the underlying Lisp system.
 This is an advanced feature that requires a trust tag (see below).  Host lisps
 differ on their handling of @('sys-call'); see the raw Lisp definition of ACL2
 source function @('system-call') for details, including exactly what
 underlying Lisp function is invoked.  You can then look at that host lisp's
 manual for details about that underlying function.</p>

 <p>On occasions where one wishes to obtain the numeric status returned by the
 host operating system (or more precisely, by the Lisp function under the hood
 that passes the system call to the host operating system), one may do so; see
 @(see sys-call-status).  The status value is the value returned by that Lisp
 function, which may well be the same numeric value returned by the host
 operating system for the underlying system call.</p>

 <p>Note that @('sys-call') does not touch the ACL2 @(tsee state); however,
 @(tsee sys-call-status) updates the @('acl2-oracle') field of the
 @('state').</p>

 <p>Be careful if you use @('sys-call')!  It can be used for example to
 overwrite files, or worse!  We view a use of @('sys-call') as a call to the
 operating system that is made outside ACL2.  The following example from Bob
 Boyer shows how to use @('sys-call') to execute, in effect, arbitrary Lisp
 forms.  ACL2 provides a ``trust tag'' mechanism that requires execution of a
 @(tsee defttag) form before you can use @('sys-call'); see @(see defttag).
 (Note: The setting of the raw Lisp variable @('*features*') below is just to
 illustrate that any such mischief is possible.  Normally @('*features*') is a
 list with more than a few elements.)</p>

 @({
  % cat foo
  print *0x85d2064=0x838E920
  detach
  q
  % acl2
  ... boilerplate deleted
  ACL2 !>(sys-call \"gdb -p $PPID -w < foo >& /dev/null \" nil)
  NIL
  ACL2 !>:q

  Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
  ACL2>*features*

  (:AKCL-SET-MV)

  ACL2>
 })

 <p>Finally, we note that @('sys-call') does not provide some features that one
 may expect of a shell.  In particular, @('sys-call') does not generally
 support shell expansion of its arguments (such as @('~/')).  It also does not
 directly support output redirection.  If you want to run a program, @('P'),
 and redirect its output, one option is to create a wrapper script, @('W') to
 call instead.  Thus @('W') might be a shell script containing the line:</p>

 @({
  P $* >& foo.out
 })")

(defxdoc sys-call*
  :parents (sys-call acl2-built-ins)
  :short "Make a system call to the host OS, returning a status"
  :long "<p>See @(see sys-call+) for a closely related utility.  There are only
 the following two differences between between @('sys-call*') and
 @('sys-call+').</p>

 <ul>

 <li>Both return an @(see error-triple) @('(mv erp val state)'), but for
 @('sys-call*'), @('val') is always @('nil').  (For @('sys-call+'), @('val') is
 the string produced as output by the command.)</li>

 <li>Logically, @('sys-call*') pops the oracle once, not twice.</li>

 </ul>")

(defxdoc sys-call+
  :parents (sys-call acl2-built-ins)
  :short "Make a system call to the host OS, returning status and output"
  :long "@({
  Example Form:
  ; The following returns (mv nil s state), where s is the standard output
  ; from the command: ls -l ./
  (sys-call+ \"ls\" '(\"-l\" \"./\") state)

  General Form:
  (sys-call+ cmd args state)
 })

 <p>where @('cmd') is a command to the host operating system and @('args') is a
 list of strings.  Also see related utilities @(see sys-call) and @(see
 sys-call*).  There are three major differences between @(tsee sys-call) and
 both @('sys-call+') and @('sys-call*').  First, the latter two take an extra
 argument, @('state').  Second, while @('sys-call') returns @('nil'),
 @('sys-call+') and @('sys-call*') both return an @(see error-triple), @('(mv
 erp val state)').  Finally, @('sys-call+') and @('sys-call*') provide a
 command to the host operating system even during a proof, which could be
 useful in computed hints and clause processors.  While execution returns
 values as listed below, further below we explain the logical return values.
 In the following, please keep in mind that the exact behavior depends on the
 platform; the description is only a guide.  For example, on some platforms
 @('erp') might always be @('nil'), even if in the error case, and @('val')
 might or might not include error output.  (For details, look at the ACL2
 source code for function @('system-call+'), whose output is converted by
 replacing an @('erp') of @('nil') by 0.)</p>

 <blockquote>

 <p>@('Erp') is either @('nil') or a non-zero integer.  Normally, @('nil')
 indicates that the command ran without error, and otherwise @('erp') is the
 exit status.</p>

 <p>@('Val') is a string, typically the output generated by the call of
 @('cmd').</p>

 <p>@('State') is an ACL2 @(see state).</p></blockquote>

 <p>While the description above pertains to the values returned by executing
 @('sys-call+'), the logical values are as follows.  For a discussion of the
 @('acl2-oracle') field of an ACL2 state, see @(tsee read-acl2-oracle) and
 @(see state).</p>

 <blockquote>

 <p>@('Erp') is the first element of the @('acl2-oracle') of the input state if
 that element is a nonzero integer, and otherwise is @('nil').</p>

 <p>@('Val') is the second element of the @('acl2-oracle') of the input state
 if it is a string, else the empty string, @('\"\"').</p>

 <p>@('State') is the result of popping the @('acl2-oracle') field twice from
 the input state.</p></blockquote>

 <p>Note that unlike @(tsee sys-call), a call of @(tsee sys-call+) has no
 effect on subsequent calls of @(tsee sys-call-status).</p>

 <p>As is the case for @('sys-call'), a trust tag is required to call
 @('sys-call+').  For discussion of this and more, see @(see sys-call).</p>")

(defxdoc sys-call-status
  :parents (sys-call acl2-built-ins)
  :short "Exit status from the preceding system call"
  :long "<p>This function returns two values, @('(mv status state)').  The
 first is the status resulting from the most recent call to the operating
 system by invoking function @('sys-call'); see @(see sys-call).  The second is
 the ACL2 @(tsee state) object, which is also the input to this function.</p>

 <p>The function @(tsee sys-call) provides a command to be executed by the host
 operating system (except when invoked during a proof; see @(see sys-call))
 using a function supplied ``under the hood'' by the underlying Lisp system.
 The status value is the value returned by that Lisp function, which may well
 be the numeric value returned by the host operating system for the underlying
 system call.  For more information, see @(see sys-call).</p>")

(defxdoc system-development
  :parents (programming)
  :short "Developing ACL2 system code"
  :long "<p>ACL2 is maintained solely by Matt Kaufmann and J Moore.  However,
 we anticipate that a few others will eventually contribute as well.  The
 subtopics of this topic provide information that is intended to help future
 developers.</p>

 <p>The website for the (first) Developer's Workshop is: <code><a
 href='http://www.cs.utexas.edu/users/moore/acl2/workshop-devel-2017/'>http://www.cs.utexas.edu/users/moore/acl2/workshop-devel-2017/</a></code></p>

 <p>For a small list of potential ACL2 development tasks, see community books
 file @('books/system/to-do.txt').</p>")

(defxdoc system-development-hints
  :parents (system-development)
  :short "Helpful hints for developing ACL2 system code"
  :long "<p>ACL2 is maintained solely by Matt Kaufmann and J Moore.  However,
 we anticipate that a few others will eventually contribute as well.  Here we
 provide a few suggestions that might facilitate the writing of ACL2 system
 code; however, the topic @(see making-system-changes) is the primary topic
 discussing how to make system changes.  Also see @(see system-style-guide) for
 style guidelines.</p>

 <p>NOTE: This is an evolving topic.  Please feel free to augment it with
 additional useful tips!</p>

 <p>Emacs provides several useful utilities for ACL2 coding, including the
 following.  If you can do these kinds of things quickly without Emacs, that's
 fine; otherwise it would probably be best for you to invest in learning
 Emacs.</p>

 <ul>

 <li>Find a function definition: @('meta-.') or @('meta-x tags-apropos').</li>

 <li>Find an Essay such as ``Essay on Hidden Packages'': @('meta-x
 tags-search').</li>

 <li>Change a name globally: @('meta-x tags-query-replace').  WARNING: if you
 do this, consider changing names in books as well, for example by using the
 following shell command.

 @({
 time fgrep --include='*.l*sp' -ri 'some-old-name' .
 })</li>

 </ul>

 <p>Defensive programming is a good idea.  For an example, see
 @('all-runes-in-ttree'), which causes a hard error if an unexpected tag is
 encountered and also is nice in how it documents tag-trees.</p>")

(defxdoc system-style-guide
  :parents (system-development)
  :short "Style guidelines for developing ACL2 system code"
  :long "<p>ACL2 is maintained solely by Matt Kaufmann and J Moore.  However,
 we anticipate that a few others will eventually contribute as well.  Here we
 set out some style guidelines that have traditionally been followed, and can
 guide development to help maintain ACL2's quality.  Separate topics provide
 instruction on maintaining ACL2 system code; see @(see making-system-changes)
 and @(see system-development-hints).</p>

 <p>The right margin is 79.  (In emacs: @('set-fill-column 79').)  Existing
 code with margin 70 is OK to leave as is, though it's nice to convert to a
 margin of 79 when modifying comments within a given function.</p>

 <p>Tabs are not used.  In emacs, setting buffer-local variable
 @('indent-tabs-mode') to @('nil') will accomplish this.  That can be
 accomplished automatically for Lisp files, as is done in distributed file
 @('emacs/emacs-acl2.el'); search there for @('indent-tabs-mode'), or simply
 load that file in your @('.emacs') file.</p>

 <p>Periods that end sentences are followed by two spaces (useful for
 @('meta-e') command in emacs).</p>

 <p>Comments for a function go immediately after its formal parameters
 (even before @(see declare) forms).</p>

 <p>Comments generally consist of complete sentences, starting on the left
 margin, each line starting with a single semicolon followed by a space.  An
 exception is very short comments to the right of code up to the end of the
 same line.</p>

 <p>Use of the @(tsee cond) macro is generally preferred to the use of @('if'),
 an exception being small expressions that are not at the top level.</p>

 <p>System state globals need to be included in @('*initial-global-table*') or
 @('*initial-ld-special-bindings*').</p>

 <p>Blank lines are avoided except in the usual circumstances, e.g. surrounding
 comments and between definitions.  Avoid consecutive blank lines.</p>

 <p>A multi-line argument is not followed by an argument on the same line.  For
 example, there should be a linebreak before the argument, @('arg'), after the
 string in this @('COND') clause:</p>

 @({
 (t (er soft ctx
        \"The value associated with a :SOME-NEW-HINT hint must be a positive ~
        integer, but ~x0 is not.\" arg))
 })

 <p>We generally avoid capitalizing all letters in a single word, except
 perhaps for keywords or quoted constants.</p>

 <p>There are no multi-line comments: @('#|| ... ||#').</p>")

(defxdoc system-utilities

; NOTE: Consider adding a defpointer below for each system utility documented
; here that doesn't have an xdoc topic.

  :parents (programming)
  :short "List of system-level programming utilities"
  :long "<p>Since the ACL2 system is written in itself, the source code defines
 many utilities that support the ACL2 implementation.  Some of these have been
 found to be useful not only to the ACL2 developers, but to those who use ACL2
 to perform tasks other than the traditional ones: writing and submitting
 definitions, and proving theorems about the functions defined.</p>

 <p>This topic provides a summary of some of those system-level utilities.  It
 is intended to be a growing document, with contributions from those in the
 community who find such utilities that benefit them.  It has already grown
 substantially from an initial version created by the ACL2 implementors, and
 others will likely continue to add to it over time.</p>

 <p>WARNING: Some system utilities are in @(':')@(tsee program) mode, and for
 many of those, @(see guard)s are incomplete or missing entirely.  Incorrect
 use of such utilities can thus lead to scary (though often harmless) raw Lisp
 errors!  Although this situation may improve over time, for now users of these
 utilities must cope with that danger just as the ACL2 implementors cope with
 it, which is by understanding the requirements on each utility that is
 invoked.  For example, if you incorrectly invoke @('(untranslate (cons 3 4)
 nil (w state))'), where perhaps @('(untranslate '(cons '3 '4) nil (w state))')
 was intended, then the resulting raw Lisp error is your responsibility for
 invoking @('untranslate') on the object @('(3 . 4)') instead of the term
 @('(cons '3 '4)').</p>

 <p>The ACL2 system comes with substantial comments.  As of Version_7.1 (May,
 2015), out of slightly under 10 MB of source code (not including 4.8 MB of
 @(see documentation) topics), nearly 400 KB (just over 40%) were comment
 lines.  This topic is not intended to supplant or duplicate those comments,
 but rather, only to note system utilities of interest to the community.  If
 you find the source comments inadequate, please feel free to ask the system
 implementors to make corresponding additions to the source code comments.
 Note that if you execute the command</p>

 @({
 grep '^; Essay on' *.lisp
 })

 <p>in your ACL2 sources directory, you will see the names of more than 80 long
 source comments, or ``Essays'', that can provide additional background.</p>

 <p>Also see @(see programming) and its subtopics, in particular @(see
 programming-with-state), which describes <em>many</em> system-level utilities.
 For example, a subsection of @(see programming-with-state), entitled
 ``SEQUENTIAL PROGRAMMING'', introduces handy utilities @(tsee pprogn) and
 @(tsee er-progn) along with links to their documentation.</p>

 <p>Here is another option for finding a system utility: As ACL2 developers
 sometimes do, use @('meta-.') or @('meta-x tags-apropos') in Emacs to find
 utilities with given substrings in their names.  For example, if in Emacs you
 submit the command @('meta-x tags-apropos') and reply @('pwd') at the prompt,
 you'll find a raw Lisp function @('our-pwd') that ACL2 defines as an analogue
 to the Linux @('pwd') command; and, with @('meta-x tags-search') applied to
 @('(our-pwd'), you can see how ACL2 source code uses this utility.</p>

 <h3>List of a few ACL2 system utilities:</h3>

 <p>Every function mentioned below belongs in the constant @(tsee
 *acl2-system-exports*).</p>

 <ul>

 <li>@('(alist-to-doublets alist)'): Return the result of replacing each pair
 @('(x . y)') in the given alist by the two-element list @('(x y)').  The order
 is preserved, i.e., the following is a theorem.</li>

 @({
 (implies (and (natp i) (< i (len alist)))
          (equal (nth i (alist-to-doublets alist))
                 (let ((pair (nth i alist)))
                   (list (car pair) (cdr pair)))))
 })

 <li>@('(all-calls names term alist ans)'):  Accumulate into @('ans')
 (which typically is @('nil') at the top level) all pseudo-terms @('u/alist')
 such that for some @('f') in the list, @('names'), @('u') is a subterm of the
 pseudo-term, @('term'), that is a call of the symbol, @('f').  Note that
 @('(all-calls-lst names lst alist ans)') is similar, except for a list,
 @('lst'), of terms in place of a single term, @('term').</li>

 <li>@('(all-ffn-symbs term ans)'): Accumulate into @('ans')
 (which typically is @('nil') at the top level) all function symbols called
 in the given term.</li>

 <li>@('(all-ffn-symbs-lst lst ans)'): Accumulate into @('ans')
 (which typically is @('nil') at the top level) all function symbols called
 in the given list of terms.</li>

 <li>@('(all-vars x)'): For a @(tsee pseudo-termp) @('x'), return the list of
 variables in @('x') in reverse print order of first occurrence.  For example,
 @('all-vars') of @(''(f (g a b) c)') is @(''(c b a)').</li>

 <li>@('(arglistp lst)'): Return true iff @('lst') is a @('nil')-terminated
 list of distinct, legal variable names, usable as the formal argument
 list (hence the name of this utility) of a function.</li>

 <li>@('(arity fn w)'): For a function symbol or @('lambda') expression @('fn')
 of @(see world) @('w'), return the number of its formal parameters.</li>

 <li>@('(body fn normalp w)'): @('Fn') should either be a @(':')@(tsee
 logic)-mode function symbol of @(see world) @('w') or a @('lambda')
 expression.  If @('fn') is a symbol and @('normalp') is @('nil'), then return
 the body of its original definition.  If @('fn') is a @('lambda') expression,
 return its body.  We now discuss the remaining case, where @('fn') is a
 @(':')@(tsee logic)-mode function symbol and @('normalp') is true.  In the
 usual case that no @(see definition) rule has been introduced for @('fn') with
 a non-@('nil') value of @(':install-body') (which is the default), return the
 @(see normalize)d body from the @('defun') form that introduced @('fn'), or
 @('nil') if @('fn') was not introduced with @('defun') (as with @(tsee
 encapsulate), @(tsee defstub), or @(tsee defchoose)) &mdash; except that in
 the case that @(':normalize nil') was specified in that @('defun') form (see
 @(see xargs)), return the unnormalized body.  The remaining case is that at
 least one @(see definition) rule for @('fn') has been installed.  In that
 case, the latest such rule provides the body (see source function
 @('latest-body') for how hypotheses are handled), with one exception: if the
 equivalence relation for that rule is other than @('equal'), then the
 unnormalized body is returned.</li>

 <li>@('(conjoin lst)'): The conjunction of the given list of terms.</li>

 <li>@('(conjoin2 term1 term2)'): The conjunction of the given two terms.</li>

 <li>@('(cons-count-bounded x)'): The number of cons nodes in @('x') (without
 accounting for sharing), but truncated above by the value of
 @('(fn-count-evg-max-val)'), which is 200,000 as of this writing.</li>

 <li>@('(cons-term fn args)'): Returns a @(see term) with function symbol (or
 @(see lambda) expression) @('fn') and arguments @('args').  Some
 simplification may be done; to avoid that, use @('fcons-term') (``fast
 cons-term''), described below.  Also see @('cons-term*') and @('fcons-term*')
 below.</li>

 <li>@('(cons-term* fn arg1 arg2 ...)'): This variant of @('cons-term')
 (described above) returns a term with the indicated function and arguments,
 where the arguments are ``spread'' into individual actual parameters rather
 than provided as a list.  Some simplification may be done; to avoid that, use
 @('fcons-term*').  Also see @('cons-term') above and @('fcons-term')
 below.</li>

 <li>@('(default-state-vars state-p &key ...)'): Returns a record suitable as
 an argument for some utilities that take the @(see world) as an argument but
 not the @(see state), such as @('translate-cmp').  That record provides values
 for certain state global variables (which are not stored in the world), such
 as @('guard-checking-on') (which holds the @(see guard)-checking mode).  As
 described below, @('default-state-vars') provides suitable defaults, which
 however can be modified by supplying keyword arguments corresponding to
 certain state globals, such as @(':guard-checking-on').  When the required
 argument is @('t'), those defaults are the values of those state globals;
 thus, @('t') is probably the right value to use for that argument when the
 state is available in the calling context.  Otherwise, those defaults are the
 values commonly found in those state globals.</li>

 <li>@('(defined-constant name w)'): If @('name') is @('t'), @('nil'), or
 defined using @(tsee defconst), return @('(quote val)') where @('val') is the
 value of @('name'); otherwise return @('nil').</li>

 <li>@('(defun-mode fn w)'): If @('fn') is a function symbol, return the @(see
 defun-mode) of @('fn'): @(':program') if @('fn') is in @(':')@(tsee program)
 mode, @(':logic') if @('fn') is in @(':')@(tsee logic) mode.  If @('fn') is
 not a function symbol, return @('nil').</li>

 <li>@('(disabledp name)'): The list of @(see rune)s introduced with @('name')
 that are currently @(see disable)d.  See @(see disabledp).  Also see
 @('enabled-runep'), below, for a more direct test of whether a given rune is
 @(see enable)d.</li>

 <li>@('(disjoin lst)'): The disjunction of the given list of terms.</li>

 <li>@('(disjoin2 term1 term2)'): The disjunction of the given two terms.</li>

 <li>@('(dumb-negate-lit t1)'): For the given @(see term) @('t1'), return a
 term that is propositionally equivalent to @('(not t1)').</li>

 <li>@('(enabled-numep nume ens wrld)'): Return true iff the given
 nume (numeric representation of a @(see rune)) in the @(see world), @('wrld'),
 is @(see enable)d with respect to the given enabled structure, @('ens').
 (For example, @('(ens state)') returns the global enabled structure; during a
 proof, the enabled structure comes from the so-called rewrite-constant.)
 @('Nil') is also a valid first argument, in which case the return value is
 @('t').  See also @('enabled-runep').</li>

 <li>@('(enabled-runep rune ens wrld)'): Return true iff the given @(see rune)
 in the @(see world), @('wrld'), is @(see enable)d with respect to the given
 enabled structure (as discussed for @('enabled-numep'), just above).  See also
 @('enabled-numep'), which may be more efficient since @('enabled-runep') is
 defined in terms of @('enabled-numep').</li>

 <li>@('(fargn x n)'): For a @(tsee pseudo-termp) @('x') that is a function
 call and for a positive integer @('n'), return the @('n')-th argument of
 @('x'), where the numbering of arguments starts at 1.</li>

 <li>@('(fargs x)'): For a @(tsee pseudo-termp) @('x') that is a function call,
 return its arguments.</li>

 <li>@('(fcons-term fn args)'): This variant of @('cons-term') (described
 above) returns a term with the indicated function and arguments, without any
 simplification.  Also see @('cons-term') and @('cons-term*') above, and
 @('fcons-term*') below.</li>

 <li>@('(fcons-term* fn arg1 arg2 ...)'): This variant of @('fcons-term')
 (described above) returns a term with the indicated function and arguments,
 without any simplification, and where the arguments are ``spread'' into
 individual actual parameters rather than provided as a list.  Also see
 @('cons-term'), @('cons-term*'), and @('fcons-term') above.</li>

 <li>@('(fdefun-mode fn)'): For a function symbol @('fn'), return the @(see
 defun-mode) of @('fn'): @(':program') if @('fn') is in @(':')@(tsee program)
 mode, @(':logic') if @('fn') is in @(':')@(tsee logic) mode.</li>

 <li>@('(ffn-symb x)'): This version of @('fn-symb') (described below) assumes
 that @('x') is a @(tsee pseudo-termp) that is a function call, without
 checking that @('x') is a function call (the leading ``f'' is for ``fast''),
 and returns its called function or @('lambda') expression.</li>

 <li>@('(ffn-symb-p x sym)'): For a @(tsee pseudo-termp) @('x'), return @('t')
 if it is a function call whose function symbol is @('sym'), else return
 @('nil').</li>

 <li>@('(ffnnamep fn term)'): Returns @('t') when the function @('fn')
 (possibly a @(see lambda) expression) is used as a function in @('term'),
 which is assumed to be a @(tsee pseudo-termp); else returns @('nil').</li>

 <li>@('(ffnnamep-lst fn lst)'): Returns @('t') when the function @('fn')
 (possibly a @(see lambda) expression) is used as a function in a member of the
 list @('lst') of @(tsee pseudo-termp)s; else returns @('nil').</li>

 <li>@('(flambda-applicationp x)'): For a @(tsee pseudo-termp) @('x') that is
 not a variable, return @('t') if it is a function call whose function symbol
 is a @('lambda') expression, else return @('nil').</li>

 <li>@('(flambdap fn)'): True when @('fn') is a @('lambda') expression.</li>

 <li>@('(fn-rune-nume fn nflg xflg wrld)'): For a function symbol @('fn'),
 return either the @(see rune) (case @('nflg') = @('nil')) or nume (numeric
 representation of a rune) (case @('nflg') = @('t')) associated with either
 @('(:DEFINITION fn)') (case @('xflg') = @('nil')) or
 @('(:EXECUTABLE-COUNTERPART fn)') (case @('xflg') = @('t')).  If @('fn') is a
 constrained function, return @('nil') for all combinations of the flags.</li>

 <li>@('(fn-symb x)'): For a @(tsee pseudo-termp) @('x'), return its called
 function or @('lambda') expression if @('x') is a function call, otherwise
 return @('nil').  Also see @('ffn-symb'), above.</li>

 <li>@('(formals fn w)'): For a function symbol @('fn') of @(see world) @('w'),
 return its list of formal parameters.</li>

 <li>@('(formula name normalp w)'): For an event name or @(see rune),
 @('name'), of @(see world) @('w'), return the corresponding formula if
 any (@(see normalize)d iff @('normalp') is true), else @('nil').  See @(see
 formula).</li>

 <li>@('(fquotep x)'): For a @(tsee pseudo-termp) @('x') that is not a
 variable, return true iff @('x') is a quoted constant.</li>

 <li>@('(fsubcor-var vars terms form)'): This variant of @('subcor-var')
 (described below) also substitutes, in the @(tsee pseudo-termp) @('form'), the
 variables in the list of @(tsee symbolp)s @('vars') with the corresponding
 elements in the list of @(tsee pseudo-termp)s @('terms'), but without
 performing any simplification.</li>

 <li>@('(function-symbolp sym w)'): True when the symbol @('sym') is a function
 symbol in the @(see world) @('w').</li>

 <li>@('(genvar pkg-witness prefix n avoid-lst)'): Generate a new variable
 name.</li>

 <li>@('(get-brr-local var state)'): The value of brr-local variable @('var');
 this is the utility used by @(see brr@).</li>

 <li>@('(get-event name w)'): For the given name of an event in the current
 ACL2 @(see world) @('w'), return that event.</li>

 <li>@('(get-skipped-proofs-p name w)'): For the given name of an event in the
 current ACL2 @(see world) @('w'), return @('t') if proofs were skipped when
 introducing that event, as with @(tsee skip-proofs) or using @(tsee
 set-ld-skip-proofsp) &mdash; that is, with proofs skipped other than by the
 system (as with @(tsee include-book)); else return @('nil').  Exception: if
 @('name') is a function symbol that is either built in or in @(':')@(tsee
 program) mode, return @('nil').</li>

 <li>@('(guard fn stobj-optp w)'): For a function symbol or @('lambda')
 expression @('fn') of @(see world) @('w'), return its @(see guard). Optimize
 the @(see stobj) recognizers away iff @('stobj-optp') is true.</li>

 <li>@('(implicate t1 t2)'): For terms @('t1') and @('t2'), return a term that
 is propositionally equivalent to @('(implies t1 t2)').</li>

 <li>@('(lambda-applicationp x)'): For a @(tsee pseudo-termp) @('x'), return
 @('t') if it is a function call whose function symbol is a @('lambda')
 expression, else return @('nil').</li>

 <li>@('(lambda-body x)'): For a @('lambda') expression @('x'), return its
 body.</li>

 <li>@('(lambda-formals x)'): For a @('lambda') expression @('x'), return its
 formal parameters.</li>

 <li>@('(logicp fn w)'): For a function symbol @('fn') of @(see world)
 @('w'), return @('t') when the @('symbol-class') of @('fn') in @('w') is not
 @(':program'), else @('nil').  (See @('symbol-class'), below.)</li>

 <li>@('(make-lambda args body)'): Return @('lambda') expression with formal
 parameters @('args') and body @('body').</li>

 <li>@('(merge-sort-lexorder l)'): Sort the list @('l') using a non-strict
 total order, @(tsee lexorder), on the ACL2 universe.</li>

 <li>@('(nvariablep x)'): For a @(tsee pseudo-termp) @('x'), return true iff
 @('x') is not a variable (i.e. it is a quoted constant or a function
 call).</li>

 <li>@('(plist-worldp alist)'): Recognizer for when @('alist') is syntactically
 well-formed as an ACL2 logical @(see world), sometimes suitable for use in
 @(see guard)s.  Note: for a somewhat deeper check, see community book
 @('books/system/pseudo-good-worldp.lisp').</li>

 <li>@('(prettyify-clause cl let*-abstractionp wrld)'): Returns an untranslated
 (user-level) term that is equivalent to the clause, @('cl').</li>

 <li>@('(programp fn w)'): For a function symbol @('fn') of @(see world)
 @('w'), return @('t') when the @('symbol-class') of @('fn') in @('w') is
 @(':program'), else @('nil').  (See @('symbol-class'), below.)</li>

 <li>@('(quotep x)'): For a @(tsee pseudo-termp) @('x'), return true iff @('x')
 is a quoted constant.</li>

 <li>@('(recursivep fn flg w)'): @('Fn') should be a @(':')@(tsee logic)-mode
 function symbol @('fn') of the @(see world), @('w').  The result is the list
 of mutually recursive functions of which @('fn') is a member.  The list is
 empty iff @('fn') is not recursive.  The list contains just @('fn') iff
 @('fn') is singly recursive.  NOTE: @('flg') should be @('t') or @('nil').  If
 @('flg') is @('nil'), the result is based solely on the @(tsee defun) form that
 introduced @('fn') and is equal to @('(getpropc fn 'recursivep nil w)').  If
 @('flg') is @('t'), then the most recent @(see definition) rule for @('fn')
 with a non-@('nil') value of @(':install-body') &mdash; which could be the
 original definition &mdash; will cause @('recursivep') to return the
 @(':clique') specified by that rule; see @(see rule-classes).</li>

 <li>@('(stobjp x known-stobjs w)'): Returns a non-@('nil') value when @('x')
 is to be treated as a @(see stobj) name, else @('nil').  Argument
 @('known-stobjs') is a list of all such names, or else @('t'), standing for
 all stobj names in the @(see world), @('w').  If you want to know whether
 @('x') has been defined as a stobj in @('w'), use @('known-stobjs') = @('t').
 Technicality: if @('known-stobjs') is a list then it is allowed to contain any
 number of @('nil') elements (as may be the case for the the @('stobjs-in') or
 @('stobjs-out') of a symbol), which are ignored.</li>

 <li>@('(stobjs-in fn w)'): For a function symbol @('fn') of @(see world)
 @('w'), return the stobjs-in of @('fn'), which is the result of modifying the
 list of formal parameters of @('fn') by replacing with @('nil') each symbol
 that is not a @(see stobj) input.  Note that @('fn') must be a symbol, not a
 @(see lambda) expression.</li>

 <li>@('(stobjs-out fn w)'): For a function symbol @('fn') of @(see world)
 @('w'), return the stobjs-out of @('fn'), which is a list whose length is the
 number of return values of @('fn') &mdash; that is, length 1 unless @('fn')
 returns multiple values.  For each @('i') less than that length, if the
 @('i')th return value is a stobj, then that is the @('i')th element of the
 stobjs-out; otherwise the @('i')th element of the stobjs-out is @('nil').
 Note that @('fn') must be a symbol, not a @(see lambda) expression.  Moreover
 @('fn') must not be a member of the list @('*stobjs-out-invalid*') (currently,
 @('IF') or @('RETURN-LAST')), since for these functions arbitrary multiple
 values may be returned.</li>

 <li>@('(subcor-var vars terms form)'): For a list @('vars') of symbols, a list
 @('terms') of @(tsee pseudo-termp)s, and a @(tsee pseudo-termp) @('form'),
 substitute, in @('form'), the <i>i</i>-th variable from @('vars') with the
 <i>i</i>-th term from @('terms').  Note that @('vars') and @('terms') should
 have the same length.  (&quot;@('subcor')&quot; stands for &quot;substitute
 corresponding elements&quot;.)  Some simplification may be done; to avoid
 that, use @('fsubcor-var') (``fast substitute corresponding elements''),
 described above.</li>

 <li>@('(sublis-fn-simple alist term)'), @('(sublis-fn alist term
 bound-vars)'): Both of these apply the functional substitution, @('alist'), to
 the given term.  Thus in both cases, all keys of @('alist') are function
 symbols.  In the case of @('sublis-fn-simple'), each key of @('alist') is
 mapped to a function symbol; but for @('sublis-fn'), a key may instead be
 mapped to a legal @(see lambda) expression.  The other difference between the
 two functions is that for @('sublis-fn'), the formal @('bound-vars') is a list
 of variables, generally @('nil') at the top level.  For details see the Lisp
 comments in the ACL2 sources for function @('sublis-fn-rec') (which is more
 general than either @('sublis-fn-simple') and @('sublis-fn'), and is called by
 both of them to do the real work).</li>

 <li>@('(sublis-fn-lst-simple alist termlist)'): Apply the given functional
 substitution, @('alist'), to each term in @('termlist'), essentially by
 applying @('sublis-fn-simple') to alist and each such term.  See the
 description of @('sublis-fn-simple'), above.</li>

 <li>@('(sublis-var alist form)'): Substitute @('alist') into the @(see term),
 @('form').</li>

 <li>@('(subst-expr new old term)'): Substitute @('new') for @('old') in
 @('term'); all are assumed to be @(see term)s.  This function provides a
 slightly optimized version of equivalent function @('(subst-expr new old
 term)').  Also, the former causes an explicit error if @('old') is a quoted
 constant, and neither will search strictly inside a quoted subterm of
 @('old').</li>

 <li>@('(subst-var new old term)'): Substitute @('new') for @('old') in
 @('term'); all are assumed to be @(see term)s, but moreover, @('old') is
 assumed to be a variable.</li>

 <li>@('(symbol-class name w)'): For a function symbol, @('name'), of the ACL2
 @(see world) @('w'), return @(':program') if @('name') is in @(':')@(tsee
 program) mode, @(':common-lisp-compliant') is @('name') is @(see
 guard)-verified, and otherwise, @(':ideal').  If @('name') is the name of a
 theorem (more specifically, has a @(''theorem') property; see @(see getprop)),
 return @(':ideal') unless the theorem is guard-verified, in which case return
 @(':common-lisp-compliant').  Otherwise return @(':program').</li>

 <li>@('(termp x w)'): Is @('x') a @(see term) in logical @(see world)
 @('w')?</li>

 <li>@('(trans-eval form ctx state aok)'): Translate and then evaluate
 @('form').  See @(see trans-eval) for discussion and related utilities.</li>

 <li>@('translate'), @('translate1'), @('translate11'), @('translate-cmp'), and
 @('translate1-cmp'): Functions that translate user-level input to translated
 @(see term)s, as recognized by @('termp').  Note that these functions perform
 macroexpansion, which checks @(see guard)s on @(see primitive)s; see @(see
 safe-mode).</li>

 <li>@('(untranslate term iff-flg w)'): see @(see untranslate).</li>

 <li>@('(value x)'): This macro call expands to @('(mv nil x state)').  For
 related discussion, see @(see error-triple).</li>

 <li>@('(variablep x)'): For a @(tsee pseudo-termp) @('x'), return true iff
 @('x') is a variable, i.e., a symbol.</li>

 </ul>

 ")

(defxdoc |Subsumption of Induction Candidates in App Example|
  :parents (|Pages Written Especially for the Tours|)
  :short "Subsumption of Induction Candidates in App Example"
  :long "<p>After collecting induction suggestions from these three terms</p>

 <code>
 (app <b>a</b> b)

 (app <b>b</b> c)

 (app <b>a</b> (app b c))
 </code>

 <p>the system notices that the first and last suggest the same decomposition
 of @('a'): case split on whether @('a') is empty (i.e., @('(endp a)')), and in
 the case where it is not empty, recursively process @('(cdr a)').  So we are
 left with two ideas about how to induct:</p>

 <p>Decompose <b>a</b> as we would to unwind (app <b>a</b> b).</p>

 <p>Decompose <b>b</b> as we would to unwind (app <b>b</b> c).</p>")

(defxdoc |Suggested Inductions in the Associativity of App Example|
  :parents (|Pages Written Especially for the Tours|)
  :short "Suggested Inductions in the Associativity of App Example"
  :long "<p>To find a plausible induction argument, the system studies the
 recursions exhibited by the terms in the conjecture.</p>

 <p>Roughly speaking, a call of a recursive function ``suggests'' an induction
 if the argument position decomposed in recursion is occupied by a
 variable.</p>

 <p>In this conjecture, three terms suggest inductions:</p>

 <code>
 (app <b>a</b> b)

 (app <b>b</b> c)

 (app <b>a</b> (app b c))
 </code>

 <p>The variable recursively decomposed is indicated in <b>bold</b>.</p>")

(defxdoc |Symbolic Execution of Models|
  :parents (|Pages Written Especially for the Tours|)
  :short "Symbolic Execution of Models"
  :long "<p><see topic='@(url |Proving Theorems about Models|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>But ACL2 is more than a programming language.</p>

 <p>Initialize <b>x</b> to 5 and let <b>y</b> be <b>any legal value</b>.</p>

 <p><img src='res/tours/computing-machine-5xy.gif'></img></p>

 <p>Because ACL2 is a mathematical language, we can simplify the expression</p>

 @({
  (lookup 'z (mc (s 'mult 5 y) 29))
 })

 <p>and get (+ y y y y y).  This is <b>symbolic execution</b> because not all
 of the parameters are known.</p>

 <p><see topic='@(url |Proving Theorems about Models|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc table
  :parents (events)
  :short "User-managed tables"
  :long "@({
  Examples:
  (table tests 1 '(...))                ; set contents of tests[1] to '(...)
  (table tests 25)                      ; get contents of tests[25]
  (table tests)                         ; return table tests as an alist
  (table tests nil nil :clear)          ; clear table tests
  (table tests nil '((foo . 7)) :clear) ; set table tests to ((foo . 7))
  (table tests nil nil :guard)          ; fetch the table guard
  (table tests nil nil :guard term)     ; set the table guard

  General Form:
  (table table-name key-term value-term op term)
 })

 <p>where @('table-name') is a symbol that is the name of a (possibly new)
 table; @('key-term') and @('value-term'), if present, are arbitrary terms
 involving (at most) the variables @('WORLD') and @('ENS'); @('op'), if
 present, is one of the table operations below; and @('term'), if present, is a
 term.  @('Table') returns an ACL2 @(see error-triple).  The effect of
 @('table') on @(tsee state) depends on @('op') and how many arguments are
 presented.  Some invocations actually have no effect on the ACL2 @(see world)
 and hence an invocation of @('table') is not always an ``event''.  We explain
 below, after giving some background information.</p>

 <p><b>Important Note:</b> The @('table') forms above are calls of a macro that
 expand to involve the special variable @(tsee state).  This will prevent you
 from accessing a table from within a hint or theory where you do not have the
 @(tsee state) variable.  However, the form</p>

 @({
  (table-alist 'tests world)
 })

 <p>returns the alist representation of the table named @('test') in the given
 @(tsee world).  Often you have access to @('world').</p>

 <p>The ACL2 system provides ``tables'' by which the user can associate one
 object with another.  Tables are in essence just conventional association
 lists &mdash; lists of pairs &mdash; but the ACL2 environment provides a means
 of storing these lists in the ``ACL2 world'' of the current @(tsee state).
 The ACL2 user could accomplish the same ends by using ACL2 ``global
 variables''; however, limitations on global variable names are imposed to
 ensure ACL2's soundness.  Some features of the system use tables, and the user
 is invited to make free use of tables.  By convention, no user-defined table
 is important to ACL2's soundness.  Because tables are stored in the ACL2 @(see
 world) they are restored by @(tsee include-book) and undone by @(':')@(tsee
 ubt).  Many users of Nqthm requested a facility by which user data could be
 saved in Nqthm ``lib files'' and tables are ACL2's answer to that request.</p>

 <p>Abstractly, each table is an association list mapping ``keys'' to
 ``values.'' In addition, each table has a ``@(':guard'),'' which is a term
 that must be true of any key and value used.  By setting the @(':guard') on a
 table you may enforce an invariant on the objects in the table, e.g., that all
 keys are positive integers and all values are symbols.  Each table has a
 ``name,'' which must be a symbol.  Given a table name, the following
 operations can be performed on the table.</p>

 <p>@(':put') &mdash; associate a value with a key (possibly changing the value
 currently associated with that key).</p>

 <p>@(':get') &mdash; retrieve the value associated with a key (or nil if no
 value has been associated with that key).</p>

 <p>@(':alist') &mdash; return an alist showing all keys and non-nil values in
 the table.</p>

 <p>@(':clear') &mdash; clear the table (so that every value is nil), or if val
 is supplied then set table to that value (which must be an alist).</p>

 <p>@(':guard') &mdash; fetch or set the :guard of the table.</p>

 <p>When the operations above suggest that the table or its @(':guard') are
 modified, what is actually meant is that the current @(see state) is redefined
 so that in it, the affected table name has the appropriate properties.  in
 such cases, the @('table') form is an event (see @(see events)).  In the
 @(':put') case, if the key is already in the table and associated with the
 proposed value, then the @('table') event is redundant (see @(see
 redundant-events)).</p>

 <p>@('Table') forms are commonly typed by the user while interacting with the
 system.  @(':Put') and @(':get') forms are especially common.  Therefore, we
 have adopted a positional syntax that is intended to be convenient for most
 applications.  Essentially, some operations admit a ``short form'' of
 invocation.</p>

 @({
  (table name key-term value-term :put)   ; long form
  (table name key-term value-term)        ; short form
 })

 <p>evaluates the key- and value-terms, obtaining two objects that we call
 @('key') and @('value'), checks that the @('key') and @('value') satisfy the
 @(':guard') on the named table and then ``modifies'' the named table so that
 the value associated with @('key') is @('value').  When used like this,
 @('table') is actually an event in the sense that it changes the ACL2 @(see
 world).  In general, the forms that are evaluated to obtain the @('key') and
 @('value') may involve two variables: @('WORLD'), which is bound to the
 then-current @(see world); and @('ENS'), which is bound to the enabled
 structure representing the current theory.  (The enabled structure is passed
 as a formal parameter to many built-in functions; for example, see @(see
 system-utilities) for a description of built-in utilities @('enabled-numep')
 and @('enabled-runep').)  However, in the special case that the table in
 question is named @(tsee acl2-defaults-table), the @('key') and @('value')
 terms may not contain any variables.  Essentially, the keys and values used in
 @(see events) setting the @(tsee acl2-defaults-table) must be explicitly given
 constants.  See @(see acl2-defaults-table).</p>

 @({
  (table name key-term nil :get)          ; long form
  (table name key-term)                   ; short form
 })

 <p>evaluates the key-term (see note below), obtaining an object, @('key'), and
 returns the value associated with @('key') in the named table (or, @('nil') if
 there is no value associated with @('key')).  When used like this, @('table')
 is not an event; the value is simply returned.</p>

 @({
  (table name nil nil :alist)             ; long form
  (table name)                            ; short form
 })

 <p>returns an alist representing the named table; for every key in the table
 with a non-@('nil') associated value, the alist pairs the key and its value.
 The order in which the keys are presented is unspecified.  When used like
 this, @('table') is not an event; the alist is simply returned.</p>

 @({
  (table name nil val :clear)
 })

 <p>sets the named table to the alist @('val'), making the checks that
 @(':put') makes for each key and value of @('val').  When used like this,
 @('table') is an event because it changes the ACL2 @(see world).</p>

 @({
  (table name nil nil :guard)
 })

 <p>returns the translated form of the guard of the named table.</p>

 @({
  (table name nil nil :guard term)
 })

 <p>Provided the named table is empty and has not yet been assigned a
 @(':guard') and @('term') (which is not evaluated) is a term that mentions at
 most the variables @('KEY'), @('VAL'), @('WORLD'), and @('ENS'), this event
 sets the @(':guard') of the named table to @('term').  Whenever a subsequent
 @(':put') occurs, @('term') will be evaluated with @('KEY') bound to the key
 argument of the @(':put'), @('VAL') bound to the @('val') argument of the
 @(':put'), @('WORLD') bound to the then current @(see world), and @('ENS')
 bound to the enabled structure representing the current theory.  An error will
 be caused by the @(':put') if the result of the evaluation is @('nil').</p>

 <p>Note that it is not allowed to change the @(':guard') on a table once it
 has been explicitly set.  Before the @(':guard') is explicitly set, it is
 effectively just @('t').  After it is set it can be changed only by undoing
 the event that set it.  The purpose of this restriction is to prevent the user
 from changing the @(':guards') on tables provided by other people or the
 system.</p>

 <p>The intuition behind the @(':guard') mechanism on tables is to enforce
 invariants on the keys and values in a table, so that the values, say, can be
 used without run-time checking.  But if the @(':guard') of a table is
 sensitive to the ACL2 @(see world), it may be possible to cause some value in
 the table to cease satisfying the @(':guard') without doing any operations on
 the table.  Consider for example the @(':guard') ``no value in this table is
 the name of an event.'' As described, that is enforced each time a value is
 stored.  Thus, @(''bang') can be @(':put') in the table provided there is no
 event named @('bang').  But once it is in the table, there is nothing to
 prevent the user from defining @('bang') as a function, causing the table to
 contain a value that could not be @(':put') there anymore.  Observe that not
 all state-sensitive @(':guard')s suffer this problem.  The @(':guard') ``every
 value is an event name'' remains invariant, courtesy of the fact that undoing
 back through an event name in the table would necessarily undo the @(':put')
 of the name into the table.</p>

 <p>@('Table') was designed primarily for convenient top-level use.  Tables are
 not especially efficient.  Each table is represented by an alist stored on the
 property list of the table name.  @(':Get') is just a @('getprop') and @(tsee
 assoc-equal).  @(':Put') does a @('getprop') to the get the table alist, a
 @('put-assoc-equal') to record the new association, and a @('putprop') to
 store the new table alist &mdash; plus the overhead associated with
 @(':guard')s and undoable @(see events), and checking (for redundancy) if the
 key is already bound to its proposed value.  Note that there are never
 duplicate keys in the resulting @('alist'); in particular, when the operation
 @(':clear') is used to install new @('alist'), duplicate keys are removed from
 that alist.</p>

 <p>A table name may be any symbol whatsoever.  Symbols already in use as
 function or theorem names, for example, may be used as table names.  Symbols
 in use only as table names may be defined with @(tsee defun), etc.  Because
 there are no restrictions on the user's choice of table names, table names are
 not included among the logical names.  Thus, @(':pe name') will never display
 a table event (for a logical name other than @(':here')).  Either @(':pe
 name') will display a ``normal'' event such as @('(defun name ...)') or
 @('(defthm name ...)') or else @(':pe name') will cause an error indicating
 that @('name') is not a logical name.  This happens even if @('name') is in
 use as a table name.</p>")

(defxdoc take
  :parents (lists acl2-built-ins)
  :short "Initial segment (first n elements) of a list"
  :long "<p>For any natural number @('n') not exceeding the length of @('l'),
 @('(take n l)') collects the first @('n') elements of the list @('l').</p>

 <p>The following is a theorem (though it takes some effort, including lemmas,
 to get ACL2 to prove it):</p>

 @({
  (equal (length (take n l)) (nfix n))
 })

 <p>If @('n') is an integer greater than the length of @('l'), then @('take')
 pads the list with the appropriate number of @('nil') elements.  Thus, the
 following is also a theorem.</p>

 @({
  (implies (and (integerp n)
                (true-listp l)
                (<= (length l) n))
           (equal (take n l)
                  (append l (make-list (- n (length l))))))
 })

 <p>For related functions, see @(see nthcdr) and see @(see butlast).</p>

 <p>The @(see guard) for @('(take n l)') is that @('n') is a nonnegative
 integer and @('l') is a true list.</p>

 @(def take)")

(defxdoc talks
  :parents (acl2-tutorial)
  :short "Some talks about ACL2"
  :long "<p>The list below contains links to talks about ACL2.  This list may
 grow over time.  Please email the @(see acl2-help) mailing list if you find a
 broken link or if you care to contribute another link to a talk (or simply
 make the changes yourself if you have permission to do so on GitHub).</p>

 <ul>

 <li>Links to several introductory/overview talks on ACL2 may be found on the
 <a
 href='http://www.cs.utexas.edu/users/kaufmann/selected-presentations.html'>page
 of talks by Matt Kaufmann</a>, including <a
 href='http://www.cs.utexas.edu/users/kaufmann/visions-moore-kaufmann.pdf'>a
 general introductory talk on ACL2 by Matt Kaufmann and J Moore</a> from
 2006.</li>

 <li>Several introductory/overview talks on ACL2 by J Moore:

   <ul>

   <li><a
   href='http://www.cs.utexas.edu/users/moore/acl2/talks/big-proof-talks/'>Two
   talks given July 6 and 7, 2017</a>, at the <a
   href='https://www.newton.ac.uk/event/bpr'>Big Proof workshop</a> at the
   Isaac Newton Institute for Mathematical Sciences in Cambridge, England.  The
   first talk focuses on the role of mechanized proof,specifically ACL2, to
   verify hardware and software of interest to industry.  The second talk
   touches upon how the ACL2 prover works, how the user directs it, and some of
   the features of particular importance to its industrial applications.</li>

   <li><a
   href='http://www.cs.utexas.edu/users/moore/acl2/talks/royal-society/talk.pdf'>Industrial
   Hardware and Software Verification with ACL2</a>, presented at the Royal
   Society, London, in April, 2016 (co-authored with Warren A. Hunt, Jr., Matt
   Kaufmann, and Anna Slobodova).</li>

   <li>This page for <a
   href='http://www.cs.utexas.edu/users/moore/publications/talks/marktoberdorf-08/index.html'>Mechanized
   Operational Semantics</a> contains links not only to talks given at the
   Marktoberdorf Summer School (Germany, August, 2008) but also to supplemental
   materials.</li>

   </ul>
 </li>

 <li>The ``Talks'' section of <a
 href='http://www.cs.utexas.edu/users/hunt/index.html'>Warren Hunt's home
 page</a> has an annotated list of links to several talks about the use of ACL2
 for hardware specification and verification.</li>

 </ul>

 <p>Note that many talks are also available from the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/workshops.html'>ACL2
 Workshops</a> pages and on the <a
 href='http://www.cs.utexas.edu/users/moore/acl2/seminar/'>University of Texas
 ACL2 Seminar page</a>.</p>
 ")

(defxdoc tau-data
  :parents (tau-system)
  :short "To see what tau knows about a function symbol"
  :long "@({
  Examples:
  (tau-data binary-+)

  General Form:
  (tau-data fn)
 })

 <p>This macro returns a list structure that indicates what facts about the
 symbol @('fn') are known to the tau system.  @('Fn') should either be a
 function symbol or else a macro associated with @('fn'); see @(see
 macro-aliases-table).  See @(see introduction-to-the-tau-system) for
 background details.</p>

 <p>The list structure should be self-explanatory given the following brief
 comments.  The ``index'' of a function, when non-@('nil'), means the function
 is a monadic Boolean function treated by the tau system as a tau
 predicate.</p>

 <p>The ``positive'' and ``negative implicants'' are conjunctions that indicate
 the tau implied by the given one or its negation.</p>

 <p>The ``signatures'' entry is a formula indicating all the known signatures.
 If the signatures formula is @('T') it means there are no known signatures.
 (Signatures is the conjunction of all signature rules and the empty
 conjunction is @('T').)</p>

 <p>If you wish to see a long list of all the runes from which some tau
 information has been gleaned, evaluate @('(global-val 'tau-runes (w
 state))').</p>")

(defxdoc tau-database
  :parents (tau-system history)
  :short "To see the tau database as a (very large) object"
  :long "@({
  Example:
  (tau-database (w state))
 })

 <p>This function returns a large list object that shows in a human-readable
 way what the tau system knows about every function symbol.  It is supposed to
 be self-explanatory.  See @(see introduction-to-the-tau-system) for background
 details.</p>

 <p>If the output is not self-explanatory, please contact the implementors and
 we will improve the output or the documentation.</p>")

(defxdoc tau-interval-dom
  :parents (tau-system)
  :short "Access the domain of a tau interval"
  :long "<p>It is the case that</p>

 @({
  (tau-interval-dom (make-tau-interval dom lo-rel lo hi-rel hi)) = dom
 })

 <p>For a well-formed interval, @('dom') is one of the symbols @('INTEGERP'),
 @('RATIONALP'), @('ACL2-NUMBERP'), or @('NIL').  When the domain is @('NIL')
 there is no domain restriction.</p>

 <p>When the domain is @('INTEGERP'), there are additional constraints on the
 other components.  See @(see make-tau-interval).</p>")

(defxdoc tau-interval-hi
  :parents (tau-system)
  :short "Access the upper bound of a tau interval"
  :long "<p>It is the case that</p>

 @({
  (tau-interval-hi (make-tau-interval dom lo-rel lo hi-rel hi)) = hi
 })

 <p>For a well-formed interval, @('hi') is either @('nil'), denoting positive
 infinity, or a rational number giving the upper bound of the interval.  It
 must be the case that the upper bound is weakly above the lower bound of a
 well-formed interval.</p>

 <p>When the domain of an interval is @('INTEGERP'), there are additional
 constraints on the other components.  See @(see make-tau-interval).</p>")

(defxdoc tau-interval-hi-rel
  :parents (tau-system)
  :short "Access the upper bound relation of a tau interval"
  :long "<p>It is the case that</p>

 @({
  (tau-interval-hi-rel (make-tau-interval dom lo-rel lo hi-rel hi)) = hi-rel
 })

 <p>For a well-formed interval, @('hi-rel') is a Boolean, where @('t') denotes
 the @(tsee <) (strong inequality or ``less-than'') relation and @('nil')
 denotes @(tsee <=) (weak inequality or ``less-than-or-equal'') relation
 between the elements of the interval and the upper bound.</p>

 <p>When the domain of an interval is @('INTEGERP'), there are additional
 constraints on the other components.  See @(see make-tau-interval).</p>")

(defxdoc tau-interval-lo
  :parents (tau-system)
  :short "Access the lower bound of a tau interval"
  :long "<p>It is the case that</p>

 @({
  (tau-interval-lo (make-tau-interval dom lo-rel lo hi-rel hi)) = lo
 })

 <p>For a well-formed interval, @('lo') is either @('nil'), denoting negative
 infinity, or a rational number giving the lower bound of the interval.  It
 must be the case that the lower bound is weakly below the upper bound of a
 well-formed interval.</p>

 <p>When the domain of an interval is @('INTEGERP'), there are additional
 constraints on the other components.  See @(see make-tau-interval).</p>")

(defxdoc tau-interval-lo-rel
  :parents (tau-system)
  :short "Access the lower bound relation of a tau interval"
  :long "<p>It is the case that</p>

 @({
  (tau-interval-lo-rel (make-tau-interval dom lo-rel lo hi-rel hi)) = lo-rel
 })

 <p>For a well-formed interval, @('lo-rel') is a Boolean, where @('t') denotes
 the @(tsee <) (strong inequality or ``less-than'') relation and @('nil')
 denotes @(tsee <=) (weak inequality or ``less-than-or-equal'') relation
 between the lower bound and the elements of the interval.</p>

 <p>When the domain of an interval is @('INTEGERP'), there are additional
 constraints on the other components.  See @(see make-tau-interval).</p>")

(defxdoc tau-intervalp
  :parents (tau-system)
  :short "Boolean recognizer for tau intervals"
  :long "@({
  General Form:
  (tau-intervalp x)
 })

 <p>An interval is a structure of the form: @('(')<i>dom</i>
 @('(')<i>lo-rel</i> @('.')  <i>lo</i>@(')') @('.')  @('(')<i>hi-rel</i> @('.')
 <i>hi</i>@('))').  Every tau contains an interval used to represent the domain
 and the upper and lower bounds of the objects recognized by the tau.</p>

 <p>Restrictions on the components of an interval are as follows.  For an
 interpretation of the meaning of the components, see @(tsee in-tau-intervalp)
 or @(tsee make-tau-interval).</p>

 <p><i>Dom</i> (``domain'') must be one of four symbols: @('INTEGERP'),
 @('RATIONALP'), @('ACL2-NUMBERP'), or @('NIL').</p>

 <p>The two ``relations,'' <i>lo-rel</i> and <i>hi-rel</i>, must be
 Booleans.</p>

 <p><i>Lo</i> and <i>hi</i> must be either @('nil') or explicit rational
 numbers.  <i>Lo</i> must be no greater than <i>hi</i> (where @('nil')s
 represent negative or positive infinity for <i>lo</i> and <i>hi</i>
 respectively.</p>

 <p>Finally, if the <i>dom</i> is @('INTEGERP'), then both relations must
 @('nil') and <i>lo</i> and <i>hi</i> must be integers when they are
 non-@('nil').</p>

 <p>Recall that @(tsee make-tau-interval) constructs intervals.  The intervals
 it constructs are well-formed only if the arguments to @('make-tau-interval')
 satisfy the rules above; @('make-tau-interval') does not coerce or adjust its
 arguments in any way.  Thus, it can be (mis-)used to create non-intervals.
 Here are examples of @('tau-intervalp') using @('make-tau-interval').</p>

 @({
  ; integers: 0 <= x <= 10:
  (tau-intervalp (make-tau-interval 'INTEGERP nil 0 nil 10))      = t

  ; integers: 0 <= x (i.e., the natural numbers):
  (tau-intervalp (make-tau-interval 'INTEGERP nil 0 nil nil))     = t

  ; violations of domain rules:
  (tau-intervalp (make-tau-interval 'INTEGERP t 0 t 10))          = nil
  (tau-intervalp (make-tau-interval 'INTEGERP nil 0 nil 10/11))   = nil

  ; violation of rule that bounds must be rational if non-nil:
  (tau-intervalp (make-tau-interval 'ACL2-NUMBERP t 0 t #c(3 5))) = nil

  ; violation of rule that lo <= hi:
  (tau-intervalp (make-tau-interval 'ACL2-NUMBERP t 0 t -10))     = nil

  ; rationals: 0 < x <= 22/7:
  (tau-intervalp (make-tau-interval 'RATIONALP t 0 nil 22/7))     = t

  ; numbers: -10 < x < 10:
  (tau-intervalp (make-tau-interval 'ACL2-NUMBERP t -10 t 10))    = t

  ; any: -10 < x < 10:
  (tau-intervalp (make-tau-interval nil t -10 t 10))              = t

  : any:
  (tau-intervalp (make-tau-interval nil nil nil nil nil))         = t
 })

 <p>Note that the second-to-last interval, with domain @('nil') contains all
 non-numbers as well as numbers strictly between -10 and 10.  The reason is
 that the interval contains @('0') and all non-numbers are coerced to @('0') by
 the inequality functions.</p>

 <p>Note that the last interval contains all ACL2 objects.  It is called the
 ``universal interval.''</p>")

(defxdoc tau-status
  :parents (tau-system)
  :short "Query or set tau system status"
  :long "@({
  Examples:
  (tau-status)
  (tau-status :system t)
  (tau-status :auto-mode nil)
  (tau-status :system t :auto-mode nil)

  General Form:
  (tau-status :system a :auto-mode b)
 })

 <p>where @('a') and @('b') are Booleans.  Both keyword arguments are optional
 and they may be presented in either order.  Value @('a') controls whether the
 @(tsee tau-system) is used during subsequent proofs.  Value @('b') controls
 whether tau system rules are added automatically (``greedily'') when rules of
 other @(tsee rule-classes) are added.  If no arguments are supplied, this is
 not an event and just returns an @(see error-triple) indicating the current
 settings.  See @(see introduction-to-the-tau-system) for background
 details.</p>

 <p>The two flags are independent.  For example, the tau system may be disabled
 in proof attempts even though it is automatically (and silently) extending its
 database as rules of other classes are added.</p>

 <p>Flag (a) is actually toggled by enabling or disabling the @(':')@(tsee
 executable-counterpart) of @(tsee tau-system).  Flag (b) is toggled with the
 function @(tsee set-tau-auto-mode), which manipulates the @(tsee
 acl2-defaults-table).</p>

 <p>This macro expands into zero, one, or two @(see events), as required by the
 supplied values of flags @('a') and @('b').</p>

 <p>If no arguments are supplied the form is not an event and simply returns
 (as an @(see error-triple), @('(mv nil ans state)')) the current settings of
 the two flags.  For example:</p>

 @({
  ACL2 !>(tau-system)
   ((:SYSTEM NIL) (:AUTO-MODE T))
 })

 <p>intended to be self-explanatory.</p>")

(defxdoc tau-system
  :parents (rule-classes)
  :short "Make a rule for the ACL2 ``type checker''"
  :long "<p>This documentation topic describes the syntactic form of
 ``tau-system'' rules; these rules extend ACL2's ``type checker.''  For an
 introduction to the tau system, see @(see introduction-to-the-tau-system).</p>

 <p>There happens to be a <i>function</i> named @('tau-system'), defined as the
 identity function.  Its only role is to provide the rune
 @('(:EXECUTABLE-COUNTERPART TAU-SYSTEM)'), which is used to enable and disable
 the tau system.  Otherwise the function @('tau-system') has no purpose and we
 recommend that you avoid using it so you are free to enable and disable the
 tau system.</p>

 <p>When in the default (``greedy'') mode (see @(tsee set-tau-auto-mode)),
 every @(tsee defun) and every @(':corollary') (see @(':')@(tsee rule-classes))
 of every @(tsee defthm) stored as a rule <i>of any</i> @(':rule-class') is
 inspected to determine if it is of one of the forms below.  Rules of these
 forms are added to the tau database, even if they are not labeled as
 @(':tau-system') rules, e.g., a @(':')@(tsee rewrite) rule might contribute to
 the tau database!  To add a rule to the tau database without adding any other
 kind of rule, tag it with @(':')@(tsee rule-classes) @(':tau-system').  If a
 theorem has @(':')@(tsee rule-classes) @('nil'), it is not considered for the
 tau database.</p>

 <code>
 General Forms:
 <i>Boolean</i>:
 (booleanp (p v))

 <i>Eval</i>:
 (p 'const) or
 (p *const*)

 <i>Simple</i>:
 (implies (p v) (q v))

 <i>Conjunctive</i>:
 (implies (and (p1 v) ... (pk v)) (q v)), ; Here k must exceed 1.

 <i>Signature Form 1</i>:
 (implies (and (p1 x1) (p2 x2) ...)
          (q (fn x1 x2 ...)))

 <i>Signature Form 2</i>:
 (implies (and (p1 x1) (p2 x2) ...)
          (q (mv-nth 'n (fn x1 x2 ...))))

 <i>Bounder Form 1 (or Form 2)</i>:
 (implies (and (tau-intervalp i1)
               ...
               (or (equal (tau-interval-dom i1) 'dom1-1)
                   ...)
               ...
               (in-tau-intervalp x1 i1)
               ...)
          (and (tau-intervalp (bounder-fn i1 ...))
               (in-tau-intervalp <i>target</i>
                                 (bounder-fn i1 ...))))

 where <i>target</i> is
 (fn x1 ... y1 ...)             in <i>Form 1</i>, and
 (mv-nth 'n (fn x1 ... y1 ...)) in <i>Form 2</i>

 <i>Big Switch</i>:
 (equal (fn . formals) body)

 <i>MV-NTH Synonym</i>:
 (equal (nth-alt x y) (mv-nth x y)) or
 (equal (mv-nth x y) (nth-alt x y))
 </code>

 <p>The symbols @('p'), @('q'), @('p1'), etc., denote monadic (one-argument)
 Boolean-valued function symbols, or equalities in which one argument is
 constant, arithmetic comparisons in which one argument is a rational or
 integer constant, or the logical negations of such terms.  By ``equalities''
 we allow @(tsee EQUAL), @(tsee EQ), @(tsee EQL), and @(tsee =).  By
 ``arithmetic comparison'' we mean @(tsee <), @(tsee <=), @(tsee >=), or @(tsee
 >).  Any of these tau predicates may appear negated.</p>

 <p>The notation @('(p v)') above might stand for any one of:</p>

 @({
  (INTEGERP X)
  (EQUAL V 'MONDAY)
  (<= I 16)
  (NOT (EQUAL X 'SUNDAY))
 })

 <p>The different rule forms above affect different aspects of the tau system.
 We discuss each form in more detail below.</p>

 <p>The documentation below is written as though the tau system is in auto
 mode!  To insure that the only rules added to the tau system are those
 explicitly assigned to @(':rule-class') @(':tau-system'), you should use
 @(tsee set-tau-auto-mode) to select manual mode.</p>

 <code>
 General Form: <i>Boolean</i>:
 (booleanp (p v))
 </code>

 <p>Here @('p') must be a function symbol and @('v') must be a variable.  Such
 a @(':tau-system') rule adds @('p') to the list of tau predicates.  If @('p')
 was recognized as Boolean when it was defined, there is no need to state this
 rule.  This form is needed if you define a monadic Boolean function in such a
 way that the system does not recognize that it is Boolean.</p>

 <code>
 General Form: <i>Eval</i>:
 (p 'const) or
 (p *const*)
 </code>

 <p>Here @('p') must be a function symbol.  In addition, recall that these
 general tau predicate forms may appear negated.  So the form above includes
 such theorems as @('(NOT (GOOD-STATEP *INITIAL-STATE*))').  A theorem of this
 form thus records whether a named predicate is true or false on the given
 constant.</p>

 <p>Generally, when the tau system must determine whether an enabled tau
 predicate is true or false on a constant, it simply evaluates the predicate on
 the constant.  This can be impossible or very inefficient if @('p') is not
 defined but constrained, or if @('p') is defined in a hard-to-compute way
 (e.g., @('(defun p (x) (evenp (ack x x)))') where @('ack') is the Ackermann
 function), or perhaps if the constant is very large.  By proving a
 @(':tau-system') rule of Eval form, you cause the tau system to note the value
 of the predicate on the constant and henceforth to look it up instead of
 evaluating the definition.</p>

 <p>A difficulty, however, is determining that a slow down is due to the
 evaluation of tau predicates and not some other reason.  The first step is
 determining that tau is slowing the proof down.  See @(tsee time-tracker-tau)
 for an explanation of @('TIME-TRACKER-NOTE')s output during some proofs
 involving tau reasoning.  These notes can alert you to the fact that
 significant amounts of time are being spent in the tau system.  @(tsee
 Time-tracker-tau) gives some ways of determining whether tau predicate
 evaluation is involved.  (If worse comes to worst, consider the following
 hack: In the ACL2 source file @('tau.lisp'), immediately after the definition
 of the system function @('ev-fncall-w-tau-recog'), there is a comment which
 contains some raw Lisp code that can be used to investigate whether tau's use
 of evaluation on constants is causing a problem.)  However, once a recognizer
 and the constants on which it is being evaluated are identified, the tau
 system can be sped up by proving Eval rules to pre-compute and store the
 values of the recognizer on those constants.  Alternatively, at the possible
 loss of some completeness in the tau system, the executable-counterpart of the
 recognizer can be disabled.</p>

 <code>
 General Form: <i>Simple</i>:
 (implies (p v) (q v))
 </code>

 <p>Here @('v') must be a variable symbol.  This rule builds-in the information
 that anything satisfying @('p') must also satisfy @('q'), i.e., the ``type''
 @('q') includes the ``type'' @('p').  Recall that the forms may be negated.
 Most of the time, @('p') and @('q') will be predicate symbols but it is
 possible they will be equalities- or inequalities-with-constants.  Examples of
 Simple rules include the following, which are in fact built-in:</p>

 @({
  (implies (natp x) (integerp x))
  (implies (integerp x) (rationalp x))
  (implies (integerp x) (not (true-listp x)))
  (implies (natp x) (not (< x 0)))
  (implies (symbol-alistp x) (alistp x))
 })

 <p>Because the tau system records the transitive closure of the Simple rules,
 any time a term is known to satisfy @('natp') it is also known to satisfy
 @('integerp') and @('rationalp'), and known not to satisfy @('true-listp'),
 and known to be non-negative.</p>

 <code>
 General Form: <i>Conjunctive</i>:
 (implies (and (p1 v) ... (pk v)) (q v)), ; Here k must exceed 1.
 </code>

 <p>The @('pi') and @('q') may be any tau predicates or their negations, @('v')
 must be a variable symbol, and @('i') must exceed 1 or else this is a Simple
 rule.  An obvious operational interpretation of this rule is that if an object
 is known to satisfy all of the @('pi'), then it is known to satisfy @('q').
 However, the actual interpretation is more general.  For example, if an object
 is known to satisfy all but one of the @('pi') and is known not to satisfy
 @('q'), then the object is known not to satisfy the ``missing'' @('pi').</p>

 <p>For example, the following Conjunctive rule allows tau to conclude that if
 weekday @('D') is not @('MON'), @('TUE'), @('THU') or @('FRI'), then it is
 @('WED'):</p>

 @({
  (implies (and (weekdayp d)
                (not (eq d 'MON))
                (not (eq d 'TUE))
                (not (eq d 'WED))
                (not (eq d 'THU)))
           (eq d 'FRI))
 })

 <p>The tau database is not closed under conjunctive rules; they are applied
 dynamically.</p>

 <code>
 General Form: <i>Signature Form 1</i>:
 (implies (and (p1 x1) (p2 x2) ... (pn xn) dep-hyp)
          (q (fn x1 x2 ... xn)))
 </code>

 <p>The @('pi') and @('q') may be any tau predicates or their negations,
 @('fn') must be a function symbol of arity @('n'), the @('xi') must be
 distinct variable symbols and @('dep-hyp') may be any term, provided it is not
 of the @('(pi xi)') shape and the only the variables in it are the
 @('xi').</p>

 <p>The Signature form actually allows multiple tau predicates to be applied to
 each variable, e.g., x1 might be required to be both an @('INTEGERP') and
 @('EVENP').  The Signature form allows there to be multiple hypotheses
 classified as @('dep-hyp')s, i.e., not fitting any of the previous shapes, and
 they are implicitly just conjoined.  The name ``dep-hyp'' is an abbreviation
 of ``dependent hypothesis'' and stems from the fact they often express
 relations between several of the function's inputs rather than type-like
 constraints on individual inputs.</p>

 <p>A Signature rule informs tau that the function @('fn') returns an object
 satisfying @('q') provided that the arguments satisfy the respective @('pi')
 and provided that @('dep-hyp') occurs in the current context.  Note: to be
 precise, dependent hypotheses are relieved only by applying ACL2's most
 primitive form of reasoning, @(see type-set).  In particular, tau reasoning is
 not used to establish dependent hypotheses.  The presence of a @('dep-hyp') in
 a signature rule may severely restrict its applicability.  We discuss this
 after showing a few mundane examples.</p>

 <p>An example Signature rule is</p>

 @({
  (implies (and (integer-listp x)
                (integer-listp y))
           (integer-listp (append x y)))
 })

 <p>Of course, a function may have multiple signatures:</p>

 @({
  (implies (and (symbol-listp x)
                (symbol-listp y))
           (symbol-listp (append x y)))
 })

 <p>Here is a Signature rule for the function @('pairlis$'):</p>

 @({
  (implies (and (symbol-listp x)
                (integer-listp y))
           (symbol-alistp (pairlis$ x y)))
 })

 <p>The tau system can consequently check this theorem by composing the last
 two rules shown and exploiting Simple rule stating that symbol-alists are also
 alists:</p>

 @({
  (thm (implies (and (symbol-listp a)
                     (symbol-listp b)
                     (integer-listp y))
                (alistp (pairlis$ (append a b) y))))
 })

 <p>Since @('a') and @('b') are known to be lists of symbols and a signature
 for @('append') is that it preserves that predicate, the first argument to the
 @('pairlis$') expression is known to be a list of symbols.  This means the
 Signature rule for @('pairlis$') tells us the result is a @('symbol-alistp'),
 but the previously mentioned Simple rule, @('(implies (symbol-alistp x)
 (alistp x))'), tells us the result is also an @('alistp').</p>

 <p>When a Signature rule has an @('dep-hyp'), that hypothesis is not an
 expression in the tau system.  Tau is not used to check that hypothesis.
 Instead, tau uses the more primitive @(see type-set) mechanism of ACL2.  Here
 is an example of a Signature rule with a @('dep-hyp'):</p>

 @({
  (implies (and (natp n)
                (integer-listp a)
                (< n (len a)))
           (integerp (nth n a)))
 })

 <p>Note that the last hypothesis is a dependent hypothesis: it is not a tau
 predicate but a relationship between @('n') and @('a').  It is relieved by
 @(see type-set).  If one is trying to compute the signature of an @('(nth n
 a)') expression in a context in which @('(< n (len a))') is explicitly
 assumed, then this mechanism would establish the dependent hypothesis.  But
 one can easily imagine an almost identical context where, say @('(< n (len
 (rev a)))') is explicitly assumed.  In that context, the Signature rule would
 not be fired because @(tsee type-set) cannot establish @('(< n (len a))') from
 @('(< n (len (rev a)))'), even though it would be easily proved by rewriting
 using the theorem @('(equal (len (rev a)) (len a))').</p>

 <p>Note also that if this signature could be phrased in a way that eliminates
 the dependency between @('n') and @('a') it would be more effective.  For
 example, here is a related Signature rule without a dependent hypothesis:</p>

 @({
  (implies (and (natp n)
                (register-filep a)
                (< n 16))
           (integerp (nth n a)))
 })

 <p>In this theorem we require only that @('n') be less than 16, which is a tau
 predicate and hence just an additional tau constraint on @('n').</p>

 <code>
 General Form: <i>Signature Form 2</i>:
 (implies (and (p1 x1) (p2 x2) ... (pn xn) dep-hyp)

          (q (mv-nth 'n (fn x1 x2 ... xn))))
 </code>

 <p>This form of signature rule is just like form 1 except that it is useful
 for functions that return multiple-values and allows us to ``type-check''
 their individual outputs.</p>

 <code>
 General Form: <i>Bounder Forms 1 and 2</i>:
 (implies (and (tau-intervalp i1)
               ...
               (or (equal (tau-interval-dom i1) 'dom1-1)
                   ...)
               ...
               (in-tau-intervalp x1 i1)
               ...)
          (and (tau-intervalp (bounder-fn i1 ...))
               (in-tau-intervalp <i>target</i>
                                 (bounder-fn i1 ...))))
 </code>

 <p>where <i>target</i> is either @('(fn x1 ... y1 ...)') in <i>Form 1</i> or
 @('(mv-nth 'n (fn x1 ... y1 ...))') in <i>Form 2</i>.</p>

 <p>This form is for advanced users only and the schema given above is just a
 reminder of the general shape.  A ``bounder'' for a given function symbol,
 @('fn'), is a function symbol @('bounder-fn') that computes an interval
 containing @('(fn x1 ... y1 ...)') (or its @('n')th component in the case of
 Form 2 rules) from the intervals containing certain of the arguments of
 @('fn').  The correctness theorem for a bounder function informs the tau
 system that bounds for @('fn') are computed by @('bounder-fn') and sets up the
 correspondence between the relevant arguments, @('xi'), of @('fn') and the
 intervals containing those arguments, @('ii') to which @('bounder-fn') is
 applied.  When the tau system computes the tau for a call of @('fn'), it
 computes the tau of the relevant arguments and applies the bounder to the
 intervals of those tau.  This provides a domain and upper and/or lower bounds
 for the value of the term.  The tau system then further augments that with
 signature rules.  See @(see bounders) for details on intervals, bounders, and
 bounder correctness theorems.</p>

 <code>
 General Form: <i>Big Switch</i>:
 (equal (fn . formals) body)
 </code>

 <p>In the Big Switch form, @('fn') must be a function symbol, @('formals')
 must be a list of distinct variable symbols, and @('body') must be a ``big
 switch'' term, i.e., one that case splits on tau predicates about a single
 variable and produces a term not involving that variable.  An example of a Big
 Switch rule is</p>

 @({
  (equal (conditional-type x y)
         (if (consp x)
             (consp y)
             (integerp y)))
 })

 <p>The idea is that the tau system can treat calls of @('conditional-type') as
 a tau-predicate after determining the tau of an argument.</p>

 <p>Since equality-to-constants are tau predicates, a more common example of a
 Big Switch rule is</p>

 @({
  (equal (dtypep x expr)
         (case x
               (STMT (stmt-typep expr))
               (EXPR (expr-typep expr))
               (MODULE (module-typep expr))
               (otherwise nil)))
 })

 <p>This is because @('(case x (STMT ...) ...)') macroexpands in ACL2 to @('(if
 (eql x 'STMT) ... ...)') and @('(eql x 'STMT)') is a tau predicate about
 @('x').</p>

 <p>Big Switch rules are recognized when a function is defined (if tau is in
 automatic mode).  They generally do not have to be proved explicitly, though
 they might be when mutual recursion is involved.  Only the first detected Big
 Switch rule about a function @('fn') is recognized.</p>

 <code>
 General Form: <i>MV-NTH Synonym</i>:
 (equal (nth-alt x y) (mv-nth x y)) or
 (equal (mv-nth x y) (nth-alt x y))
 </code>

 <p>Rules of this form just tell the tau system that the user-defined function
 @('nth-alt') is synonymous with the ACL2 primitive function @('mv-nth').
 Because ACL2's rewriter gives special handling to @('mv-nth'), users sometimes
 define their own versions of that function so they can disable them and
 control rewriting better.  By revealing to the tau system that such a synonym
 has been introduced you allow Signature rules of Form 2 to be used.</p>")

(defxdoc tenth
  :parents (nth acl2-built-ins)
  :short "Tenth member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc term
  :parents (miscellaneous)
  :short "The three senses of well-formed ACL2 expressions or formulas"
  :long "<p>Also see @(see untranslate) for a relevant utility (and a more
 abbreviated explanation of terms).</p>

 @({
  Examples of Terms:
  (cond ((caar x) (cons t x)) (t 0))   ; an untranslated term

  (if (car (car x)) (cons 't x) '0)    ; a translated term

  (car (cons x y) 'nil v)              ; a pseudo-term
 })

 <p>In traditional first-order predicate calculus a ``term'' is a syntactic
 entity denoting some object in the universe of individuals.  Often, for
 example, the syntactic characterization of a term is that it is either a
 variable symbol or the application of a function symbol to the appropriate
 number of argument terms.  Traditionally, ``atomic formulas'' are built from
 terms with predicate symbols such as ``equal'' and ``member;'' ``formulas''
 are then built from atomic formulas with propositional ``operators'' like
 ``not,'' ``and,'' and ``implies.'' Theorems are formulas.  Theorems are
 ``valid'' in the sense that the value of a theorem is true, in any model of
 the axioms and under all possible assignments of individuals to variables.</p>

 <p>However, in ACL2, terms are used in place of both atomic formulas and
 formulas.  ACL2 does not have predicate symbols or propositional operators as
 distinguished syntactic entities.  The ACL2 universe of individuals includes a
 ``true'' object (denoted by @('t')) and a ``false'' object (denoted by
 @('nil')), predicates and propositional operators are functions that return
 these objects.  Theorems in ACL2 are terms and the ``validity'' of a term
 means that, under no assignment to the variables does the term evaluate to
 @('nil').</p>

 <p>We use the word ``term'' in ACL2 in three distinct senses.  We will speak
 of ``translated'' terms, ``untranslated'' terms, and ``pseudo-'' terms.</p>

 <p><i>Translated Terms: The Strict Sense and Internal Form</i></p>

 <p>In its most strict sense, a ``term'' is either a legal variable symbol, a
 quoted constant, or the application of an n-ary function symbol or closed
 @('lambda') expression to a true list of n terms.</p>

 <p>The legal variable symbols are symbols other than @('t') or @('nil') which
 are not in the keyword package, do not start with ampersand, do not start and
 end with asterisks, and if in the main Lisp package, do not violate an
 appropriate restriction (see @(see name)).</p>

 <p>Quoted constants are expressions of the form @('(quote x)'), where @('x')
 is any ACL2 object.  Such expressions may also be written @(''x').</p>

 <p>Closed @('lambda') expressions are expressions of the form @('(lambda (v1
 ... vn) body)') where the @('vi') are distinct legal variable symbols,
 @('body') is a term, and the only free variables in @('body') are among the
 @('vi').</p>

 <p>The function @('termp'), which takes two arguments, an alleged term @('x')
 and a logical world @('w') (see @(see world)), recognizes terms of a given
 extension of the logic.  @('Termp') is defined in @(':')@(tsee program) mode.
 Its definition may be inspected with @(':')@(tsee pe) @('termp') for a
 complete specification of what we mean by ``term'' in the most strict sense.
 Most ACL2 term-processing functions deal with terms in this strict sense and
 use @('termp') as a @(see guard).  That is, the ``internal form'' of a term
 satisfies @('termp'), the strict sense of the word ``term.''</p>

 <p><i>Untranslated Terms: What the User Types</i></p>

 <p>While terms in the strict sense are easy to explore (because their
 structure is so regular and simple) they can be cumbersome to type.  Thus,
 ACL2 supports a more sugary syntax that includes uses of macros and constant
 symbols.  Very roughly speaking, macros are functions that produce terms as
 their results.  Constants are symbols that are associated with quoted objects.
 Terms in this sugary syntax are ``translated'' to terms in the strict sense;
 the sugary syntax is more often called ``untranslated.''  Roughly speaking,
 translation just implements macroexpansion, the replacement of constant
 symbols by their quoted values, and the checking of all the rules governing
 the strict sense of ``term.''</p>

 <p>More precisely, macro symbols are as described in the documentation for
 @(tsee defmacro).  A macro, @('mac'), can be thought of as a function,
 @('mac-fn'), from ACL2 objects to an ACL2 object to be treated as an
 untranslated term.  For example, @(tsee caar) is defined as a macro symbol;
 the associated macro function maps the object @('x') into the object @('(car
 (car x))').  A macro form is a ``call'' of a macro symbol, i.e., a list whose
 @(tsee car) is the macro symbol and whose @(tsee cdr) is an arbitrary true
 list of objects, used as a term.  Macroexpansion is the process of replacing
 in an untranslated term every occurrence of a macro form by the result of
 applying the macro function to the appropriate arguments.  The ``appropriate''
 arguments are determined by the exact form of the definition of the macro;
 macros support positional, keyword, optional and other kinds of arguments.
 See @(see defmacro).</p>

 <p>In addition to macroexpansion and constant symbol dereferencing,
 translation implements the mapping of @(tsee let) and @(tsee let*) forms into
 applications of @('lambda') expressions and closes @('lambda') expressions
 containing free variables.  Thus, the translation of</p>

 @({
  (let ((x (1+ i))) (cons x k))
 })

 <p>can be seen as a two-step process that first produces</p>

 @({
  ((lambda (x) (cons x k)) (1+ i))
 })

 <p>and then</p>

 @({
  ((lambda (x k) (cons x k)) (1+ i) k) .
 })

 <p>Observe that the body of the @(tsee let) and of the first @('lambda')
 expression contains a free @('k') which is finally bound and passed into the
 second @('lambda') expression.</p>

 <p>Translation also maps @(tsee flet) forms into applications of @('lambda')
 expressions.  See @(see flet).</p>

 <p>When we say, of an event-level function such as @(tsee defun) or @(tsee
 defthm), that some argument ``must be a term'' we mean an untranslated term.
 The event functions translate their term-like arguments.</p>

 <p>To better understand the mapping between untranslated terms and translated
 terms it is convenient to use the keyword command @(':')@(tsee trans) to see
 examples of translations.  See @(see trans) and also see @(see trans1).</p>

 <p>Finally, we note that the theorem prover prints terms in untranslated form.
 But there can be more than one correct untranslated term corresponding to a
 given translated term.  For example, the translated term @('(if x y 'nil)')
 can be untranslated as @('(if x y nil)') and can also be untranslated as
 @('(and x y)').  The theorem prover attempts to print an untranslated term
 that is as helpful to the user as possible.  In particular, consider a term of
 the form @('(nth k st)') where @('st') is a single-threaded object (see @(see
 stobj)) and the @('kth') accessor of @('st') is, say, @('kn').  The theorem
 prover typically would expand @('(kn st)') to @('(nth k st)').  If @('k') is
 large then it could be difficult for the user to make sense out of a proof
 transcript that mentions the expanded term.  Fortunately, the untranslation of
 @('(nth k st)') would be @('(nth *kn* st)'); here @('*kn*') would be a
 constant (see @(see defconst)) added by the @(tsee defstobj) event introducing
 @('st'), defined to have value @('k').  The user can extend this user-friendly
 style of printing applications of @(tsee nth) to stobjs; see @(see
 add-nth-alias).  These remarks about printing applications of function @(tsee
 nth) extend naturally to function @(tsee update-nth).  Moreover, the prover
 will attempt to treat terms as @(see stobj)s for the above purpose when
 appropriate.  For example, if function @('foo') has @(see signature) @('((foo
 * st) => (mv * * * st))'), where @('st') is introduced with @('(defstobj st f0
 f1)'), then the @(see term) @('(nth '1 (mv-nth '3 (foo x st0)))') will be
 printed as @('(nth *f1* (mv-nth 3 (foo x st0)))').</p>

 <p><i>Pseudo-Terms: A Common Guard for Metafunctions</i></p>

 <p>Because @('termp') is defined in @(':')@(tsee program) mode, it cannot be
 used effectively in conjectures to be proved.  Furthermore, from the
 perspective of merely guarding a term processing function, @('termp') often
 checks more than is required.  Finally, because @('termp') requires the
 logical @(see world) as one of its arguments it is impossible to use
 @('termp') as a @(see guard) in places where the logical @(see world) is not
 itself one of the arguments.</p>

 <p>For these reasons we support the idea of ``pseudo-terms.''  A pseudo-term
 is either a symbol (but not necessarily one having the syntax of a legal
 variable symbol), a true list of length 2 beginning with @('quote'), or the
 ``application of'' a symbol or pseudo @('lambda') expression to a true list of
 pseudo-terms.  A pseudo @('lambda') expression is an expression of the form
 @('(lambda (v1 ... vn) body)') where the @('vi') are all symbols and @('body')
 is a pseudo-term.</p>

 <p>Pseudo-terms are recognized by the unary function @(tsee pseudo-termp).  If
 @('(termp x w)') is true, then @('(pseudo-termp x)') is true.  However, if
 @('x') fails to be a (strict) term it may nevertheless still be a pseudo-term.
 For example, @('(car a b)') is not a term, because @(tsee car) is applied to
 the wrong number of arguments, but it is a pseudo-term.</p>

 <p>The structures recognized by @(tsee pseudo-termp) can be recursively
 explored with the same simplicity that terms can be.  In particular, if @('x')
 is not a @('variablep') or an @('fquotep'), then @('(ffn-symb x)') is the
 function (@('symbol') or @('lambda') expression) and @('(fargs x)') is the
 list of argument pseudo-terms.  A metafunction (see @(see meta)) or
 clause-processor (see @(see clause-processor)) may use @(tsee pseudo-termp) as
 the @(see guard).</p>")

(defxdoc term-list-listp
  :parents (acl2-built-ins)
  :short "recognizer for a list of clauses"
  :long "@({
  Example:
  (term-list-listp
   '(((NOT (ENDP X)) (NATP (LEN X)))
     ((ENDP X) (NOT (NATP (LEN (CDR X)))) (NATP (LEN X))))
   (w state))

  General Form:
  (term-list-listp x w)
 })

 <p>where @('x') is any ACL2 object and @('w') is an ACL2 logical @(see world).
 The result is @('t') or @('nil') according to whether @('x') is a true list of
 true lists of quotations of well-formed terms in @('w').</p>

 <p>This function is the standard ACL2 idiom for recognizing a ``set of
 clauses.''  See @(tsee clause-processor).  Each clause processor is supposed
 to take a clause (i.e., @('term-listp')) as input and yield a list of
 clauses (i.e., @('term-list-listp')) as output.  When a clause processor is
 run by the theorem prover its input is guaranteed to be a well-formed clause
 by invariants maintained by ACL2.  But its output is checked by an explicit
 call to this function unless the user has proved that the clause processor
 always returns a list of clauses (see @(see well-formedness-guarantee)) or has
 taken the risk of disabling the runtime test with @(tsee
 set-skip-meta-termp-checks).</p>

 @(def term-list-listp)")

(defxdoc term-listp
  :parents (acl2-built-ins)
  :short "recognizer for a list of quotations of terms and of clauses"
  :long "@({
  Example:
  (term-listp '((ZP X) 'NIL (CONS X Y)) (w state))

  General Form:
  (term-listp x w)
 })

 <p>where @('x') is any ACL2 object and @('w') is an ACL2 logical @(see world).
 The result is @('t') or @('nil') according to whether @('x') is a true list of
 quotations of well-formed terms in @('w').</p>

 <p>This function is used in the definition of @(tsee termp).  In addition,
 @('term-listp') is the standard ACL2 idiom for recognizing a clause (``set of
 literals'').  See @(tsee clause-processor).  Each clause processor is supposed
 to take a clause (i.e., @('term-listp')) as input and yield a list of
 clauses (i.e., @(tsee term-list-listp)) as output.  When a clause processor is
 run by the theorem prover its input is guaranteed to be a well-formed clause
 by invariants maintained by ACL2.  But its output is checked by an explicit
 call of @(tsee term-list-listp) unless the user has proved that the clause
 processor always returns a list of clauses (see @(see
 well-formedness-guarantee)) or has taken the risk of disabling the runtime
 test with @(tsee set-skip-meta-termp-checks).</p>

 <p>@(tsee Term-listp) is mutually recursive with @(tsee termp).</p>

 @(def term-listp)")

(defxdoc term-order
  :parents (term acl2-built-ins)
  :short "The ordering relation on terms used by ACL2"
  :long "<p>ACL2 must occasionally choose which of two terms is syntactically
 smaller.  The need for such a choice arises, for example, when using equality
 hypotheses in conjectures (the smaller term is substituted for the larger
 elsewhere in the formula), in stopping loops in permutative rewrite rules
 (see @(see loop-stopper)), and in choosing the order in which to try to cancel
 the addends in linear arithmetic inequalities.  When this notion of syntactic
 size is needed, ACL2 uses ``term order.''  Popularly speaking, term order is
 just a lexicographic ordering on terms.  But the situation is actually more
 complicated.</p>

 <p>We define term order only with respect to terms in translated form.  See
 @(see trans).  Constants are viewed as built up by <i>pseudo-function</i>
 applications, as described at the end of this documentation.</p>

 <p>@('Term1') comes before @('term2') in the term order iff</p>

 <blockquote>

 <p>(a) the number of variable occurrences in @('term1') is less than that in
 @('term2'), or</p>

 <p>(b) the numbers of variable occurrences in the two terms are equal but the
 number of function applications in @('term1') is less than that in @('term2'),
 or</p>

 <p>(c) the numbers of variable occurrences in the two terms are equal, the
 numbers of functions applications in the two terms are equal, but
 pseudo-function application count for @('term1') is less than that for
 @('term2'), or</p>

 <p>(d) the numbers of variable occurrences in the two terms are equal, the
 numbers of functions applications in the two terms are equal, the
 pseudo-function application counts for the two terms are equal, and @('term1')
 comes before @('term2') in a lexicographic ordering, @(tsee lexorder), based
 their structure as Lisp objects: see @(see lexorder).</p>

 </blockquote>

 <p>The function @('term-order'), when applied to the translations of two ACL2
 terms, returns @('t') iff the first is ``less than or equal'' to the second in
 the term order.</p>

 <p>By ``number of variable occurrences'' we do not mean ``number of distinct
 variables'' but ``number of times a variable symbol is mentioned.''  @('(Cons
 x x)') has two variable occurrences, not one.  Thus, perhaps
 counterintuitively, a large term that contains only one variable occurrence,
 e.g., @('(standard-char-p (car (reverse x)))') comes before @('(cons x x)') in
 the term order.</p>

 <p>Since constants contain no variable occurrences and non-constant
 expressions must contain at least one variable occurrence, constants come
 before non-constants in the term order, no matter how large the constants.
 For example, the list constant</p>

 @({
  '(monday tuesday wednesday thursday friday)
 })

 <p>comes before @('x') in the term order.  Because term order is involved in
 the control of permutative rewrite rules and used to shift smaller terms to
 the left, a set of permutative rules designed to allow the permutation of any
 two tips in a tree representing the nested application of some function will
 always move the constants into the left-most tips.  Thus,</p>

 @({
  (+ x 3 (car (reverse klst)) (dx i j)) ,
 })

 <p>which in translated form is</p>

 @({
  (binary-+ x
            (binary-+ '3
                      (binary-+ (dx i j)
                                (car (reverse klst))))),
 })

 <p>will be permuted under the built-in commutativity rules to</p>

 @({
  (binary-+ '3
            (binary-+ x
                      (binary-+ (car (reverse klst))
                                (dx i j))))
 })

 <p>or</p>

 @({
  (+ 3 x (car (reverse klst)) (dx i j)).
 })

 <p>Two terms with the same numbers of variable occurrences and function
 applications and the same pseudo-function application count are ordered by
 lexicographic means, based on their structures.  See @(see lexorder).  Thus,
 if two terms @('(member ...)') and @('(reverse ...)') contain the same numbers
 of variable occurrences and function applications, and no quoted constants,
 then the @(tsee member) term is first in the term order because @(tsee member)
 comes before @(tsee reverse) in the term order (which is here reduced to
 alphabetic ordering).</p>

 <p>It remains to discuss the notion of <i>pseudo-function application
 count</i>.</p>

 <p>Clearly, two constants are ordered using cases (c) and (d) of term order,
 since they each contain 0 variable occurrences and no function calls.  This
 raises the question ``How many function applications are in a constant?''
 Because we regard the number of function applications as a more fundamental
 measure of the size of a constant than lexicographic considerations, we
 decided that for the purposes of term order, constants would be seen as being
 built by primitive constructor functions.  These constructor functions are not
 actually defined in ACL2 but merely imagined for the purposes of term order.
 We here use suggestive names for these imagined functions, ignoring entirely
 the prior use of these names within ACL2.  The imagined applications of these
 functions are what we refer to as <i>pseudo-function</i> applications.</p>

 <p>The constant function @('z') constructs @('0').  Positive integers are
 constructed from @('(z)') by the successor function, @('s').  Thus @('2') is
 @('(s (s (z)))') and contains three function applications.  @('100') contains
 one hundred and one applications.  Negative integers are constructed from
 their positive counterparts by @(tsee -).  Thus, @('-2') is @('(- (s (s
 (z))))') and has four applications.  Ratios are constructed by the dyadic
 function @(tsee /).  Thus, @('-1/2') is</p>

 @({
  (/ (- (s (z))) (s (s (z))))
 })

 <p>and contains seven applications.  Complex rationals are similarly
 constructed from rationals.  All character objects are considered primitive
 and are constructed by constant functions of the same name.  Thus @('#\\a')
 and @('#\\b') both contain one application.  Strings are built from the empty
 string, @('(o)') by the ``string-cons'' function written @('cs').  Thus
 @('\"AB\"') is @('(cs (#\\a) (cs (#\\b) (o)))') and contains five
 applications.  Symbols are obtained from strings by ``packing'' the @(tsee
 symbol-name) with the unary function @('p').  Thus @(''ab') is</p>

 @({
  (p (cs (#\\a) (cs (#\\b) (o))))
 })

 <p>and has six applications.  Note that packages are here ignored and thus
 @(''acl2::ab') and @(''my-package::ab') each contain just six applications.
 Finally, @(see cons)es are built with @(tsee cons), as usual.  So @(''(1
 . 2)') is @('(cons '1 '2)') and contains six applications, since @(''1')
 contains two and @(''2') contains three.  This, for better or worse, answers
 the question ``How many function applications are in a constant?''</p>

 <p>Finally, when we refer to the ``pseudo-function application count'', we
 mean the number of pseudo-function applications as described above, except
 that we bound this number by the constant @('(fn-count-evg-max-val)').  (This
 bound is important for efficiency, so that constants that are very large
 @('cons') structures do not cause significant slowdown as ACL2 attempts to
 walk through them while computing their pseudo-function application
 count.)</p>")

(defxdoc term-table
  :parents (meta)
  :short "A table used to validate meta rules"
  :long "@({
  Example:
  (table term-table t '((binary-+ x y) '3 'nil (car x)))
 })

 <p>See @(see table) for a general discussion of tables and the @('table')
 event used to manipulate tables.</p>

 <p>The ``@('term-table')'' is used at the time a meta rule is checked for
 syntactic correctness.  Each proposed metafunction is run on each term in this
 table, and the result in each case is checked to make sure that it is a
 @('termp') in the current world.  In each case where this test fails, a
 warning is printed.</p>

 <p>By default, when a metafunction is run in support of the application of a
 meta rule, the result must be a term (see @(tsee termp)) in the current world.
 When the result is not a term, a hard error arises.  (However, see the last
 paragraph below.)  The @('term-table') is simply a means for providing
 feedback to the user at the time a meta rule is submitted, warning of the
 definite possibility that such a hard error will occur at some point in the
 future.</p>

 <p>The key used in @('term-table') is arbitrary.  The top-most value is always
 the one that is used; it is the entire list of terms to be considered.  Each
 must be a @('termp') in the current ACL2 world.</p>

 <p>The runtime check on the output of metafunctions can be avoided by proving
 that it will always succeed (see @(see well-formedness-guarantee)) or by
 telling ACL2 to skip the test at the risk of soundness (see @(tsee
 set-skip-meta-termp-checks)).</p>")

(defxdoc termination-theorem
  :parents (lemma-instance measure hints)
  :short "Use a (functional instance of a) previously-proved measure theorem"
  :long "<p>See @(see lemma-instance) for a discussion of
 @(':termination-theorem') and @(':termination-theorem!') lemma instances, and
 see @(see tthm) for a related user-level query utility.  Also see @(see
 termination-theorem-example) for simple examples of the use of
 measure (termination) theorems in @(see hints).  For a related utility, see
 @(see make-termination-theorem).</p>")

(defxdoc termination-theorem-example
  :parents (lemma-instance measure hints)
  :short "How to use a previously-proved measure theorem"
  :long "<p>See @(see lemma-instance) for a discussion of
 @(':termination-theorem') and @(':termination-theorem!') lemma instances, and
 see @(see tthm) for a related user-level query utility.  In this topic, we
 illustrate the use of such lemma instances to take advantage of a measure
 theorem already proved for an existing definition, when attempting to admit a
 new definition.  We present two examples: a basic one, and then another that
 shows how an existing termination theorem can be automatically functionally
 instantiated.  For a related utility, see @(see make-termination-theorem).</p>

 <p>The following very simple example is contrived but should get the main idea
 across.  Suppose that the following event was previously executed, for example
 when including a book, in order to define the log base 10 of @('x').</p>

 @({
 (encapsulate
   ()
   (local (include-book \"arithmetic-5/top\" :dir :system))
   (defun log10 (x) ; log base 10 of x
     (if (or (zp x)
             (< x 10))
         0
       (1+ (log10 (floor x 10))))))
 })

 <p>Now suppose we want to admit the following definition, whose recursion
 pattern is similar to that above.  The simplest way might be to include the
 same book as above, but perhaps that is impossible because the @(see formula)
 for some name in that book conflicts with the formula for that name in the
 current session.  Without that book, it could be challenging to develop lemmas
 that allow the termination proof to succeed for this proposed definition.  So
 we provide a hint, specifying the use of the termination theorem already
 proved for @('log10'), as follows.</p>

 @({
 (defun base10-digits (x)
   (declare (xargs :hints
                   ((\"Goal\" :use ((:termination-theorem log10))))))
   (if (or (zp x)
           (< x 10))
       (list x)
     (append (base10-digits (floor x 10))
             (list (mod x 10)))))
 })

 <p>With this hint, the termination proof succeeds, printing the following line
 in the event summary.</p>

 @({
 Hint-events: ((:USE LOG10))
 })

 <p>This line says that the only @(':use') hint was based on the event
 @('log10').  This may surprise you; perhaps you would expect to see something
 instead such as @('(:USE (:TERMINATION-THEOREM LOG10))').  However, the
 @('Hint-events') field of the summary is intended only to show the names of
 @(see events) that support the hints.  For example, if you replace the
 @(':use') hint in the example above with</p>

 @({
 :use ((:rewrite car-cons) (:termination-theorem log10))
 })

 <p>then the @('Hint-events') summary line will be as follows.</p>

 @({
 Hint-events: ((:USE CAR-CONS) (:USE LOG10))
 })

 <p>Similarly, proof output for a @(':use') hint (provided when not in @(see
 gag-mode)) is also given at the level of events.  For the definition above, we
 get the following output.</p>

 @({
 We augment the goal with the hypothesis provided by the :USE hint.
 The hypothesis can be obtained from LOG10.  We are left with the following
 subgoal.
 })

 <p>Again, perhaps one would expect to see ``@('obtained from the termination
 theorem for LOG10')''.  But for the modified hint shown above, using
 @('(:rewrite car-cons)'), we similarly see only event names, not a @(see
 rune).</p>

 @({
 These hypotheses can be obtained from CAR-CONS and LOG10.
 })

 <p>Next, we consider an example where a function symbol being defined occurs
 in the measure theorem.</p>

 @({
 (defun left (x)
   (car x))
 (defun right (x)
   (car x))
 (defun first-natp (x)
   (if (atom x)
       (if (natp x) x nil)
     (or (first-natp (left x))
         (first-natp (right x)))))
 })

 <p>The measure (termination) theorem for @('first-natp') is as follows.</p>

 @({
 (AND (IMPLIES (NOT (ATOM X))
               (O< (ACL2-COUNT (LEFT X))
                   (ACL2-COUNT X)))
      (IMPLIES (AND (NOT (ATOM X))
                    (NOT (FIRST-NATP (LEFT X))))
               (O< (ACL2-COUNT (RIGHT X))
                   (ACL2-COUNT X))))
 })

 <p>Now suppose the functions @('left') and @('right') are @(see disable)d and we then
 try to admit the analogous definition below.  This sort of situation may be
 common; imagine a library of books in which @('first-natp') is defined
 followed by disabling of @('left') and @('right'), and we have included that
 book in hopes of re-using the termination theorem.</p>

 @({
 (in-theory (disable left right))

 (defun first-symbolp (x)
   (if (atom x)
       (if (symbolp x) x nil)
     (or (first-symbolp (left x))
         (first-symbolp (right x)))))

 })

 <p>This time the termination theorem is as follows.</p>

 @({
 (AND (IMPLIES (NOT (ATOM X))
               (O< (ACL2-COUNT (LEFT X))
                   (ACL2-COUNT X)))
      (IMPLIES (AND (NOT (ATOM X))
                    (NOT (FIRST-SYMBOLP (LEFT X))))
               (O< (ACL2-COUNT (RIGHT X))
                   (ACL2-COUNT X))))
 })

 <p>Notice that this theorem is not an immediate consequence of the termination
 theorem for @('first-natp'), because of the call @('first-symbolp') in the
 latter that replaces the call @('first-natp') in the former.  ACL2 provides
 support to work around this difficulty, however.  When you give a
 @(':termination-theorem') @(see lemma-instance) in your :hints for the
 termination proof, then ACL2 automatically replaces the old function symbol
 (here, @('first-natp')) in the old termination theorem by the new function
 symbol (here, @('first-symbolp')), before applying the hint.  So the following
 definition is admitted, because the old termination theorem, thus modified, is
 exactly the new termination theorem.</p>

 @({
 (defun first-symbolp (x)
   (declare (xargs :hints
                   ((\"Goal\" :by (:termination-theorem first-natp)))))
   (if (atom x)
       (if (symbolp x) x nil)
     (or (first-symbolp (left x))
         (first-symbolp (right x)))))
 })

 <p>Such a substitution is made provided the old and new function symbols each
 have the same number of formal parameters.  In general a @(':termination-theorem')
 may be used for admitting either a singly-recursive function or a nest of
 mutually-recursion functions; the general criterion is that the number of
 formals must match for corresponding functions.</p>

 <p>The functional substitution can be provided explicitly.  The following
 example has identical behavior to that above.</p>

 @({
 (defun first-symbolp (x)
   (declare (xargs :hints
                   ((\"Goal\" :by (:termination-theorem
                                 first-natp
                                 ((first-natp first-symbolp)))))))
   (if (atom x)
       (if (symbolp x) x nil)
     (or (first-symbolp (left x))
         (first-symbolp (right x)))))
 })

 <p>Finally, note that a @(':by') hint is not guaranteed to work; a @(':use')
 hint may be a bit slower, and may require the use of @(':instance') (see @(see
 lemma-instance), but it can be more reliable.</p>

 <p>We conclude with a remark about what happens when the termination theorem
 does not exist, even though (as required) the indicated function symbol is in
 @(see logic) mode.  (For example, imagine that you are generating such hints
 programmatically, without analyzing whether the indicated function symbol was
 defined using recursion.)  In that case, using @(':termination-theorem') will
 fail.  Here, for example, is what happens if @('f') was defined
 non-recursively.</p>

 @({
 ACL2 !>(defun g (x)
          (declare (xargs :hints
                          ((\"Goal\" :use ((:termination-theorem f))))))
          (if (consp x)
              (g (cddr x))
            x))


 ACL2 Error in ( DEFUN G ...):  The object (:TERMINATION-THEOREM F)
 is an ill-formed lemma instance because there is no termination theorem
 for F.  The function F is not recursive.  See :DOC lemma-instance.


 Summary
 Form:  ( DEFUN G ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

 ACL2 Error in ( DEFUN G ...):  See :DOC failure.

 ******** FAILED ********
 ACL2 !>
 })

 <p>The alternative, @(':termination-theorem!'), is provided in order to avoid
 this sort of error.  Here is the corresponding (edited) log, with @(see
 gag-mode) off.  Notice that since there is no termination theorem stored for
 @('f'), the @(':use') hint specifies the use of @('T') for the termination
 theorem.</p>

 @({
 ACL2 !>(defun g (x)
          (declare (xargs :hints
                          ((\"Goal\" :use ((:termination-theorem! f))))))
          (if (consp x)
              (g (cddr x))
            x))

 For the admission of G we will use the relation O< (which is known
 to be well-founded on the domain recognized by O-P) and the measure
 (ACL2-COUNT X).  The non-trivial part of the measure conjecture is

 Goal
 (IMPLIES (CONSP X)
          (O< (ACL2-COUNT (CDDR X))
              (ACL2-COUNT X))).

 [Note:  A hint was supplied for our processing of the goal above.
 Thanks!]

 We augment the goal with the hypothesis provided by the :USE hint.
 The hypothesis can be obtained from F.  We are left with the following
 subgoal.

 Goal'
 (IMPLIES T
          (OR (NOT (CONSP X))
              (O< (ACL2-COUNT (CDDR X))
                  (ACL2-COUNT X)))).

 By case analysis we reduce the conjecture to

 [[.. output elided ..]]

 Hint-events: ((:USE F))
 Time:  0.02 seconds (prove: 0.01, print: 0.01, other: 0.00)
 Prover steps counted:  1121
  G
 ACL2 !>
 })")

(defxdoc termp
  :parents (term acl2-built-ins)
  :short "recognizer for the quotation of a @(see term)"
  :long "@({
  Example:
  (termp '(CAR (CONS X Y)) (w state))

  General Form:
  (termp x w)
 })

 <p>where @('x') is any ACL2 object and @('w') is an ACL2 logical @(see world).
 The result is @('t') or @('nil') according to whether @('x') is the quotation
 of a translated (well-formed) term in the @(see world), @('w').  See @(see
 term) for a discussion of translated terms.</p>

 <p>Each metafunction (see @(tsee meta)) is supposed to take (the quotation of)
 a translated term as input and yield (the quotation of) a translated term as
 output.  When a metafunction is run by the simplifier its input is guaranteed
 to be well-formed by invariants maintained by ACL2.  But its output is checked
 by an explicit call of @('termp') unless the user has proved that the
 metafunction always returns a term (see @(see well-formedness-guarantee)) or
 has taken the risk of disabling the runtime test with @(tsee
 set-skip-meta-termp-checks).</p>

 <p>@(tsee Termp) is mutually recursive with @(tsee term-listp).</p>

 @(def termp)
 @(def term-listp)")

(defxdoc the
  :parents (guard compilation acl2-built-ins)
  :short "@('The') is a special form that can be used to optimize the execution
 efficiency of @(see guard)-verified ACL2 definitions, or (less frequently) to
 carry out a low-level run-time type checks. (Advanced)"

  :long "<p>@('The') is a special Common Lisp form.  It is usually used as a
 way to boost the performance of ACL2 definitions by telling the Common Lisp
 compiler that a certain expression will always produce a result of a certain
 type.  This information may allow the Common Lisp compiler to avoid certain
 run-time checks.  See @(see declare) and @(see type-spec) for general, related
 background.</p>

 <p>General form:</p>
 @({
      (the <typ> <val>)   ;; returns <val>, or causes a run-time error
 })

 <ul>
 <li>@('<typ>') is a @(see type-spec)</li>
 <li>@('<val>') is some expression that should produce a value of that type.</li>
 </ul>

 <p>Typical example:</p>

 @({
      (defun merge-bytes (b1 b2)
        ;; Combine two 8-bit bytes into a 16-bit result.
        (declare (type (unsigned-byte-p 8) b1 b2))
        (the (unsigned-byte 16)
             (logior (the (unsigned-byte 16) (ash b1 8))
                     b2)))
 })

 <p>On most Lisp implementations 16-bit numbers are fixnums.  The @('the')
 forms above are promises to the Lisp compiler that these @('ash') and
 @('logior') operations will always produce 16-bit numbers.  Ideally, the
 compiler could use this information to generate more efficient code, i.e., by
 omitting whatever code is normally required to handle bignum results.  (Of
 course, a sufficiently smart compiler could have figured this out on its own;
 in practice Lisp compilers vary in their reasoning abilities.)</p>


 <h3>Relation to Guards</h3>

 <p>To justify that type declarations are correct, @('the') is integrated into
 ACL2's @(see guard) mechanism.  When a call of @('(the TYPE EXPR)') in the
 body of a function definition generates a guard proof obligation that the
 type, @('TYPE'), holds for the value of the expression, @('EXPR').  Consider
 the following example.</p>

 @({
  (defun f (x)
    (declare (xargs :guard (p1 x)))
    (if (p2 x)
        (the integer (h x))
      17))
 })

 <p>The @(see guard) proof obligation generated for the @('THE') expression
 above is as follows.</p>

 @({
  (implies (and (p1 x) (p2 x))
           (let ((var (h x))) (integerp var)))
 })

 <p>For @('the') to provide any execution speed benefit, @(see guard)s must be
 <see topic='@(url verify-guards)'>verified</see>.</p>

 <p>In contexts where guards have <i>not</i> been verified, @('the') acts as a
 low-level, run-time type check that @('val') satisfies the type specification
 @('typ') (see @(see type-spec)).  An error is caused if the check fails;
 otherwise, @('val') is returned.  Here are some examples:</p>

 @({
  (the integer 3)       ; returns 3
  (the (integer 0 6) 3) ; returns 3
  (the (integer 0 6) 7) ; causes an error (see below for exception)
 })

 <p>There is an exception to the rule that failure of the type-check causes an
 error: there is no error when @(see guard)-checking has been turned off, that
 is, in any of the following ways; also @(see set-guard-checking) and see @(see
 with-guard-checking).</p>

 <ul>
 <li>@(':set-guard-checking nil')</li>
 <li>@('(with-guard-checking nil ...)')</li>
 <li>@(':set-guard-checking :none')</li>
 <li>@('(with-guard-checking :none ...)')</li>
 </ul>


 <h3>Further resources</h3>

 <p>The @(see b*) macro provides a special syntax that may make using @('the')
 forms more pleasant; see @(see patbind-the) for more information.</p>

 <p>When optimizing functions with type declarations, you may wish to manually
 inspect the compiler's output with @(see disassemble$) or conduct experiments
 to measure the impact of your optimizations.</p>

 <p>@('THE') is defined in Common Lisp.  See any Common Lisp documentation for
 more information.</p>")

(defxdoc the-method
  :parents (acl2-tutorial)
  :short "How to find proofs"
  :long "<p>Also see @(see introduction-to-the-theorem-prover) for a more
 detailed tutorial on how to prove theorems with ACL2.</p>

 <p>Many users develop proof scripts in an Emacs buffer and submit one event at
 a time to the theorem prover running in a @('*shell*') buffer.  The script
 buffer is logically divided into two regions: the events that have been
 accepted by the theorem prover and those that have not yet been accepted.  An
 imaginary ``barrier'' divides these two regions.  The region above the barrier
 describes the state of the @('*shell*') buffer (and ACL2's logical world).
 The region below the barrier is the ``to do'' list.</p>

 <p>We usually start a proof project by typing the key lemmas, and main goal
 into the to do list.  Definitions are here just regarded as theorems to prove
 (i.e., the measure conjectures).  Then we follow ``The Method.''</p>

 <p>(1) Think about the proof of the first theorem in the to do list.
 Structure the proof either as an induction followed by simplification or just
 simplification.  Have the necessary lemmas been proved? That is, are the
 necessary lemmas in the done list already?  If so, proceed to Step 2.
 Otherwise, add the necessary lemmas at the front of the to do list and repeat
 Step 1.</p>

 <p>(2) Call the theorem prover on the first theorem in the to do list and let
 the output stream into the *shell* buffer.  Abort the proof if it runs more
 than a few seconds.</p>

 <p>(3) If the theorem prover succeeded, advance the barrier past the
 successful command and go to Step 1.</p>

 <p>(4) Otherwise, inspect the failed proof attempt, starting from the
 beginning, not the end.  Basically you should look for the first place the
 proof attempt deviates from your imagined proof.  If your imagined proof was
 inductive, inspect the induction scheme used by ACL2.  If that is ok, then
 find the first subsequent subgoal that is stable under simplification and
 think about why it was not proved by the simplifier.  If your imagined proof
 was not inductive, then think about the first subgoal stable under
 simplification, as above.  Modify the script appropriately.  It usually means
 adding lemmas to the to do list, just in front of the theorem just tried.  It
 could mean adding hints to the current theorem.  In any case, after the
 modifications go to Step 1.</p>

 <p>We do not seriously suggest that this or any rotely applied algorithm will
 let you drive ACL2 to difficult proofs.  Indeed, to remind you of this we call
 this ``The Method'' rather than ``the method.''  That is, we are aware of the
 somewhat pretentious nature of any such advice.  But these remarks have helped
 many users approach ACL2 in a constructive and disciplined way.</p>

 <p>We say much more about The Method in the ACL2 book.  See the home page.
 Also see @(see set-gag-mode) for a discussion of a way for ACL2 to help you to
 use The Method.  And again, see @(see introduction-to-the-theorem-prover) for
 a more detailed tutorial.</p>

 <p>Learning to read failed proofs is a useful skill.  There are several kinds
 of ``checkpoints'' in a proof: (1) a formula to which induction is being (or
 would be) applied, (2) the first formula stable under simplification, (3) a
 formula that is possibly generalized, either by cross-fertilizing with and
 throwing away an equivalence hypothesis or by explicit generalization of a
 term with a new variable.</p>

 <p>At the induction checkpoint, confirm that you believe the formula being
 proved is a theorem and that it is appropriately strong for an inductive
 proof.  Read the selected induction scheme and make sure it agrees with your
 idea of how the proof should go.</p>

 <p>At the post-simplification checkpoint, which is probably the most commonly
 seen, consider whether there are additional rewrite rules you could prove to
 make the formula simplify still further.  Look for compositions of function
 symbols you could rewrite.  Look for contradictions among hypotheses and prove
 the appropriate implications: for example, the checkpoint might contain the
 two hypotheses @('(P (F A))') and @('(NOT (Q (G (F A))))') and you might
 realize that @('(implies (p x) (q (g x)))') is a theorem.  Look for signs that
 your existing rules did not apply, e.g., for terms that should have been
 rewritten, and figure out why they were not.  Possible causes include that
 they do not exactly match your old rules, that your old rules have hypotheses
 that cannot be relieved here &mdash; perhaps because some other rules are
 missing, or perhaps your old rules are disabled.  If you cannot find any
 further simplifications to make in the formula, ask yourself whether it is
 valid.  If so, sketch a proof.  Perhaps the proof is by appeal to a
 combination of lemmas you should now prove?</p>

 <p>At the two generalization checkpoints &mdash; where hypotheses are
 discarded or terms are replaced by variables &mdash; ask yourself whether the
 result is a theorem.  It often is not.  Think about rewrite rules that would
 prove the formula.  These are often restricted versions of the overly-general
 formulas created by the system's heuristics.</p>

 <p>See @(see proof-tree) for a discussion of a tool to help you navigate
 through ACL2 proofs.</p>")

(defxdoc theories
  :parents (acl2)
  :short "Sets of @(see rune)s to @(see enable)/@(see disable) in concert"
  :long "@({
  Example: '((:definition app) ; or (:d app)
             (:executable-counterpart app)
             (:i app)
             rv
             (rv)
             (:r assoc-of-app))
 })

 <p>See:</p>

 <p>A theory is a list of ``runic designators'' as described below.  Each runic
 designator denotes a set of ``runes'' (see @(see rune)) and by unioning
 together the runes denoted by each member of a theory we define the set of
 runes corresponding to a theory.  Theories are used to control which rules are
 ``@(see enable)d,'' i.e., available for automatic application by the theorem
 prover.  There is always a ``current'' theory.  A rule is @(see enable)d
 precisely if its @(see rune) is an element of the set of @(see rune)s
 corresponding to the current theory.  At the top-level, the current theory is
 the theory selected by the most recent @(tsee in-theory) event, extended with
 the rule names introduced since then.  Inside the theorem prover, the
 @(':')@(tsee in-theory) hint (see @(see hints)) can be used to select a
 particular theory as current during the proof attempt for a particular
 goal.</p>

 <p>Theories are generally constructed by ``theory expressions.''  Formally, a
 theory expression is any term, containing at most the single free variable
 @(tsee world), that when evaluated with @(tsee world) bound to the current
 ACL2 world (see @(see world)) produces a theory.  ACL2 provides various
 functions for the convenient construction and manipulation of theories.  These
 are called ``theory functions'' (see @(see theory-functions)).  For example,
 the theory function @(tsee union-theories) takes two theories and produces
 their union.  The theory function @(tsee universal-theory) returns the theory
 containing all known rule names as of the introduction of a given logical
 name.  But a theory expression can contain constants, e.g.,</p>

 @({
  '(len (len) (:rewrite car-cons) car-cdr-elim)
 })

 <p>and user-defined functions.  The only important criterion is that a theory
 expression mention no variable freely except @(tsee world) and evaluate to a
 theory.</p>

 <p>More often than not, theory expressions typed by the user do not mention
 the variable @(tsee world).  This is because user-typed theory expressions are
 generally composed of applications of ACL2's theory functions.  These
 ``functions'' are actually macros that expand into terms in which @(tsee
 world) is used freely and appropriately.  Thus, the technical definition of
 ``theory expression'' should not mislead you into thinking that interesting
 theory expressions must mention @(tsee world); they probably do and you just
 didn't know it!</p>

 <p>One aspect of this arrangement is that theory expressions cannot generally
 be evaluated at the top-level of ACL2, because @(tsee world) is not bound.  To
 see the value of a theory expression, @('expr'), at the top-level, type</p>

 @({
  ACL2 !>(LET ((WORLD (W STATE))) expr).
 })

 <p>However, because the built-in theories are quite long, you may be sorry you
 printed the value of a theory expression!</p>

 <p>A theory is a true list of runic designators and to each theory there
 corresponds a set of @(see rune)s, obtained by unioning together the sets of
 @(see rune)s denoted by each runic designator.  For example, the theory
 constant</p>

 @({
     '(len (len) (:e nth) (:rewrite car-cons) car-cdr-elim)
 })

 <p>corresponds to the set of @(see rune)s</p>

 @({
     {(:definition len)
      (:induction len)
      (:executable-counterpart len)
      (:executable-counterpart nth)
      (:elim car-cdr-elim)
      (:rewrite car-cons)} .
 })

 <p>Observe that the theory contains five elements but its runic correspondent
 contains six.  That is because runic designators can denote sets of several
 @(see rune)s, as is the case for the first designator, @('len').  If the above
 theory were selected as current then the six rules named in its runic
 counterpart would be @(see enable)d and all other rules would be @(see
 disable)d.</p>

 <p>We now precisely define the runic designators and the set of @(see rune)s
 denoted by each.  When we refer below to the ``macro-aliases dereference of''
 a symbol, @('symb'), we mean the (function) symbol corresponding @('symb') in
 the macro-aliases-table if there is such a symbol, else @('symb') itself; see
 @(see macro-aliases-table).  For example, the macro-aliases dereference of
 @(tsee append) is @(tsee binary-append), and the macro-aliases dereference of
 @(tsee nth) is @('nth').</p>

 <ul>

 <li>A @(see rune) is a runic designator and denotes the singleton set
 containing that rune.</li>

 <li>Suppose that @('symb') is a symbol and @('symb'') is the macro-aliases
 dereference of @('symb'), where @('symb'') is a function symbol introduced
 with a @(tsee defun) (or @(tsee defuns)) event.  Then @('symb') is a runic
 designator and denotes the set containing the runes <tt>(:definition
 symb')</tt> and <tt>(:induction symb')</tt>, omitting the latter if no such
 @(see induction) rune exists (presumably because the definition of @('symb'')
 is not singly recursive).</li>

 <li>Suppose that @('symb') is a symbol and @('symb'') is the macro-aliases
 dereference of @('symb'), where @('symb'') is a function symbol introduced
 with a @(tsee defun) (or @(tsee defuns)) event.  Then @('(symb)') is a runic
 designator and denotes the singleton set containing the rune
 <tt>(:executable-counterpart symb')</tt>.</li>

 <li>If @('symb') is the name of a @(tsee defthm) (or @(tsee defaxiom)) event
 that introduced at least one rule, then @('symb') is a runic designator and
 denotes the set of the names of all rules introduced by the named event.</li>

 <li>If @('str') is the string naming some @(tsee defpkg) event and @('symb')
 is the symbol returned by @('(intern str \"ACL2\")'), then @('symb') is a
 runic designator and denotes the singleton set containing @('(:rewrite
 symb)'), which is the name of the rule stating the conditions under which the
 @(tsee symbol-package-name) of @('(intern x str)') is @('str').</li>

 <li>If @('symb') is the name of a @(tsee deftheory) event, then @('symb') is a
 runic designator and denotes the runic theory (as defined below) corresponding
 to @('symb').</li>

 <li>Finally, suppose that @('symb') is a symbol and @('symb'') is the
 macro-aliases dereference of @('symb').  Then @('(:KWD symb . rest)') is a
 runic designator, known as a ``runic abbreviation'', if @('(:KWD' symb'
 . rest)') is a @(see rune), where: @(':KWD') is one of @(':d'), @(':e'),
 @(':i'), @(':r'), or @(':t'); and @(':KWD'') is @(':definition'),
 @(':executable-counterpart'), @(':induction'), @(':rewrite'), or
 @(':type-prescription'), respectively.  In this case, @('(:KWD symb . rest)')
 denotes the runic theory (as defined below) corresponding to the rune
 @('(:KWD' symb' . rest)').</li>

 </ul>

 <p>Note that including a function name, e.g., @(tsee len), in the current
 theory @(see enable)s that function but does not @(see enable) the @(see
 executable-counterpart).  Similarly, including @('(len)') or @('(:e len)')
 @(see enable)s the executable-counterpart but not the symbolic definition.
 And including the name of a proved lemma @(see enable)s all of the rules added
 by the event.  Of course, one can include explicitly the @(see rune)s naming
 the rules in question and so can avoid entirely the use of non-runic elements
 in theories.</p>

 <p>Because a @(see rune) is a runic designator denoting the set containing
 that @(see rune), a list of @(see rune)s is a theory and denotes itself.
 There is a natural ``canonical'' ordering of runes by order of their creation.
 We call a canonically ordered true list of runes a ``runic theory.''  To every
 theory there corresponds a runic theory, sometimes called its runic
 correspondent, obtained by unioning together the sets denoted by each
 designator in the theory.  When a theory is selected as ``current'' it is
 actually its runic correspondent that is effectively used.  That is, a @(see
 rune) is @(see enable)d iff it is a member of the runic correspondent of the
 current theory.  The value of a theory defined with @(tsee deftheory) is the
 runic correspondent of the theory computed by the defining theory expression.
 The theory manipulation functions, e.g., @(tsee union-theories), actually
 convert their theory arguments to their runic correspondents before performing
 the required set operation.  The manipulation functions always return runic
 theories.  Thus, it is sometimes convenient to think of (non-runic) theories
 as merely abbreviations for their runic correspondents, abbreviations which
 are ``expanded'' at the first opportunity by theory manipulation functions and
 the ``theory consumer'' functions such as @(tsee in-theory) and @(tsee
 deftheory).</p>")

(defxdoc theories-and-primitives
  :parents (theories)
  :short "Warnings from disabling or enabling certain built-in functions"
  :long "<p>When you @(see disable) the @(see definition) or @(see
 executable-counterpart) of a built-in function, you may see a warning, for
 example as follows.</p>

 @({
 ACL2 !>(in-theory (disable mv-nth))

 ACL2 Warning [Theory] in ( IN-THEORY (DISABLE ...)):  The :DEFINITION
 rule for the built-in function MV-NTH is disabled by the theory expression
 (DISABLE MV-NTH), but some expansions of its calls may still occur.
 See :DOC theories-and-primitives.
 })

 <p>This warning is telling us that the indicated built-in functions are
 given certain special handling, hence their calls may be expanded even when
 their definitions are disabled.</p>

 <p>These warnings can be eliminated by turning off all theory warnings (see
 @(see set-inhibit-warnings)) or even turning off all warnings (see @(see
 set-inhibit-output-lst)), or simply by evaluating the following form.</p>

 @({
 (assign verbose-theory-warning nil)
 })

 <p>But before you eliminate such theory warnings, you may wish to read the
 following to gain more understanding of their significance.</p>

 <p>First consider the following example, evaluated after the @(tsee in-theory)
 event displayed above.</p>

 @({
 ACL2 !>(thm (equal (mv-nth 2 (list a b c d e)) c))

 Q.E.D.

 Summary
 Form:  ( THM ...)
 Rules: ((:DEFINITION MV-NTH)
         (:FAKE-RUNE-FOR-TYPE-SET NIL))
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
 Prover steps counted:  19

 Proof succeeded.
 ACL2 !>
 })

 <p>Note that even though the @(see definition) of @(tsee mv-nth) had been
 @(see disable)d, nevertheless its definition rule was used in proving this
 theorem.  It is as though @(tsee mv-nth) had not been been disabled after all!
 The warning is intended to indicate that expansion of @('mv-nth') calls may be
 made by the theorem prover even when @('mv-nth') is disabled.  Indeed, the
 prover has special-purpose code for simplifying certain @('mv-nth') calls.</p>

 <p>A similar issue can arise for @('executable-counterpart') rules, as the
 following log illustrates.</p>

 @({
 ACL2 !>(in-theory (disable (:e symbolp)))

 ACL2 Warning [Theory] in ( IN-THEORY (DISABLE ...)):  The :EXECUTABLE-
 COUNTERPART rule for SYMBOLP is disabled by the theory expression
 (DISABLE (:E SYMBOLP)), but because this built-in function is given
 certain special handling, some evaluations of its calls may still occur.
 See :DOC theories-and-primitives.


 Summary
 Form:  ( IN-THEORY (DISABLE ...))
 Rules: NIL
 Warnings:  Theory
 Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
  (:NUMBER-OF-ENABLED-RUNES 3233)
 ACL2 !>(thm (symbolp 'a))

 Q.E.D.

 Summary
 Form:  ( THM ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

 Proof succeeded.
 ACL2 !>
 })

 <p>In general, ACL2 warns when @(tsee in-theory) @(see events) or @(see hints)
 leave you in a theory where rules for certain built-in functions have just
 been disabled, yet these rules may be applied in some cases nonetheless,
 because of special-purpose prover code for handling calls of that function.
 The built-in function symbols with such @(see definition) rules or @(see
 executable-counterpart) rules are those in the following two lists,
 respectively.</p>

 @(def *definition-minimal-theory*)

 @(def *built-in-executable-counterparts*)

 <p>Finally we discuss a third class of warnings.  This final class of warnings
 pertains to @(see primitive)s that do not have definitions, such as @('cons').
 Here is an example of such a warning, for the event @('(in-theory (disable
 cons))').</p>

 @({
 ACL2 Warning [Theory] in ( IN-THEORY (DISABLE ...)):  There is no effect
 from disabling or enabling :DEFINITION rules for primitive functions
 (see :DOC primitive).  For the expression (DISABLE CONS), the attempt
 to disable CONS will therefore have no effect for its definition.
 See :DOC theories-and-primitives.
 })

 <p>Unlike the warnings discussed above, warnings about primitives can occur
 not only when disabling definitions but also when enabling them.  Here is what
 happens when we submit @('(in-theory (enable cons))') immediately after the
 event just above.</p>

 @({
 ACL2 Warning [Theory] in ( IN-THEORY (ENABLE ...)):  There is no effect
 from disabling or enabling :DEFINITION rules for primitive functions
 (see :DOC primitive).  For the expression (ENABLE CONS), the attempt
 to enable CONS will therefore have no effect for its definition.  See
 :DOC theories-and-primitives.
 })

 <p>If however we submit @('(in-theory (enable cons))') again, or in a fresh
 session, there is no warning.  To see why, understand that all of these
 warnings are based on a comparison of the preceding current @(see theory) with
 the new one.  If @('cons') is already enabled, then @('(in-theory (enable
 cons))') is a no-op; hence, there is no warning.</p>

 <p>There is another case in which there is no warning: if all definitions of
 primitives transition from disabled to enabled, or vice-versa.  For example,
 such a transition occurs for consecutive events @('(in-theory (current-theory
 'ground-zero))') and @('(in-theory (theory 'minimal-theory))').</p>")

(defxdoc theory
  :parents (theories theory-functions)
  :short "Retrieve named theory"
  :long "<p>Examples:</p>

 <p><i>For use in @(tsee in-theory) @(see events) or @(':in-theory') @(see
 hints):</i><br/>
 <tt>(theory 'ground-zero)</tt></p>

 <p><i>For direct evaluation at the top-level loop:</i><br/>
 <tt>(let ((world (w state))) (theory 'ground-zero))</tt></p>

 <p>In the examples above, the theory returned is the one in force when ACL2 is
 started up (see @(see ground-zero)).</p>

 @({
  General Form:
  (theory name)
 })

 <p>where @('name') is the name of a previously executed @(tsee deftheory)
 event (otherwise a hard error occurs).  Returns the named theory.  See @(see
 theories).</p>

 <p>This ``function'' is actually a macro that expands to a term mentioning the
 single free variable @(tsee world).  When theory expressions are evaluated by
 @(tsee in-theory) or the @(':')@(tsee in-theory) hint, @(tsee world) is bound
 to the current ACL2 @(see world).</p>")

(defxdoc theory-functions
  :parents (theories)
  :short "Functions for obtaining or producing @(see theories)"
  :long "@({
  Example Calls of Theory Functions:
  (universal-theory :here)
  (union-theories th1 th2)
  (set-difference-theories th1 th2)
 })

 <p>The theory functions are documented individually:</p>

 <p>The functions (actually, macros) mentioned above are convenient ways to
 produce @(see theories).  (See @(see theories).) Some, like @(tsee
 universal-theory), take a logical name (see @(see logical-name)) as an
 argument and return the relevant theory as of the time that name was
 introduced.  Others, like @(tsee union-theories), take two @(see theories) and
 produce a new one.  See @(see redundant-events) for a caution about the use of
 logical names in theory expressions.</p>

 <p>Theory expressions are generally composed of applications of theory
 functions.  Formally, theory expressions are expressions that involve, at
 most, the free variable @(tsee world) and that when evaluated with @(tsee
 world) bound to the current ACL2 world (see @(see world)) return @(see
 theories).  The ``theory functions'' are actually macros that expand into
 forms that involve the free variable @(tsee world).  Thus, for example
 @('(universal-theory :here)') actually expands to @('(universal-theory-fn
 :here world)') and when that form is evaluated with @(tsee world) bound to the
 current ACL2 @(see world), @('universal-theory-fn') scans the ACL2 property
 lists and computes the current universal theory.  Because the theory functions
 all implicitly use @(tsee world), the variable does not generally appear in
 anything the user types.</p>")

(defxdoc theory-invariant
  :parents (events)
  :short "User-specified invariants on @(see theories)"
  :long "@({
  Examples:
  (theory-invariant (not (and (active-runep '(:rewrite left-to-right))
                              (active-runep '(:rewrite right-to-left))))
                    :key my-invariant
                    :error nil)

  ; Equivalent to the above:
  (theory-invariant (incompatible (:rewrite left-to-right)
                                  (:rewrite right-to-left))
                    :key my-invariant
                    :error nil)

  ; As above, but cause an error for non-runes:
  (theory-invariant (incompatible! (:rewrite left-to-right)
                                   (:rewrite right-to-left))
                    :key my-invariant
                    :error nil)

  General Form:
  (theory-invariant term &key key error)
 })

 <p>where:</p>

 <ul>

 <li>@('term') is a term that uses no variables other than @('ens') and @(tsee
 state);</li>

 <li>@('key') is an arbitrary ``name'' for this invariant (if omitted, an
 integer is generated and used); and</li>

 <li>@(':error') specifies the action to be taken when an invariant is
 violated &mdash; either @('nil') if a warning is to be printed, else @('t')
 (the default) if an error is to be caused.</li>

 </ul>

 <p>@('Theory-invariant') is an event that adds to or modifies the @(see table)
 of user-supplied theory invariants that are checked each time a theory
 expression is evaluated.</p>

 <p>The theory invariant mechanism is provided via a table (see @(see table))
 named @('theory-invariant-table').  In fact, the @('theory-invariant')
 ``event'' is just a macro that expands into a use of the @(tsee table) event.
 More general access to the @('theory-invariant') @(see table) is provided by
 @(tsee table) itself.  For example, the @(see table) can be inspected or
 cleared with @(tsee table); you can clear an individual theory invariant by
 setting the invariant to @('t'), or eliminate all theory invariants with the
 command @('(table theory-invariant-table nil nil :clear)').</p>

 <p>@('Theory-invariant-table') maps arbitrary keys to records containing terms
 that mention, at most, the variables @('ens') and @(tsee state).  Every time
 an alleged theory expression is evaluated, e.g., in the @(tsee in-theory)
 event or @(':')@(tsee in-theory) hint, each of the terms in
 @('theory-invariant-table') is evaluated with @('ens') bound to a so-called
 ``enabled structure'' obtained from the theory expression and @(tsee state)
 bound to the current ACL2 state (see @(see state)).  Users generally need not
 know about the enabled structure, other than that it can be accessed using the
 macros @('active-runep') and @('incompatible'); see @(see active-runep) and
 see @(see incompatible).  (Also see variants @(see active-or-non-runep) and
 @(see incompatible!), whose use by the theory-invariant mechanism will cause
 an error any time either ``rune'' is not truly a rune.)  If the result is
 @('nil'), a message is printed and an error occurs (except, only a warning
 occurs if @(':error nil') is specified).  Thus, the @(see table) can be
 thought of as a list of conjuncts.  Each @('term') in the @(see table) has a
 ``name,'' which is just the key under which the term is stored.  When a theory
 violates the restrictions specified by some term, both the name and the term
 are printed.  By calling @('theory-invariant') with a new term but the same
 name, you can overwrite that conjunct of the theory invariant; but see the
 Local Redefinition Caveat at the end of this note.  You may want to avoid
 using explicit names, since otherwise the subsequent inclusion of another book
 that defines a theory invariant with the same name will override your theory
 invariant.</p>

 <p>Theory invariants are particularly useful in the context of large rule sets
 intended for re-use.  Such sets often contain conflicting rules, e.g., rules
 that are to be @(see enable)d when certain function symbols are @(see
 disable)d, rules that rewrite in opposite directions and thus loop if
 simultaneously @(see enable)d, groups of rules which should be @(see enable)d
 in concert, etc.  The developer of such rule sets understands these
 restrictions and probably documents them.  The theory invariant mechanism
 allows the developer to codify his restrictions so that the user is alerted
 when they are violated.</p>

 <p>Since theory invariants are arbitrary terms, macros may be used to express
 commonly used restrictions.  For example, executing the event</p>

 @({
  (theory-invariant (incompatible (:rewrite left-to-right)
                                  (:rewrite right-to-left)))
 })

 <p>would subsequently cause an error any time the current theory contained
 both of the two @(see rune)s shown.  Of course, @(see incompatible) is just
 defined as a macro.  Its definition may be inspected with @(':pe
 incompatible').</p>

 <p>In order for a @('theory-invariant') event to be accepted, the proposed
 theory invariant must be satisfied by the current theory (see @(see
 current-theory)).  The value returned upon successful execution of the event
 is the key (whether user-supplied or generated).</p>

 <p>Local Redefinition Caveat.  Care needs to be taken when redefining a theory
 invariant in a @(see local) context.  Consider the following example.</p>

 @({
  (theory-invariant
   (active-runep '(:definition binary-append))
   :key app-inv)

  (encapsulate
   ()
   (local (theory-invariant t :key app-inv))
   (in-theory (disable binary-append))
   (defthm ...))
 })

 <p>The second pass of the @(tsee encapsulate) will fail, because the @(tsee
 in-theory) event violates the original @('theory-invariant') and the @(tsee
 local) @('theory-invariant') is skipped in the second pass of the @(tsee
 encapsulate).  Of course, @(tsee local) @(tsee theory-invariant)s in @(see
 books) can cause the analogous problem in the second (@(tsee include-book))
 pass of a @(tsee certify-book).  In both cases, though, the theory invariants
 are only checked at the conclusion of the (@('include-book') or
 @('encapsulate')) event.  Indeed, theory invariants are checked at the end of
 every event related to @(see theories), including @(tsee defun), @(tsee
 defthm), @(tsee in-theory), @(tsee encapsulate), and @(tsee include-book),
 except for events executed on behalf of an @(tsee include-book) or the second
 pass of an @(tsee encapsulate).</p>")

(defxdoc third
  :parents (nth acl2-built-ins)
  :short "Third member of the list"
  :long "<p>See any Common Lisp documentation for details.</p>")

(defxdoc thm
  :parents (miscellaneous)
  :short "Prove a theorem"
  :long "@({
  Example:
  (thm (equal (app (app a b) c)
              (app a (app b c))))
 })

 <p>Also see @(see defthm).  Unlike @(tsee defthm), @('thm') does not create an
 event; it merely causes the theorem prover to attempt a proof.</p>

 @({
  General Form:
  (thm term
       :hints        hints
       :otf-flg      otf-flg)
 })

 <p>where @('term') is a term alleged to be a theorem, and @(tsee hints) and
 @(tsee otf-flg) are as described in the corresponding @(see documentation)
 topics.  The keyword arguments above are both optional.</p>")

(defxdoc tidbits
  :parents (acl2-tutorial)
  :short "Some basic hints for using ACL2"
  :long "<p>See @(see books) for a discussion of books.  Briefly, a book is a
 file whose name ends in ``.lisp'' that contains ACL2 @(see events); see @(see
 events).</p>

 <p>See @(see history) for a list of useful commands.  Some examples:</p>

 @({
    :pbt :here      ; print the current event
    :pbt (:here -3) ; print the last four events
    :u              ; undo the last event
    :pe append      ; print the definition of append
 })

 <p>See @(see documentation) to learn how to print documentation to the
 terminal.  There are also versions of the @(see documentation) for web
 browsers and for Emacs (see @(see ACL2-Doc)).</p>

 <p>There are quite a few kinds of rules allowed in ACL2 besides @(':')@(tsee
 rewrite) rules, though we hope that beginners won't usually need to be aware
 of them.  See @(see rule-classes) for details.  In particular, there is
 support for @(see congruence) rewriting.  See @(see rune) (``RUle NamE'') for
 a description of the various kinds of rules in the system.  Also see @(see
 theories) for a description of how to build @(see theories) of @(see rune)s,
 which are often used in hints; see @(see hints).</p>

 <p>A ``@(see programming) mode'' is supported; see @(see program), see @(see
 defun-mode), and see @(see default-defun-mode).  It can be useful to prototype
 functions after executing the command @(':')@(tsee program), which will cause
 definitions to be syntax-checked only.</p>

 <p>ACL2 supports mutual recursion, though this feature is not tied into the
 automatic discovery of @(see induction) schemas and is often not the best way
 to proceed when you expect to be reasoning about the functions.  See @(see
 defuns); also see @(see mutual-recursion).</p>

 <p>See @(see ld) for discussion of how to load files of @(see events).  There
 are many options to @(tsee ld), including ones to suppress proofs and to
 control output.</p>

 <p>The @(':')@(tsee otf-flg) (Onward Thru the Fog FLaG) is a useful feature
 that Nqthm users have often wished for.  It prevents the prover from aborting
 a proof attempt and inducting on the original conjecture.  See @(see
 otf-flg).</p>

 <p>ACL2 supports redefinition and redundancy in @(see events); see @(see
 ld-redefinition-action) and see @(see redundant-events).</p>

 <p>A @(see proof-tree) display feature is available for use with Emacs.  This
 feature provides a view of ACL2 proofs that can be much more useful than
 reading the stream of @(see characters) output by the theorem prover as its
 ``proof.''  See @(see proof-tree).</p>

 <p>An interactive feature similar to Pc-Nqthm is supported in ACL2.  See @(see
 verify) and see @(see proof-builder).</p>

 <p>ACL2 allows you to @(see monitor) the use of @(see rewrite) rules.  See
 @(see break-rewrite).</p>

 <p>See @(see arrays) to read about applicative, fast @(see arrays) in
 ACL2.</p>

 <p>To quit the ACL2 @(see command) loop, or (in akcl) to return to the ACL2
 @(see command) loop after an interrupt, type @(':')@(tsee q).  To continue
 (resume) after an interrupt (in akcl), type @(':r').  To cause an interrupt
 (in akcl under Unix (trademark of AT&amp;T)), hit control-C (twice, if inside
 Emacs).  To exit ACL2 altogether, type @(':')@(tsee quit).</p>

 <p>See @(see state) to read about the von Neumannesque ACL2 @(see state)
 object that records the ``current state'' of the ACL2 session.  Also see @(see
 @), and see @(see assign), to learn about reading and setting global @(see
 state) variables.</p>

 <p>If you want your own von Neumannesque object, e.g., a structure that can be
 ``destructively modified'' but which must be used with some syntactic
 restrictions, see @(see stobj).</p>")

(defxdoc time$
  :parents (programming acl2-built-ins)
  :short "Time an evaluation"
  :long "<p>Semantically, @('(time$ x ...)') equals @('x').  However, its
 evaluation may write timing output to the trace output (which is usually the
 terminal), as explained further below.</p>

 @({
  Examples:

  ; Basic examples:

  (time$ (foo 3 4))
  (time$ (mini-proveall))
  (defun bar (x) (time$ (f x)))

  ; Custom examples, which use a custom timing message rather than a built-in
  ; message from Lisp:

  ; Report only if real time is at least 1/2 second (two equivalent forms).
  (time$ (foo) :mintime 1/2)
  (time$ (foo) :real-mintime 1/2)

  ; Report only if allocation is at least 1000 bytes (and if the Lisp supports
  ; :minalloc).
  (time$ (foo) :minalloc 1000)

  ; Report only if real time is at least 1/2 second and (if the Lisp supports
  ; :minalloc) allocation is at least 931 bytes.
  (time$ (foo) :real-mintime 1/2 :minalloc 931)

  ; Print \"Hello Moon, Goodbye World\" instead of any timing data.
  (time$ (foo)
         :msg \"Hello ~s0, ~s1 World.\"
         :args (list \"Moon\" \"Goodbye\"))

  ; Print default custom timing message (same as omitting :mintime 0):
  (time$ (foo)
         :mintime 0)

  ; Print supplied custom timing message.
  (let ((bar ...))
    (time$ (foo)
           :msg \"The execution of ~xf took ~st seconds of real ~
                 time and ~sc seconds of run time (cpu time), and ~
                 allocated ~sa bytes.  In an unrelated note, bar ~
                 currently has the value ~x0.~%\"
           :args (list bar)))

  General Forms:
  (time$ form)
  (time$ form ; arguments below are optional
         :real-mintime  <rational number of seconds>
         :run-mintime   <rational number of seconds>
         :minalloc      <number of bytes>
         :msg           <fmt string>
         :args          <list of arguments for msg>
         )
  ; Note: :real-mintime can be replaced by :mintime
 })

 <p>where @('form') is processed as usual except that the host Common Lisp
 times its evaluation.</p>

 <p>The simplest form is @('(time$ x)'), which will call the @('time') utility
 in the underlying Lisp, and will print a small default message.  If you want
 to see a message printed by the host Lisp, use @('(time$ x :mintime nil)')
 instead, which may provide detailed, implementation-specific data such as the
 amounts of time spent in user and system mode, the gc time, the number of page
 faults encountered, and so on.  Of you can create a custom message, configured
 using the @(':msg') and @(':args') parameters.  @('Time$') can also be made to
 report timing information only conditionally: the @(':real-mintime') (or
 equivalently, @(':mintime')), @(':run-mintime'), and @(':minalloc') arguments
 can be used to avoid reporting timing information for computations that take a
 small amount of time (perhaps as might be expected in ordinary cases), but to
 draw the user's attention to computations that take longer or allocate more
 memory than expected.</p>

 <p>We next document the keyword arguments in some detail.</p>

 <blockquote><p>Keyword arguments @(':real-mintime') (or @(':mintime')) and
 @(':run-mintime') can be used to specify a minimum time threshold for time
 reporting.  That is, no timing information will be printed if the execution of
 @('form') takes less than the specified number of seconds of real (total) time
 or run (cpu) time, respectively.  Note that rational numbers like 1/2 may be
 used to specify a fractional amount of seconds.  It is an error to specify
 both @(':real-mintime') and its synonym, @(':mintime').</p>

 <p>Keyword argument @(':minalloc') is not supported on all Lisps.  When it is
 not supported, it is ignored.  But on supported Lisps, @(':minalloc') can be
 used to specify a minimum memory allocation threshold.  If @('form') results
 in fewer than this many bytes being allocated, then no timing information will
 be reported.</p>

 <p>Keyword argument @(':msg'), when provided, should be a string accepted by
 the @('fmt') family of functions (see @(see fmt)), and it may refer to the
 elements of @(':args') by their positions, just as for @('cw') (see @(see
 cw)).</p></blockquote>

 <p>The following directives allow you to report timing information using the
 @(':msg') string.  The examples at the top of this documentation topic
 illustrate the use of these directives.</p>

 <blockquote><p>@('~xf') &mdash; the form that was executed</p>

 <p>@('~sa') &mdash; the amount of memory allocated, in bytes (in supported
 Lisps)</p>

 <p>@('~st') &mdash; the real time taken, in seconds</p>

 <p>@('~sc') &mdash; the run time (cpu time) taken, in seconds</p>

 <p>The following apply only when the host Lisp is GCL.  The two system times
 will likely be @('nil') unless the GCL version is 2.6.10 or later.  Note the
 upper-case characters for child times.</p>

 <p>@('~sC') &mdash; the child run time (cpu time) taken, in seconds</p>

 <p>@('~ss') &mdash; the system time taken, in seconds</p>

 <p>@('~sS') &mdash; the child system time taken, in seconds</p></blockquote>

 <p>We turn now to an example that illustrates how @('time$') can be called in
 function bodies.  Consider the following definition of the Fibonacci function,
 followed by the definition of a function that times @('k') calls of this
 function.</p>

 @({
  (defun fib (n)
    (if (zp n)
        1
      (if (= n 1)
          1
        (+ (fib (- n 1))
           (fib (- n 2))))))

  (defun time-fib (k)
    (if (zp k)
        nil
      (prog2$
       (time$ (fib k)
              :mintime 1/2
              :msg \"(fib ~x0) took ~st seconds, ~sa bytes allocated.~%\"
              :args (list k))
       (time-fib (1- k)))))
 })

 <p>The following log shows a sample execution of the function defined just
 above.</p>

 @({
  ACL2 !>(time-fib 36)
  (fib 36) took 3.19 seconds, 1280 bytes allocated.
  (fib 35) took 1.97 seconds, 1280 bytes allocated.
  (fib 34) took 1.21 seconds, 1280 bytes allocated.
  (fib 33) took 0.75 seconds, 1280 bytes allocated.
  NIL
  ACL2 !>
 })

 <p>Notes:</p>

 <p>(1) Common Lisp specifies that the @('time') utility prints to ``trace
 output'', and @('time$') follows this convention.  Thus, if you have opened a
 @(see trace) file (see @(see open-trace-file)), then you can expect to find
 the @('time$') output there.</p>

 <p>(2) Unless the @(':msg') argument is supplied, an explicit call of
 @('time$') in the top-level loop will show that the form being timed is a call
 of the ACL2 evaluator function @('ev-rec').  This is normal; the curious are
 invited, at their own risk, to see @(see return-last) for an
 explanation.</p>")

(defxdoc time-tracker
  :parents (debugging time$ acl2-built-ins)
  :short "Display time spent during specified evaluation"
  :long "<p>The @('time-tracker') macro is a utility for displaying time spent
 during specified evaluation.  In general, the user provides this
 specification.  However, ACL2 itself uses this utility for tracking uses of
 its @(see tau-system) reasoning utility (see @(see time-tracker-tau)).  We
 discuss that use as an example before discussing the general form for calls of
 @('time-tracker').</p>

 <p>Note that by default, the time being tracked is runtime (cpu time); to
 switch to realtime (elapsed time), see @(see get-internal-time).</p>

 <p>Remark for ACL2(p) users (see @(see parallelism)): @('time-tracker') is
 merely a no-op in ACL2(p).</p>

 <p>During the development of the @(see tau-system), we were concerned about
 the possibility that it would slow down proofs without any indication of how
 one might avoid the problem.  We wanted a utility that would alert the user in
 such situations.  However, the tau-system code does not return @(see state),
 so we could not track time spent in the state.  We developed the
 @('time-tracker') utility to track time and print messages, and we did it in a
 general way so that others can use it in their own code.  Here is an example
 of such a message that could be printed during a proof.</p>

 @({
  TIME-TRACKER-NOTE [:TAU]: Elapsed runtime in tau is 2.58 secs; see
  :DOC time-tracker-tau.
 })

 <p>And here is an example of such a message that could be printed at the end
 of the proof.</p>

 @({
  TIME-TRACKER-NOTE [:TAU]: For the proof above, the total time spent
  in the tau system was 20.29 seconds.  See :DOC time-tracker-tau.
 })

 <p>The @('time-tracker') utility tracks computation time spent on behalf of a
 user-specified ``tag''.  In the case of the tau-system, we chose the tag,
 @(':tau').  The first argument of @('time-tracker') is the tag, which in our
 running example is always @(':tau').  Note that although all arguments of
 @('time-tracker') are evaluated, the first argument is typically a keyword and
 the second is always a keyword, and such arguments evaluate to themselves.</p>

 <p>An ACL2 function invoked at the start of a proof includes approximately the
 following code.</p>

 @({
  (progn$
   (time-tracker :tau :end)
   (time-tracker :tau :init
                 :times '(1 2 3 4 5)
                 :interval 5
                 :msg \"Elapsed runtime in tau is ~st secs; see :DOC ~
                       time-tracker-tau.~|~%\")
   ...)
 })

 <p>The first @('time-tracker') call (above) ends any existing time-tracking
 for tag @(':tau').  One might have expected it to be put into code managing
 the proof summary, but we decided not to rely on that code being executed,
 say, in case of an interrupt.  When a given tag is not already being
 time-tracked, then @(':end') is a no-op (rather than an error).</p>

 <p>The second @('time-tracker') call (above) initiates time-tracking for the
 tag, @(':tau').  Moreover, it specifies the effect of the @(':print?')
 keyword.  Consider the following abbreviated definition from the ACL2 source
 code.</p>

 @({
  (defun tau-clausep-lst-rec (clauses ens wrld ans ttree state calist)
    (cond
     ((endp clauses)
      (mv (revappend ans nil) ttree calist))
     (t (mv-let
         (flg1 ttree1 calist)
         (tau-clausep (car clauses) ens wrld state calist)
         (prog2$ (time-tracker :tau :print?)
                 (tau-clausep-lst-rec (cdr clauses) ...))))))
 })

 <p>Notice that @('(time-tracker :tau :print?)') is executed immediately after
 @('tau-clausep') is called.  The idea is to check whether the total time
 elapsed inside the tau-system justifies printing a message to the user.  The
 specification of @(':times '(1 2 3 4 5)') in the @(':init') form above says
 that a message should be printed after 1 second, after 2 seconds, ..., and
 after 5 seconds.  Thereafter, the specification of @(':interval 5') in the
 @(':init') form above says that each time we print, at least 5 additional
 seconds should have been tracked before @('(time-tracker :tau :print?)')
 prints again.  Finally, the @(':msg') keyword above specifies just what should
 be printed.  If it is omitted, then a reasonable default message is printed
 (as discussed below), but in this case we wanted to print a custom message.
 The @(':msg') string above is what is printed using formatted printing (see
 @(see fmt)), where the character @('#\\t') is bound to a string giving a
 decimal representation with two decimal points of the time tracked so far for
 tag @(':tau').  (As our general description below points out, @(':msg') can
 also be a ``message'' list rather than a string.)</p>

 <p>But when is time actually tracked for @(':tau')?  Consider the following
 definition from the ACL2 source code.</p>

 @({
  (defun tau-clausep-lst (clauses ens wrld ans ttree state calist)
    (prog2$ (time-tracker :tau :start!)
            (mv-let
             (clauses ttree calist)
             (tau-clausep-lst-rec clauses ens wrld ans ttree state calist)
             (prog2$ (time-tracker :tau :stop)
                     (mv clauses ttree calist)))))
 })

 <p>The two calls of @('time-tracker') above first start, and then stop,
 time-tracking for the tag, @(':tau').  Thus, time is tracked during evaluation
 of the call of @('tau-clausep-lst-rec'), which is the function (discussed
 above) that does the @(see tau-system)'s work.</p>

 <p>Finally, as noted earlier above, ACL2 may print a time-tracking message for
 tag @(':tau') at the end of a proof.  The ACL2 function @('print-summary')
 contains essentially the following code.</p>

 @({
  (time-tracker :tau :print?
                :min-time 1
                :msg \"For the proof above, the total runtime ~
                      spent in the tau system was ~st seconds.  ~
                      See :DOC time-tracker-tau.~|~%\")
 })

 <p>The use of @(':min-time') says that we are to ignore the @(':times') and
 @(':interval') established by the @(':init') call described above, and
 instead, print a message if and only if at least 1 second (since 1 is the
 value of keyword @(':min-time')) has been tracked for tag @(':tau').
 Formatted printing (see @(see fmt)) is used for the value of @(':msg'), where
 the character @('#\\t') is bound to a decimal string representation of the
 time in seconds, as described above.</p>

 <p>The example above covers all legal values for the second argument of
 @('time-tracker') and discusses all the additional legal keyword arguments.
 We conclude with a precise discussion of all arguments.  Note that all
 arguments are evaluated; thus when we refer to an argument, we are discussing
 the value of that argument.  All times discussed are runtimes, i.e., cpu
 times, unless that default is changed; see @(see get-internal-time).</p>

 @({
  General forms:

  (time-tracker t)        ; enable time-tracking (default)

  (time-tracker nil)      ; disable time-tracking

  (time-tracker tag       ; a symbol other than t or nil
                option    ; :init, :end, :start, :start!, :stop, or :print?
                ;; keyword arguments:
                :times    ; non-nil if and only if option is :init
                :interval ; may only be non-nil with :init option
                :min-time ; may only be non-nil with :print? option
                :msg      ; may only be non-nil with :init and :print? options
 })

 <p>Time-tracking is enabled by default.  If the first argument is @('t') or
 @('nil'), then no other arguments are permitted and time-tracking is enabled
 or disabled, respectively.  When time-tracking is disabled, nothing below
 takes place.  Thus we assume time-tracking is enabled for the remainder of
 this discussion.  We also assume below that the first argument is neither
 @('t') nor @('nil').</p>

 <p>We introduce some basic notions about time-tracking.  A given tag, such as
 @(':tau') in the example above, might or might not currently be ``tracked'':
 @(':init') causes the specified tag to be tracked, while @(':end') causes the
 specified tag not to be tracked.  If the tag is being tracked, the tag might
 or might not be ``active'': @(':start') and @(':start!') cause the tag to be
 in an active state, while @(':stop') causes the tag not to be active.  Note
 that only tracked tags can be in an active or inactive state.  For a tag that
 is being tracked, the ``accumulated time'' is the total time spent in an
 active state since the time that the tag most recently started being tracked,
 and the ``checkpoint list'' is a non-empty list of rational numbers specifying
 when printing may take place, as described below.</p>

 <p>We now consider each legal value for the second argument, or ``option'',
 for a call of @('time-tracker') on a given tag.</p>

 <p>@(':Init') specifies that the tag is to be tracked.  It also establishes
 defaults for the operation of @(':print?'), as described below, using the
 @(':times'), @(':interval'), and @(':msg') keywords.  Of these three, only
 @(':times') is required, and its value must be a non-empty list of rational
 numbers specifying the initial checkpoint list for the tag.  It is an error to
 specify @(':init') if the tag is already being tracked.  (So if you don't care
 whether or not the tag is already being tracked and you want to initiate
 tracking for that tag, use @(':end') first.)</p>

 <p>@(':End') specifies that if the tag is being tracked, then it should stop
 being tracked.  If the tag is not being tracked, then @(':end') has no
 effect.</p>

 <p>@(':Start') specifies that the tag is to be active.  It is an error to
 specify @(':start') if the tag is not being tracked or is already active.</p>

 <p>@(':Start!') has the same effect as @(':start'), except that it does not
 cause an error when the tag is already active.  In effect, @(':start!') first
 invokes @(':stop') if the tag is already active, and then invokes
 @('start').</p>

 <p>@(':Stop') specifies that the tag is to stop being active.  It is an error
 to specify @(':stop') if the tag is not being tracked or is not active.</p>

 <p>@(':Print?') specifies that if the tag is being tracked (not necessarily
 active), then a message should be printed if a suitable condition is met.  The
 nature of that message and that condition depend on the keyword options
 supplied with @(':print?') as well as those supplied with the @(':init')
 option that most recently initiated tracking.  @(':Print?') has no effect if
 the tag is not being tracked, except that if certain keyword values are
 checked if supplied with @(':print?'): @(':min-time') must be a rational
 number or @('nil'), and @(':msg') must be either a string, a true-list whose
 @('car') is a string, or @('nil').  The remainder of this documentation
 describes the @(':print?') option in detail under the assumption that the tag
 is being tracked: first, giving the conditions under which it causes a message
 to be printed, and second, explaining what is printed.</p>

 <p>When @(':print?') is supplied a non-@('nil') value of @(':min-time'), that
 value must be a rational number, in which case a message is printed if the
 accumulated time for the tag is at least that value.  Otherwise a message is
 printed if the accumulated time is greater than or equal to the @('car') of
 the checkpoint list for the tag.  In that case, the tracking state for the tag
 is updated in the following two ways.  First, the checkpoint list is scanned
 from the front and as long as the accumulated time is greater than or equal to
 the @('car') of the remaining checkpoint list, that @('car') is popped off the
 checkpoint list.  Second, if the checkpoint list has been completely emptied
 and a non-@('nil') @(':interval') was supplied when tracking was most recently
 initiated with the @(':init') option, then the checkpoint list is set to
 contain a single element, namely the sum of the accumulated time with that
 value of @(':interval').</p>

 <p>Finally, suppose the above criteria are met, so that @(':print?') results
 in printing of a message.  We describe below the message, @('msg'), that is
 printed.  Here is how it is printed (see @(see fmt)), where
 @('seconds-as-decimal-string') is a string denoting the number of seconds of
 accumulated time for the tag, with two digits after the decimal point.</p>

 @({
  (fms \"TIME-TRACKER-NOTE [~x0]: ~@1~|\"
       (list (cons #0 tag)
             (cons #1 msg)
             (cons #t seconds-as-decimal-string))
       (proofs-co state) state nil)
 })

 <p>The value of @('msg') is the value of the @(':msg') keyword supplied with
 @(':print?'), if non-@('nil'); else, the value of @(':msg') supplied when most
 recently initialization with the @(':init') option, if non-@('nil'); and
 otherwise, the string @('\"~st s\"') (the final ``s'' abbreviating the word
 ``seconds'').  It is convenient to supply @(':msg') as a call @('(msg str
 arg-0 arg-1 ... arg-k)'), where @('str') is a string and each @('arg-i') is
 the value to be associated with @('#\\i') upon formatted printing (as with
 @(tsee fmt)) of the string @('str').</p>")

(defxdoc time-tracker-tau
  :parents (tau-system)
  :short "Messages about expensive use of the @(see tau-system)"
  :long "<p>This @(see documentation) topic explains messages printing by the
 theorem prover about the @(see tau-system), as follows.</p>

 <p>During a proof you may see a message such as the following.</p>

 @({
  TIME-TRACKER-NOTE [:TAU]: Elapsed runtime in tau is 4.95 secs; see
  :DOC time-tracker-tau.
 })

 <p>Just below a proof summary you may see a message such as the following.</p>

 @({
  TIME-TRACKER-NOTE [:TAU]: For the proof above, the total runtime spent
  in the tau system was 30.01 seconds.  See :DOC time-tracker-tau.
 })

 <p>Both of these messages are intended to let you know that certain prover
 heuristics (see @(see tau-system)) may be slowing proofs down more than they
 are helping.  If you are satisfied with the prover's performance, you may
 ignore these messages or even turn them off by disabling time-tracking
 entirely (see @(see time-tracker)).  Otherwise, here are some actions that you
 can take to solve such a performance problem.</p>

 <p>The simplest solution is to disable the tau-system, in either of the
 following equivalent ways.</p>

 @({
  (in-theory (disable (:executable-counterpart tau-system)))
  (in-theory (disable (tau-system)))
 })

 <p>But if you want to leave the tau-system enabled, you could investigate the
 possibility is that the tau-system is causing an expensive @(':')@(tsee
 logic)-mode function to be executed.  You can diagnose that problem by
 observing the rewriter &mdash; see @(see dmr) &mdash; or by interrupting the
 system and getting a backtrace (see @(see set-debugger-enable)).  A solution
 in that case is to disable the @(see executable-counterpart) of that function,
 for example in any of these equivalent ways.</p>

 @({
  (in-theory (disable (:executable-counterpart foo)))
  (in-theory (disable (:e foo)))
  (in-theory (disable (foo)))
 })

 <p>As a result, the tau-system will be weakened, but perhaps only
 negligibly.</p>

 <p>In either case above, you may prefer to provide @(':')@(tsee in-theory)
 hints rather than @(':in-theory') @(see events); see @(see hints).</p>

 <p>A more sophisticated solution is to record values of the @(':')@(tsee
 logic)-mode function in question, so that the tau-system will look up the
 necessary values rather than calling the function, whether or not the
 executable-counterpart of that function is enabled.  Here is an example of a
 lemma that can provide such a solution.  See @(see tau-system).</p>

 @({
  (defthm lemma
    (and (foo 0)
         (foo 17)
         (foo t)
         (not (foo '(a b c))))
    :rule-classes :tau-system)
 })")

(defxdoc tips
  :parents (acl2-tutorial)
  :short "Some hints for using the ACL2 prover"
  :long "<p>We present here some tips for using ACL2 effectively.  Though this
 collection is somewhat <i>ad hoc</i>, we try to provide some organization,
 albeit somewhat artificial: for example, the sections overlap, and no
 particular order is intended.  This material has been adapted by Bill Young
 from a very similar list for Nqthm that appeared in the conclusion of:
 ``Interaction with the Boyer-Moore Theorem Prover: A Tutorial Study Using the
 Arithmetic-Geometric Mean Theorem,'' by Matt Kaufmann and Paolo Pecchiari, CLI
 Technical Report 100, June, 1995.  We also draw from a similar list in Chapter
 13 of ``A Computational Logic Handbook'' by R.S. Boyer and J
 S. Moore (Academic Press, 1988).  We'll refer to this as ``ACLH'' below.</p>

 <p>These tips are organized roughly as follows.</p>

 <blockquote><p>A. ACL2 Basics</p>

 <p>B. Strategies for creating events</p>

 <p>C. Dealing with failed proofs</p>

 <p>D. Performance tips</p>

 <p>E. Miscellaneous tips and knowledge</p>

 <p>F. Some things you DON'T need to know</p></blockquote>

 <p><i>ACL2 BASICS</i></p>

 <p><b>A1. The ACL2 logic.</b><br></br>

 This is a logic of total functions.  For example, if @('A') and @('B') are
 less than or equal to each other, then we need to know something more in order
 to conclude that they are equal (e.g., that they are numbers).  This kind of
 twist is important in writing definitions; for example, if you expect a
 function to return a number, you may want to apply the function @(tsee fix) or
 some variant (e.g., @(tsee nfix) or @(tsee ifix)) in case one of the formals
 is to be returned as the value.</p>

 <p>ACL2's notion of ordinals is important on occasion in supplying ``measure
 @(see hints)'' for the acceptance of recursive definitions.  Be sure that your
 measure is really an ordinal.  Consider the following example, which ACL2
 fails to admit (as explained below).</p>

 @({
    (defun cnt (name a i x)
      (declare (xargs :measure (+ 1 i)))
      (cond ((zp (+ 1 i))
             0)
            ((equal x (aref1 name a i))
             (1+ (cnt name a (1- i) x)))
            (t (cnt name a (1- i) x))))
 })

 <p>One might think that @('(+ 1 i)') is a reasonable measure, since we know
 that @('(+ 1 i)') is a positive integer in any recursive call of @('cnt'), and
 positive integers are ACL2 ordinals (see @(see o-p)).  However, the ACL2 logic
 requires that the measure be an ordinal unconditionally, not just under the
 governing assumptions that lead to recursive calls.  An appropriate fix is to
 apply @(tsee nfix) to @('(+ 1 i)'), i.e., to use</p>

 @({
    (declare (xargs :measure (nfix (+ 1 i))))
 })

 <p>in order to guarantee that the measure will always be an ordinal (in fact,
 a positive integer).</p>

 <p>For more about admissibility of recursive definitions, see @(see defun), in
 particular the discussion of termination.</p>

 <p><b>A2. Simplification.</b><br></br>

 The ACL2 simplifier is basically a rewriter, with some ``@(see linear)
 arithmetic'' thrown in.  One needs to understand the notion of conditional
 rewriting.  See @(see rewrite).</p>

 <p><b>A3. Parsing of rewrite rules.</b><br></br></p>

 <p>ACL2 parses @(see rewrite) rules roughly as explained in ACLH,
 <i>except</i> that it never creates ``unusual'' rule classes.  In ACL2, if you
 want a @(':')@(tsee linear) rule, for example, you must specify @(':')@(tsee
 linear) in the @(':')@(tsee rule-classes).  See @(see rule-classes), and also
 see @(see rewrite) and see @(see linear).</p>

 <p><b>A4. Linear arithmetic.</b><br></br>

 On this subject, it should suffice to know that the prover can handle truths
 about @(tsee +) and @(tsee -), and that @(see linear) rules (see above) are
 somehow ``thrown in the pot'' when the prover is doing such reasoning.
 Perhaps it's also useful to know that @(see linear) rules can have hypotheses,
 and that conditional rewriting is used to relieve those hypotheses.</p>

 <p><b>A5. Events.</b><br></br>

 Over time, the expert ACL2 user will know some subtleties of its @(see
 events).  For example, @(tsee in-theory) @(see events) and @(see hints) are
 important, and they distinguish between a function's definition and its @(see
 executable-counterpart).</p>

 <p><i>B. STRATEGIES FOR CREATING EVENTS</i></p>

 <p>In this section, we concentrate on the use of definitions and @(see
 rewrite) rules.  There are quite a few kinds of rules allowed in ACL2 besides
 @(see rewrite) rules, though most beginning users probably won't usually need
 to be aware of them.  See @(see rule-classes) for details.  In particular,
 there is support for @(see congruence) rewriting.  Also see @(see rune)
 (``RUle NamE'') for a description of the various kinds of rules in the
 system.</p>

 <p><b>B1. Use high-level strategy.</b><br></br>

 Decompose theorems into ``manageable'' lemmas (admittedly, experience helps
 here) that yield the main result ``easily.''  It's important to be able to
 outline non-trivial proofs by hand (or in your head).  In particular, avoid
 submitting goals to the prover when there's no reason to believe that the goal
 will be proved and there's no ``sense'' of how an induction argument would
 apply.  It is often a good idea to avoid induction in complicated theorems
 unless you have a reason to believe that it is appropriate.</p>

 <p><b>B2. Write elegant definitions.</b><br></br>

 Try to write definitions in a reasonably modular style, especially recursive
 ones.  Think of ACL2 as a @(see programming) language whose procedures are
 definitions and lemmas, hence we are really suggesting that one follow good
 @(see programming) style (in order to avoid duplication of ``code,'' for
 example).</p>

 <p>When possible, complex functions are best written as compositions of
 simpler functions.  The theorem prover generally performs better on primitive
 recursive functions than on more complicated recursions (such as those using
 accumulating parameters).</p>

 <p>Avoid large non-recursive definitions which tend to lead to large case
 explosions.  If such definitions are necessary, try to prove all relevant
 facts about the definitions and then @(see disable) them.</p>

 <p>Whenever possible, avoid mutual recursion if you care to prove anything
 about your functions.  The induction heuristics provide essentially no help
 with reasoning about mutually defined functions.  Mutually recursive functions
 can usually be combined into a single function with a ``flag'' argument.
 (However, see @(see mutual-recursion-proof-example) for a small example of
 proof involving mutually recursive functions.)</p>

 <p><b>B3. Look for analogies.</b><br></br>

 Sometimes you can easily edit sequences of lemmas into sequences of lemmas
 about analogous functions.</p>

 <p><b>B4. Write useful rewrite rules.</b><br></br>

 As explained in A3 above, every @(see rewrite) rule is a directive to the
 theorem prover, usually to replace one @(see term) by another.  The directive
 generated is determined by the syntax of the @(tsee defthm) submitted.  Never
 submit a @(see rewrite) rule unless you have considered its interpretation as
 a proof directive.</p>

 <p><b>B4a.  Rewrite rules should simplify.</b><br></br>

 Try to write @(see rewrite) rules whose right-hand sides are in some sense
 ``simpler than'' (or at worst, are variants of) the left-hand sides.  This
 will help to avoid infinite loops in the rewriter.</p>

 <p><b>B4b.  Avoid needlessly expensive rules.</b><br></br>

 Consider a rule whose conclusion's left-hand side (or, the entire conclusion)
 is a @(see term) such as @('(consp x)') that matches many @(see term)s
 encountered by the prover.  If in addition the rule has complicated
 hypotheses, this rule could slow down the prover greatly.  Consider switching
 the conclusion and a complicated hypothesis (negating each) in that case.</p>

 <p><b>B4c. The ``Knuth-Bendix problem''.</b><br></br>

 Be aware that left sides of @(see rewrite) rules should match the ``normalized
 forms'', where ``normalization'' (rewriting) is inside out.  Be sure to avoid
 the use of nonrecursive function symbols on left sides of @(see rewrite)
 rules, except when those function symbols are @(see disable)d, because they
 tend to be expanded away before the rewriter would encounter an instance of
 the left side of the rule.  Also assure that subexpressions on the left hand
 side of a rewrite rule are in simplified form; see @(see community-books)
 example @('books/demos/knuth-bendix-problem-1.lisp').</p>

 <p><b>B4d. Avoid proving useless rules.</b><br></br>

 Sometimes it's tempting to prove a @(see rewrite) rule even before you see how
 it might find application.  If the rule seems clean and important, and not
 unduly expensive, that's probably fine, especially if it's not too hard to
 prove.  But unless it's either part of the high-level strategy or, on the
 other hand, intended to get the prover past a particular unproved goal, it may
 simply waste your time to prove the rule, and then clutter the database of
 rules if you are successful.</p>

 <p><b>B4e. State rules as strongly as possible, usually.</b><br></br>

 It's usually a good idea to state a rule in the strongest way possible, both
 by eliminating unnecessary hypotheses and by generalizing subexpressions to
 variables.</p>

 <p>Advanced users may choose to violate this policy on occasion, for example
 in order to avoid slowing down the prover by excessive attempted application
 of the rule.  However, it's a good rule of thumb to make the strongest rule
 possible, not only because it will then apply more often, but also because the
 rule will often be easier to prove (see also B6 below).  New users are
 sometimes tempted to put in extra hypotheses that have a ``type restriction''
 appearance, without realizing that the way ACL2 handles (total) functions
 generally lets it handle trivial cases easily.</p>

 <p><b>B4f. Avoid circularity.</b><br></br>

 A stack overflow in a proof attempt almost always results from circular
 rewriting.  Use @(tsee brr) to investigate the stack; see @(see break-lemma).
 Because of the complex heuristics, it is not always easy to define just when a
 @(see rewrite) will cause circularity.  See the very good discussion of this
 topic in ACLH.</p>

 <p>See @(see break-lemma) for a trick involving use of the forms @('brr t')
 and @('(cw-gstack)') for inspecting loops in the rewriter.</p>

 <p><b>B4g. Remember restrictions on permutative rules.</b><br></br>

 Any rule that permutes the variables in its left hand side could cause
 circularity.  For example, the following axiom is automatically supplied by
 the system:</p>

 @({
    (defaxiom commutativity-of-+
              (equal (+ x y) (+ y x))).
 })

 <p>This would obviously lead to dangerous circular rewriting if such
 ``permutative'' rules were not governed by a further restriction.  The
 restriction is that such rules will not produce a @(see term) that is
 ``lexicographically larger than'' the original @(see term) (see @(see
 loop-stopper)).  However, this sometimes prevents intended rewrites.  See
 Chapter 13 of ACLH for a discussion of this problem.</p>

 <p><b>B5. Conditional vs. unconditional rewrite rules.</b><br></br>

 It's generally preferable to form unconditional @(see rewrite) rules unless
 there is a danger of case explosion.  That is, rather than pairs of rules such
 as</p>

 @({
  (implies p
           (equal term1 term2))
 })

 <p>and</p>

 @({
  (implies (not p)
           (equal term1 term3))
 })

 <p>consider:</p>

 @({
  (equal term1
         (if p term2 term3))
 })

 <p>However, sometimes this strategy can lead to case explosions: @(tsee IF)
 @(see term)s introduce cases in ACL2.  Use your judgment.  (On the subject of
 @(tsee IF): @(tsee COND), @(tsee CASE), @(tsee AND), and @(tsee OR) are macros
 that abbreviate @(tsee IF) forms, and propositional functions such as @(tsee
 IMPLIES) quickly expand into @(tsee IF) @(see term)s.)</p>

 <p><b>B6. Create elegant theorems.</b><br></br>

 Try to formulate lemmas that are as simple and general as possible.  For
 example, sometimes properties about several functions can be ``factored'' into
 lemmas about one function at a time.  Sometimes the elimination of unnecessary
 hypotheses makes the theorem easier to prove, as does generalizing first by
 hand.</p>

 <p><b>B7. Use</b> @(tsee defaxiom)s <b>temporarily to explore
 possibilities.</b><br></br>

 When there is a difficult goal that seems to follow immediately (by a
 @(':use') hint or by rewriting) from some other lemmas, you can create those
 lemmas as @(tsee defaxiom) @(see events) (or, the application of @(tsee
 skip-proofs) to @(tsee defthm) @(see events)) and then double-check that the
 difficult goal really does follow from them.  Then you can go back and try to
 turn each @(tsee defaxiom) into a @(tsee defthm).  When you do that, it's
 often useful to @(see disable) any additional @(see rewrite) rules that you
 prove in the process, so that the ``difficult goal'' will still be proved from
 its lemmas when the process is complete.</p>

 <p>Better yet, rather than disabling @(see rewrite) rules, use the @(tsee
 local) mechanism offered by @(tsee encapsulate) to make temporary rules
 completely @(tsee local) to the problem at hand.  See @(see encapsulate) and
 see @(see local).</p>

 <p><b>B9. Use books.</b><br></br>

 Consider using previously certified @(see books), especially for @(see
 arithmetic) reasoning.  This cuts down the duplication of effort and starts
 your specification and proof effort from a richer foundation.  See @(see
 community-books).</p>

 <p><i>C. DEALING WITH FAILED PROOFS</i></p>

 <p><b>C1. Look in proof output for goals that can't be further
 simplified.</b><br></br>

 Use the ``@(see proof-tree)'' utility to explore the proof space.  However,
 you don't need to use that tool to use the ``checkpoint'' strategy.  The idea
 is to think of ACL2 as a ``simplifier'' that either proves the theorem or
 generates some goal to consider.  That goal is the first ``checkpoint,'' i.e.,
 the first goal that does not further simplify.  Exception: it's also important
 to look at the induction scheme in a proof by induction, and if induction
 seems appropriate, then look at the first checkpoint <i>after</i> the
 induction has begun.</p>

 <p>Consider whether the goal on which you focus is even a theorem.  Sometimes
 you can execute it for particular values to find a counterexample.</p>

 <p>When looking at checkpoints, remember that you are looking for any reason
 at all to believe the goal is a theorem.  So for example, sometimes there may
 be a contradiction in the hypotheses.</p>

 <p>Don't be afraid to skip the first checkpoint if it doesn't seem very
 helpful.  Also, be willing to look a few lines up or down from the checkpoint
 if you are stuck, bearing in mind however that this practice can be more
 distracting than helpful.</p>

 <p><b>C2. Use the ``break rewrite'' facility.</b><br></br>

 @(tsee Brr) and related utilities let you inspect the ``rewrite stack.''
 These can be valuable tools in large proof efforts.  See @(see break-lemma)
 for an introduction to these tools, and see @(see break-rewrite) for more
 complete information.</p>

 <p>The break facility is especially helpful in showing you why a particular
 rewrite rule is not being applied.</p>

 <p><b>C3. Use induction hints when necessary.</b> Of course, if you can define
 your functions so that they suggest the correct inductions to ACL2, so much
 the better!  But for complicated inductions, induction @(see hints) are
 crucial.  See @(see hints) for a description of @(':induct') @(see hints).</p>

 <p><b>C4. Use the interactive ``Proof-Builder'' to explore.</b><br></br>

 The @(tsee verify) command supplied by ACL2 allows one to explore problem
 areas ``by hand.''  However, even if you succeed in proving a conjecture with
 @(tsee verify), it is useful to prove it without using it, an activity that
 will often require the discovery of @(see rewrite) rules that will be useful
 in later proofs as well.</p>

 <p><b>C5. Don't have too much patience.</b><br></br>

 Interrupt the prover fairly quickly when simplification isn't succeeding.</p>

 <p><b>C6. Simplify rewrite rules.</b><br></br>

 When it looks difficult to relieve the hypotheses of an existing @(see
 rewrite) rule that ``should'' apply in a given setting, ask yourself if you
 can eliminate a hypothesis from the existing @(see rewrite) rule.  If so, it
 may be easier to prove the new version from the old version (and some
 additional lemmas), rather than to start from scratch.</p>

 <p><b>C7. Deal with base cases first.</b><br></br>

 Try getting past the base case(s) first in a difficult proof by induction.
 Usually they're easier than the inductive step(s), and rules developed in
 proving them can be useful in the inductive step(s) too.  Moreover, it's
 pretty common that mistakes in the statement of a theorem show up in the base
 case(s) of its proof by induction.</p>

 <p><b>C8. Use</b> @(':expand') <b>hints.</b> Consider giving @(':expand')
 @(see hints).  These are especially useful when a proof by induction is
 failing.  It's almost always helpful to open up a recursively defined function
 that is supplying the induction scheme, but sometimes ACL2 is too timid to do
 so; or perhaps the function in question is @(see disable)d.</p>

 <p><i>D. PERFORMANCE TIPS</i></p>

 <p><b>D1. Disable rules.</b><br></br>

 There are a number of instances when it is crucial to @(see disable) rules,
 including (often) those named explicitly in @(':use') @(see hints).  Also,
 @(see disable) recursively defined functions for which you can prove what seem
 to be all the relevant properties.  The prover can spend significant time
 ``behind the scenes'' trying to open up recursively defined functions, where
 the only visible effect is slowness.</p>

 <p><b>D2. Turn off the ``break rewrite'' facility.</b> Remember to execute
 @(':brr nil') after you've finished with the ``break rewrite'' utility (see
 @(see break-rewrite)), in order to bring the prover back up to full speed.</p>

 <p><i>E. MISCELLANEOUS TIPS AND KNOWLEDGE</i></p>

 <p><b>E1. Order of application of rewrite rules.</b><br></br>

 Keep in mind that the most recent @(see rewrite) rules in the @(see history)
 are tried first.</p>

 <p><b>E2. Relieving hypotheses is not full-blown theorem proving.</b><br></br>

 Relieving hypotheses on @(see rewrite) rules is done by rewriting and @(see
 linear) arithmetic alone, not by case splitting or by other prover processes
 ``below'' simplification.</p>

 <p><b>E3. ``Free variables'' in rewrite rules.</b><br></br> The set of ``free
  variables'' of a @(see rewrite) rule is defined to contain those variables
  occurring in the rule that do not occur in the left-hand side of the rule.
  It's often a good idea to avoid rules containing free variables because they
  are ``weak,'' in the sense that hypotheses containing such variables can
  generally only be proved when they are ``obviously'' present in the current
  context.  This weakness suggests that it's important to put the most
  ``interesting'' (specific) hypotheses about free variables first, so that the
  right instances are considered.  For example, suppose you put a very general
  hypothesis such as @('(consp x)') first.  If the context has several @(see
  term)s around that are known to be @(tsee consp)s, then @('x') may be bound
  to the wrong one of them.  For much more information on free variables, see
  @(see free-variables).</p>

 <p><b>E4. Obtaining information</b><br></br>

 Use @(':')@(tsee pl) @('foo') to inspect @(see rewrite) rules whose left hand
 sides are applications of the function @('foo').  Another approach to seeing
 which @(see rewrite) rules apply is to enter the interactive @(see
 proof-builder) with @(tsee verify), and use the @('show-rewrites') or @('sr')
 command.</p>

 <p><b>E5. Consider esoteric rules with care.</b><br></br>

 If you care to see @(see rule-classes) and peruse the list of subtopics (which
 will be listed right there in most versions of this @(see documentation)),
 you'll see that ACL2 supports a wide variety of rules in addition to
 @(':')@(see rewrite) rules.  Should you use them?  This is a complex question
 that we are not ready to answer with any generality.  Our general advice is to
 avoid relying on such rules as long as you doubt their utility.  More
 specifically: be careful not to use conditional type prescription rules, as
 these have been known to bring ACL2 to its knees, unless you are conscious
 that you are doing so and have reason to believe that they are working
 well.</p>

 <p><i>F. SOME THINGS YOU DON'T NEED TO KNOW</i></p>

 <p>Most generally: you shouldn't usually need to be able to predict too much
 about ACL2's behavior.  You should mainly just need to be able to react to
 it.</p>

 <p><b>F1. Induction heuristics.</b><br></br>

 Although it is often important to read the part of the prover's
 output that gives the induction scheme chosen by the prover, it is
 not necessary to understand how the prover made that choice.
 (Granted, advanced users may occasionally gain minor insight from such
 knowledge.  But it's truly minor in many cases.)  What <i>is</i> important is
 to be able to tell it an appropriate induction when it doesn't pick the right
 one (after noticing that it doesn't).  See C3 above.</p>

 <p><b>F2. Heuristics for expanding calls of recursively defined
 functions.</b><br></br>

 As with the previous topic, the important thing isn't to understand these
 heuristics but, rather, to deal with cases where they don't seem to be
 working.  That amounts to supplying @(':expand') @(see hints) for those calls
 that you want opened up, which aren't.  See also C8 above.</p>

 <p><b>F3. The ``waterfall''.</b><br></br>

 As discussed many times already, a good strategy for using ACL2 is to look for
 checkpoints (goals stable under simplification) when a proof fails, perhaps
 using the @(see proof-tree) facility.  Thus, it is reasonable to ignore almost
 all the prover output, and to avoid pondering the meaning of the other
 ``processes'' that ACL2 uses besides simplification (such as elimination,
 cross-fertilization, generalization, and elimination of irrelevance).  For
 example, you don't need to worry about prover output that mentions ``type
 reasoning'' or ``abbreviations,'' for example.</p>")

(defxdoc toggle-pc-macro
  :parents (proof-builder)
  :short "Change an ordinary macro command to an atomic macro, or vice-versa"
  :long "@({
  Example:
  (toggle-pc-macro pro)
 })

 <p>Change @('pro') from an atomic macro command to an ordinary one (or
 vice-versa, if @('pro') happens to be an ordinary macro command)</p>

 @({
  General Form:
  (toggle-pc-macro name &optional new-tp)
 })

 <p>If name is an atomic macro command then this turns it into an ordinary one,
 and vice-versa.  However, if @('new-tp') is supplied and not @('nil'), then it
 should be the new type (the symbol @('macro') or @('atomic-macro'), in any
 package), or else there is no change.</p>")

(defxdoc top-level
  :parents (miscellaneous)
  :short "Evaluate a top-level form as a function body"
  :long "<p>Some forms, such as calls of @(tsee with-local-stobj), are illegal
 when supplied directly to the ACL2 top-level loop.  The macro @('top-level')
 provides a workaround in such cases, by defining a temporary @(':')@(tsee
 program)-mode function named @('top-level-fn') whose only argument is
 @('state') and whose body is the form to be evaluated.  When the call of
 @('top-level') returns there is no change to the existing ACL2 logical @(see
 world).  The following edited log illustrates all of the above points.</p>

 @({
  ACL2 !>:pbt 0
            0  (EXIT-BOOT-STRAP-MODE)
  ACL2 !>(defstobj st fld)

  Summary
  Form:  ( DEFSTOBJ ST ...)
  Rules: NIL
  Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
   ST
  ACL2 !>(top-level
          (with-local-stobj
           st
           (mv-let (result st)
                   (let ((st (update-fld 17 st)))
                     (mv (fld st) st))
                   result)))
  17
  ACL2 !>(top-level
          (with-local-stobj
           st
           (mv-let (result st)
                   (let ((st (update-fld 17 st)))
                     (mv (fld st) st))
                   (mv nil result state))))
   17
  ACL2 !>(top-level
          (with-local-stobj
           st
           (mv-let (result st)
                   (let ((st (update-fld 17 st)))
                     (mv (fld st) st))
                   (mv result state))))
  (17 <state>)
  ACL2 !>:pbt 0
            0  (EXIT-BOOT-STRAP-MODE)
     d      1:x(DEFSTOBJ ST FLD)
  ACL2 !>
 })

 <p>Each argument of @('top-level') after the first should be a @(tsee declare)
 form or @(see documentation) string, as the list of these extra arguments will
 be placed before the first argument when forming the definition of
 @('top-level-fn').</p>

 <p>@(tsee Top-level) generates a call of @(tsee ld), so that the value
 returned is printed in the normal way.  The call of @(tsee top-level) itself
 actually evaluates to @('(mv erp :invisible state)'), where @('erp') is @('t')
 if and only evaluation of the call of @('top-level-fn') caused an error, which
 normally results in no additional output.  (For details about ``caused an
 error'', see the definition of @('top-level') in the ACL2 source code, and see
 @(see ld-error-action).)</p>")

(defxdoc trace
  :parents (debugging)
  :short "Tracing functions in ACL2"
  :long "<p>ACL2 provides a trace utility, @(tsee trace$), with corresponding
 reverse operation @(tsee untrace$).  These can be used without any dependence
 on the underlying Lisp utility, and are the tracing utilities of choice in
 ACL2; see @(see trace$) and see @(see untrace$).</p>

 <p>However, for advanced users we note that the underlying host Lisp may also
 provide a trace utility, @('trace'), and corresponding @('untrace').
 Moreover, these have been modified in the case that the host Lisp is GCL,
 Allegro CL, or CCL (OpenMCL), to provide limited support for @(':entry'),
 @(':exit'), and perhaps @(':cond') keywords, to hide certain large data
 structures (world, enabled structure, rewrite constant), and to trace
 executable-counterparts (see @(see evaluation)).  See source files
 @('*-trace.lisp').  For the above Lisps, you can invoke the original
 @('trace') and @('untrace') by invoking @('old-trace') and @('old-untrace'),
 respectively, in raw Lisp rather than in the normal ACL2 loop.</p>")

(defxdoc trace!
  :parents (trace)
  :short "Trace the indicated functions after creating an active trust tag"
  :long "@({
  Example:
  (trace! (fact :native t :entry *foo*))

  General Form:
  (trace! spec1 ... specn)
 })

 <p>where the @('speci') are suitable arguments to @(tsee trace$).</p>

 <p>See @(see trace$) for a way to trace function calls.  Some calls of
 @('trace$') are potentially dangerous and thus require a trust tag (see @(see
 defttag)).  But it can be a nuisance to call @('defttag') explicitly, so the
 @('trace!') macro is provided in order to avoid the need to do that:
 @('trace!') automatically defines a (temporary) trust tag.</p>

 <p>See @(see untrace$) for how to undo the effect of @(tsee trace!).</p>

 <p>The evaluation of a @('trace!') form causes temporary creation of an active
 trust tag, @(':trace!'), followed by the corresponding @('trace$') form.  The
 trust tag will disappear when the call to @('trace!') completes.  Even though
 @('trace!') will remove its temporary ttag, it will still print a ``@('TTAG
 NOTE')'', which indicates that the session is suspect.  See @(see defttag) and
 see @(see ttags-seen) for further remarks on this issue.</p>

 <p>Because of the active trust tag, it is possible to do things with
 @('trace!')  that are useful but without logical justification.  Below is an
 example of how to use @('trace!') to cause a function call to change @(see
 state), even though the function does not take @(tsee state) as a
 parameter.  Note: It may be helpful to see @(see evaluation) in order to
 understand the package prefix @('\"ACL2_*1*_ACL2\"') displayed below.</p>

 @({
  ACL2 !>(defun fact (n)
           (declare (xargs :guard (natp n) :verify-guards nil))
           (if (zp n)
               1
             (* n (fact (1- n)))))

  The admission of FACT 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 N).  We observe that the type of FACT is described by the
  theorem (AND (INTEGERP (FACT N)) (< 0 (FACT N))).  We used the :compound-
  recognizer rule ZP-COMPOUND-RECOGNIZER and primitive type reasoning.

  Summary
  Form:  ( DEFUN FACT ...)
  Rules: ((:COMPOUND-RECOGNIZER ZP-COMPOUND-RECOGNIZER)
          (:FAKE-RUNE-FOR-TYPE-SET NIL))
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FACT
  ACL2 !>(defun update-foo (n value state)
           (declare (xargs :stobjs state :verify-guards nil))
           (assign foo (cons (cons n value) (@ foo))))

  Since UPDATE-FOO is non-recursive, its admission is trivial.  We observe
  that the type of UPDATE-FOO is described by the theorem
  (AND (CONSP (UPDATE-FOO N VALUE STATE))
       (TRUE-LISTP (UPDATE-FOO N VALUE STATE))).
  We used primitive type reasoning.

  (UPDATE-FOO * * STATE) => (MV * * STATE).

  Summary
  Form:  ( DEFUN UPDATE-FOO ...)
  Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   UPDATE-FOO
  ACL2 !>(trace! (fact :exit (update-foo n value state)))

  TTAG NOTE: Adding ttag :TRACE! from the top level loop.
   ((FACT :EXIT (UPDATE-FOO N VALUE STATE)))
  ACL2 !>(assign foo nil)
   NIL
  ACL2 !>(fact 7)
  1> (ACL2_*1*_ACL2::FACT 7)
    2> (ACL2_*1*_ACL2::FACT 6)
      3> (ACL2_*1*_ACL2::FACT 5)
        4> (ACL2_*1*_ACL2::FACT 4)
          5> (ACL2_*1*_ACL2::FACT 3)
            6> (ACL2_*1*_ACL2::FACT 2)
              7> (ACL2_*1*_ACL2::FACT 1)
                8> (ACL2_*1*_ACL2::FACT 0)
                <8 NIL
              <7 NIL
            <6 NIL
          <5 NIL
        <4 NIL
      <3 NIL
    <2 NIL
  <1 NIL
  5040
  ACL2 !>(@ foo)
  ((7 . 5040)
   (6 . 720)
   (5 . 120)
   (4 . 24)
   (3 . 6)
   (2 . 2)
   (1 . 1)
   (0 . 1))
  ACL2 !>(verify-guards fact)

  Computing the guard conjecture for FACT....

  The guard conjecture for FACT is trivial to prove, given the :compound-
  recognizer rules NATP-COMPOUND-RECOGNIZER and ZP-COMPOUND-RECOGNIZER,
  primitive type reasoning and the :type-prescription rule FACT.  FACT
  is compliant with Common Lisp.

  Summary
  Form:  ( VERIFY-GUARDS FACT)
  Rules: ((:COMPOUND-RECOGNIZER NATP-COMPOUND-RECOGNIZER)
          (:COMPOUND-RECOGNIZER ZP-COMPOUND-RECOGNIZER)
          (:FAKE-RUNE-FOR-TYPE-SET NIL)
          (:TYPE-PRESCRIPTION FACT))
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   FACT
  ACL2 !>(assign foo nil)
   NIL
  ACL2 !>(fact 7)
  1> (ACL2_*1*_ACL2::FACT 7)
    2> (FACT 7)
      3> (FACT 6)
        4> (FACT 5)
          5> (FACT 4)
            6> (FACT 3)
              7> (FACT 2)
                8> (FACT 1)
                  9> (FACT 0)
                  <9 NIL
                <8 NIL
              <7 NIL
            <6 NIL
          <5 NIL
        <4 NIL
      <3 NIL
    <2 NIL
  <1 NIL
  5040
  ACL2 !>(@ foo)
  ((7 . 5040)
   (7 . 5040)
   (6 . 720)
   (5 . 120)
   (4 . 24)
   (3 . 6)
   (2 . 2)
   (1 . 1)
   (0 . 1))
  ACL2 !>(trace! (fact :exit (progn (update-foo n value state)
                                    (cons traced-fn values))))

  TTAG NOTE: Adding ttag :TRACE! from the top level loop.
   ((FACT :EXIT (PROGN (UPDATE-FOO N VALUE STATE)
                       (CONS TRACED-FN VALUES))))
  ACL2 !>(assign foo nil)
   NIL
  ACL2 !>(fact 7)
  1> (ACL2_*1*_ACL2::FACT 7)
    2> (FACT 7)
      3> (FACT 6)
        4> (FACT 5)
          5> (FACT 4)
            6> (FACT 3)
              7> (FACT 2)
                8> (FACT 1)
                  9> (FACT 0)
                  <9 (FACT 1)
                <8 (FACT 1)
              <7 (FACT 2)
            <6 (FACT 6)
          <5 (FACT 24)
        <4 (FACT 120)
      <3 (FACT 720)
    <2 (FACT 5040)
  <1 (ACL2_*1*_ACL2::FACT 5040)
  5040
  ACL2 !>(@ foo)
  ((7 . 5040)
   (7 . 5040)
   (6 . 720)
   (5 . 120)
   (4 . 24)
   (3 . 6)
   (2 . 2)
   (1 . 1)
   (0 . 1))
  ACL2 !>
 })

 <p>Finally, we remark that using @('trace!') can cause errors in situations
 where tracing is automatically suspended and re-introduced.  This is likely to
 be a rare occurrence, but consider the following example.</p>

 @({
  (trace! (lexorder :native t :multiplicity 1))
  (certify-book \"foo\" 0 t)
 })

 <p>If the certify-book causes compilation, you may see an error such as the
 following.</p>

 @({
  ACL2 Error in (CERTIFY-BOOK \"foo\" ...):  The keyword :NATIVE cannot
  be used in a trace spec unless there is an active trust tag.  The trace
  spec (LEXORDER :NATIVE T :MULTIPLICITY 1) is thus illegal.  Consider
  using trace! instead.  The complete list of keywords that require a
  trust tag for use in a trace spec is: (:NATIVE :DEF :MULTIPLICITY).
 })

 <p>This error is harmless.  The function will appear, when calling
 @('(trace$)'), to remain traced, but in fact there will be no tracing
 behavior, so you may want to call @(tsee untrace$) on the function symbol in
 question.</p>")

(defxdoc trace$
  :parents (trace)
  :short "Trace function evaluations"
  :long "@({
  Examples:
  (trace$ foo bar)     ; trace foo and bar
  (trace$)             ; return current trace info (no new tracing specified)
  (trace$ (foo :entry  ; trace foo, printing first actual parameter upon entry
               (car arglist)))
  (trace$ (foo :exit   ; trace foo, using fmt to print upon exit
               (:fmt (msg \"Exiting FOO with ~x0\"
                          value))))
  (trace$ (foo :native t))

  General Forms:
  (trace$ spec1 spec2 ... specn) ; n >= 1
  (trace$)
 })

 <p>where the @('speci') are trace specs, as described below.</p>

 <p>@('Trace$') installs alternate code for the indicated functions that prints
 information upon entry to, and exit from, calls of the functions.  For an
 alternate tracing utility used for educational purposes in <a
 href='http://acl2s.ccs.neu.edu/acl2s/doc/'>ACL2s</a>, see community book
 @('books/misc/trace-star.lisp').</p>

 <p>From a logical perspective all trace printing is a fiction.  (But see @(see
 trace!)  for a way to get around this and modify @(see state).)  For a related
 fiction, see @(see cw).  @('(Trace$)') returns the list of currently-active
 trace specs, while the application of @('trace$') to at least one argument
 returns the list of its arguments that are successfully acted on.</p>

 <p>Output from @(tsee trace$) normally goes to the screen, i.e., to @(tsee
 standard-co).  But it can be redirected to a file; see @(see
 open-trace-file).</p>

 <p>See @(see untrace$) for how to undo the effect of @(tsee trace$).  Also see
 @(see trace) for mention of modifications made to raw Lisp trace, which is
 accessible (as described below) using the @(':native') keyword.</p>

 <p>Note that when @('trace$') is applied to a function without option
 @(':native'), that function's declarations and documentation are
 discarded.</p>

 <p>Next, we introduce tracing with some examples.  After that, we provide
 reference documentation for individual trace options allowed in a trace spec.
 Note that although our example focuses on user-defined functions, @('trace$')
 can also be applied to built-in functions, though perhaps only system hackers
 should take advantage of this observation.</p>

 <p>We begin by illustrating the simplest sort of trace spec: a function
 symbol.  For example, the form @('(trace$ foo bar)') directs the tracing of
 functions @('foo') and @('bar') by virtue of the two trace specs @('foo') and
 @('bar').  We can see tracing in action by first defining:</p>

 @({
  (defun f (x)
    (cons x x))

  (defun g (x)
    (list (f x) 3))
 })

 <p>The following log then illustrates tracing of these two functions.  Notice
 that before @(see guard)s have been verified, the ``executable-counterpart
 functions'' are called but the corresponding submitted functions are
 not (see (@see evaluation) for relevant background); but after guard
 verification of @('f'), the submitted function for @('f') is indeed called.
 (See @(see guard) and see @(see guard-evaluation-examples-log).)</p>

 @({
  ACL2 !>(trace$ f g)
   ((F) (G))
  ACL2 !>(g 7)
  1> (ACL2_*1*_ACL2::G 7)
    2> (ACL2_*1*_ACL2::F 7)
    <2 (ACL2_*1*_ACL2::F (7 . 7))
  <1 (ACL2_*1*_ACL2::G ((7 . 7) 3))
  ((7 . 7) 3)
  ACL2 !>(verify-guards f)

  Computing the guard conjecture for F....

  The guard conjecture for F is trivial to prove.  F is compliant with
  Common Lisp.

  Summary
  Form:  ( VERIFY-GUARDS F)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   F
  ACL2 !>(g 7)
  1> (ACL2_*1*_ACL2::G 7)
    2> (ACL2_*1*_ACL2::F 7)
      3> (F 7)
      <3 (F (7 . 7))
    <2 (ACL2_*1*_ACL2::F (7 . 7))
  <1 (ACL2_*1*_ACL2::G ((7 . 7) 3))
  ((7 . 7) 3)
  ACL2 !>
 })

 <p>The following example introduces trace specs other than function symbols.
 Consider the following definition.</p>

 @({
  (defun fact (n)
    (declare (xargs :guard (natp n)))
    (if (zp n)
        1
      (* n (fact (1- n)))))
 })

 <p>The following log illustrates the use of trace options @(':cond')
 (condition for entering trace), @(':entry') (what to print on entry), and
 @(':exit') (what to print on exit).  The reason for two calls on argument 4 is
 that we are seeing such calls for the executable-counterpart of @('fact') and
 also its raw Lisp function.</p>

 @({
  ACL2 !>(trace$ (fact :cond (evenp (car arglist))
                       :entry (cons 'factorial-call arglist)
                       :exit (car values)))
   ((FACT :COND (EVENP (CAR ARGLIST))
          :ENTRY (CONS 'FACTORIAL-CALL ARGLIST)
          :EXIT (CAR VALUES)))
  ACL2 !>(fact 4)
  1> (FACTORIAL-CALL 4)
    2> (FACTORIAL-CALL 4)
      3> (FACTORIAL-CALL 2)
        4> (FACTORIAL-CALL 0)
        <4 1
      <3 2
    <2 24
  <1 24
  24
  ACL2 !>
 })

 <p>Notice that @('VALUES') above is the list of all values returned, which is
 a one-element list unless @(tsee mv) return is used, as illustrated in the
 following example, after defining: @('(defun two-vals (x) (mv x 7))').</p>

 @({
  ACL2 !>(trace$ two-vals)
   ((TWO-VALS))
  ACL2 !>(two-vals 3)
  1> (ACL2_*1*_ACL2::TWO-VALS 3)
  <1 (ACL2_*1*_ACL2::TWO-VALS 3 7)
  (3 7)
  ACL2 !>(verify-guards two-vals)

  Computing the guard conjecture for TWO-VALS....

  The guard conjecture for TWO-VALS is trivial to prove, given the :executable-
  counterpart of CONS.  TWO-VALS is compliant with Common Lisp.

  Summary
  Form:  ( VERIFY-GUARDS TWO-VALS)
  Rules: ((:EXECUTABLE-COUNTERPART CONS))
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
   TWO-VALS
  ACL2 !>(two-vals 3)
  1> (ACL2_*1*_ACL2::TWO-VALS 3)
    2> (TWO-VALS 3)
    <2 (TWO-VALS 3 7)
  <1 (ACL2_*1*_ACL2::TWO-VALS 3 7)
  (3 7)
  ACL2 !>
 })

 <p>We now document all of the options that may appear in a trace spec.  A
 trace spec with options is of the form</p>

 @({
  (fn :kwd1 val1 :kwd2 val2 ... :kwdn valn)
 })

 <p>and here we document each legal keyword @(':kwdi') and corresponding
 expected value @('vali').  Note that @('trace$') is intended primarily for
 functions defined in the ACL2 command loop (see @(see lp)).  If you want to
 trace a function that is defined in raw Lisp, then you can use option
 @(':native') (see below), but then many other @('trace$') options will not be
 available to you: all of them except @(':multiplicity') and @(':native')
 itself will be passed directly to the @('trace') utility of the underlying
 Common Lisp.</p>

 <p>@(':COND'), @(':ENTRY'), and @(':EXIT')</p>

 <p><b>Introduction</b>.  For each of these three options, the value is a
 (user-level) term, except that for @(':entry') and @(':exit') the value can be
 of the form @('(:fmt u)') or @('(:fmt! u)'), where @('u') is a user-level
 term.  We skip these two latter cases for now and return to them later.  Then
 the indicated term is evaluated as indicated in the next paragraph, and if the
 @(':cond') term is omitted or evaluates to non-@('nil'), then the value of the
 @(':entry') term is printed on entry and the value of the @(':exit') term is
 printed on exit.  By default, where @(':entry') is omitted or is specified as
 @('nil'), the value printed for @(':entry') is the list obtained by consing
 the calling function symbol onto the list of actual parameters: in the
 notation described below, this is @('(cons TRACED-FN ARGLIST)').  Similarly,
 the default for printing at the exit of the function call, i.e. where
 @(':exit') is omitted or is specified as @('nil'), is @('(cons TRACED-FN
 VALUES)') where @('VALUES') is the list of values returned as described
 below.</p>

 <p><b>Available Variables</b>.  In the evaluations of the term described below
 upon a call of @('fn'), each formal parameter of the definition of @('fn')
 will be bound to the corresponding actual of the call, the variable
 @('ARGLIST') will be bound to the list of actuals, and the variable
 @('TRACED-FN') will be bound to the function being called (either @('fn') or
 its executable-counterpart function; see above).  Additionally in the case of
 @(':exit'), the variable @('VALUES') will be bound to the multiple values
 returned (thus, a one-element list if @(tsee mv) is not used in the return).
 Also for @(':exit'), we bind @('VALUE') to the logical value returned, i.e.,
 to the suitable list of values returned in the @(tsee mv) case and otherwise
 to the single value returned.  So in the @('mv') case, @('VALUE') is the same
 as @('VALUES'), and otherwise @('VALUE') is @('(car VALUES)').  Other than
 these variables and @(tsee STATE), no other variable may occur in the term,
 whose value must be a single non-@(tsee stobj) value, unless there is an
 active trust tag (see @(see defttag)).</p>

 <p>Now suppose @('fn') is called.  First: If @(':cond') is supplied and the
 result of evaluating the @(':cond') term is @('nil'), then no tracing is done.
 Otherwise tracing proceeds as follows.  First the @(':entry') form is
 evaluated, and the result is printed.  Then the call of @('fn') is evaluated.
 Finally the @(':exit') term is evaluated and the result is printed.  As
 indicated above, the default for the @(':entry') term if omitted or explicitly
 @('nil') is @('(cons TRACED-FN ARGLIST)'), and the default for the @(':exit')
 term if omitted or explicitly @('nil') is @('(cons TRACED-FN VALUES)').</p>

 <p>Note that if the function has a formal named @('ARGLIST'), then
 @('ARGLIST') will nevertheless refer to the entire list of formals, not the
 single formal named @('ARGLIST'); similarly for @('TRACED-FN'), and
 additionally for @('VALUE') and @('VALUES') in the case of @(':exit').</p>

 <p>As mentioned above, for each of @(':entry') and @(':exit'), a value of
 @('nil') specifies the default behavior.  If you really want a value of
 @('nil'), use a non-@('nil') form that evaluates to @('nil'), for example
 @('(car nil)') or @(''nil').  However, for @(':cond') a value of @('nil')
 means what it says: do not evaluate the @(':entry') or @(':exit') forms.</p>

 <p>Finally we discuss the case that the @(':entry') or @(':exit') term is of
 the form @('(:fmt u)') or @('(:fmt! u)').  In these cases, the term @('u') is
 evaluated as described above to produce a value, say @('msg'), but instead of
 printing @('msg') directly, ACL2 calls @('fmt1') using the string @('\"~@0\"')
 and the alist that binds just character @('#\\0') to @('msg').  The following
 example illustrates this point, where @('fact') is defined as above.  Also see
 @(see fmt).  Note that @('(msg string . vals)') produces a value suitable for
 a @('\"~@\"') directive to the @('fmt') family of print functions.</p>

 @({
  ACL2 !>(trace$
          (fact
           :entry (:fmt (msg \"Tracing ~x0 on ~x1\" traced-fn arglist))
           :exit (car values)))
   ((FACT :ENTRY (:FMT (MSG \"Tracing ~x0 on ~x1\" TRACED-FN ARGLIST))
          :EXIT (CAR VALUES)))
  ACL2 !>(fact 3)
  1> Tracing ACL2_*1*_ACL2::FACT on (3)
    2> Tracing FACT on (3)
      3> Tracing FACT on (2)
        4> Tracing FACT on (1)
          5> Tracing FACT on (0)
          <5 1
        <4 1
      <3 2
    <2 6
  <1 6
  6
  ACL2 !>
 })

 <p>If @(':fmt!') is used instead of @(':fmt'), then indentation as is the
 prefix string, @('\"n> \"') or @('\"<n \"').  The following example
 illustrates the use of @(':fmt!').</p>

 @({
  ACL2 !>(trace$
          (fact
           :entry (:fmt! (msg \"Tracing ~x0 on ~x1\" traced-fn arglist))
           :exit (:fmt! (msg \"From input ~x0: ~x1\"
                             (car arglist) (car values)))))
   ((FACT :ENTRY (:FMT! (MSG \"Tracing ~x0 on ~x1\" TRACED-FN ARGLIST))
          :EXIT (:FMT! (MSG \"From input ~x0: ~x1\" (CAR ARGLIST)
                            (CAR VALUES)))))
  ACL2 !>(fact 3)
  Tracing ACL2_*1*_ACL2::FACT on (3)
  Tracing FACT on (3)
  Tracing FACT on (2)
  Tracing FACT on (1)
  Tracing FACT on (0)
  From input 0: 1
  From input 1: 1
  From input 2: 2
  From input 3: 6
  From input 3: 6
  6
  ACL2 !>
 })

 <p>Here is the same example, with user-managed indentation.</p>

 @({
  ACL2 !>(trace$
          (fact
           :entry (:fmt! (msg \"~t0Tracing ~x1 on ~x2\"
                              (+ 3 (* 2 (@ trace-level)))
                              traced-fn arglist))
           :exit (:fmt! (msg \"~t0From input ~x1: ~x2\"
                             (1+ (* 2 (@ trace-level)))
                             (car arglist) (car values)))))
   ((FACT :ENTRY (:FMT! (MSG \"~t0Tracing ~x1 on ~x2\"
                             (+ 3 (* 2 (@ TRACE-LEVEL)))
                             TRACED-FN ARGLIST))
          :EXIT (:FMT! (MSG \"~t0From input ~x1: ~x2\"
                            (1+ (* 2 (@ TRACE-LEVEL)))
                            (CAR ARGLIST)
                            (CAR VALUES)))))
  ACL2 !>(fact 3)
     Tracing ACL2_*1*_ACL2::FACT on (3)
       Tracing FACT on (3)
         Tracing FACT on (2)
           Tracing FACT on (1)
             Tracing FACT on (0)
             From input 0: 1
           From input 1: 1
         From input 2: 2
       From input 3: 6
     From input 3: 6
  6
  ACL2 !>
 })

 <p><b>ADVANCED OPTIONS</b> (alphabetical list)</p>

 <p>@(':COMPILE')</p>

 <p>The tracing of @('fn') installs a substitute definition of @('fn') that
 prints trace information.  If the @(':compile') option is omitted or has value
 @(':same'), then the new definition will be compiled if and only if the
 existing definition is already compiled.  Otherwise, the new definition will
 be compiled exactly when the value of @(':compile') is not @('nil').</p>

 <p>@(':DEF'), @(':MULTIPLICITY')</p>

 <p>ACL2's @('trace$') mechanism often needs to know the number of outputs of a
 traced function, in the sense of @(tsee mv).  If you trace a function that was
 not defined inside the ACL2 loop (hence you are using the @(':native')
 option), or if you provide an alternative definition using option @(':def')
 (see below) and the new definition changes the number of values returned, then
 a natural number value for @(':multiplicity') informs the trace utility of the
 number of expected outputs of the function being traced.  In the case that
 @(':native') is supplied, the effect of a non-@('nil') @(':multiplicity')
 value depends on the host Lisp.  In the case of Lisps for which ACL2 uses the
 built-in Lisp mechanism for returning multiple values (see @(see mv)), which
 are CCL and threaded SBCL as of June, 2010, @(':multiplicity') is not needed
 and is ignored with @(':native t').  For GCL and Allegro CL,
 @(':multiplicity') is used to generate a suitable @(':exit') form if the
 @(':exit') keyword was not already supplied.  For the other Lisps, the
 @(':multiplicity') value is treated essentially as 1 whether it is supplied or
 not, because we do not know how to pass suitable information based on this
 value to the host Lisp's built-in tracing mechanism.</p>

 <p>Note that even supplying a @(':multiplicity') option does not change the
 meaning of the variable @('values').  See the discussion of @(':native')
 below.</p>

 <p>A useful option can be to supply a definition as the value of @(':def').
 (Again, note that if @(':native') is used, then all options other than
 @(':multiplicity') are passed directly to the underlying Lisp; in particular,
 @(':def') will have no effect with @(':native') except in the unlikely case
 that the raw Lisp provides some sort of support for @(':def').)  Note that
 this definition should be like a @(tsee defun) form, but without the leading
 @('defun') symbol; and it should define the function symbol being traced, with
 the same formal parameter list.  However, tracing of the
 ``executable-counterpart'' of a function (see @(see evaluation) is not
 sensitive to the @(':def') option; rather, if a function has an
 executable-counterpart then that executable-counterpart is traced.</p>

 <p>@(':EVISC-TUPLE')</p>

 <p>The printing described above is, by default, done using the current default
 trace evisc-tuple, which can be set using @(tsee set-trace-evisc-tuple) (for
 the shape of this tuple, see @(see evisc-tuple)); see @(see
 set-trace-evisc-tuple).  This tuple is based by default on the raw Lisp
 variables @('*print-level*') and @('*print-length*'), and will hide the ACL2
 @(see world) and handle @(see stobj)s appropriately.  You may override this
 default by supplying an evisc tuple with the @(':evisc-tuple') argument in
 your trace spec.  Be careful to supply a valid evisc-tuple, or you may get a
 raw Lisp error!</p>

 <p>A special value, @(':print'), is useful if you are doing system hacking
 that can produce objects that are not valid ACL2 objects, such as raw Lisp
 arrays or objects in supporting packages not visible in the ACL2
 read-eval-print loop.  If you supply @(':evisc-tuple :print'), then the
 printing described above will be done with raw Lisp printing rather than ACL2
 printing: specifically, with @('(format *trace-output* \"s%\" x)'), where
 @('x') is the value to be printed.</p>

 <p>A second special value for @(':evisc-tuple'), @(':no-print'), avoids
 printing the values of the @(':entry') and @(':exit') forms (or their
 defaults, if not specified).  This option is of use for side effects; for an
 example see community book @('books/misc/wet.lisp').</p>

 <p>Note that if @(':evisc-tuple X') is supplied, then the form @('X') will be
 evaluated before the function body is entered.  You can thus pull some tricks
 to print extra information before the @(':entry') form is evaluated, for
 example as follows for a factorial function, @('fact').</p>

 @({
  ACL2 !>(trace$ (fact :evisc-tuple
                       (prog2$ (cw \"~|**** HERE IS CW ****~|\")
                               nil)))
   ((FACT :EVISC-TUPLE (PROG2$ (CW \"~|**** HERE IS CW ****~|\")
                               NIL)))
  ACL2 !>(fact 3)
  **** HERE IS CW ****
  1> (ACL2_*1*_ACL2::FACT 3)
  **** HERE IS CW ****
    2> (ACL2_*1*_ACL2::FACT 2)
  **** HERE IS CW ****
      3> (ACL2_*1*_ACL2::FACT 1)
  **** HERE IS CW ****
        4> (ACL2_*1*_ACL2::FACT 0)
        <4 (ACL2_*1*_ACL2::FACT 1)
      <3 (ACL2_*1*_ACL2::FACT 1)
    <2 (ACL2_*1*_ACL2::FACT 2)
  <1 (ACL2_*1*_ACL2::FACT 6)
  6
  ACL2 !>
 })

 <p>@(':FORMALS')</p>

 <p>Normally ACL2 can figure out the formals for a given function.  This is
 always the case for functions defined in the ACL2 command loop and when option
 @(':def') is supplied.  If neither of these cases applies then you can still
 trace a function (even without using the @(':native') option) by supplying
 option @(':notinline :fncall'), but you will still need to supply the list of
 formal parameters.  The value of the @(':formals') option should be the list
 of formals in this case.</p>

 <p>@(':HIDE')</p>

 <p>The default value for this advanced option is @('t'), which causes @(see
 stobj)s and the logical @(see world) to be printed as single symbols, along
 with certain large structures of interest to developers (rewrite constants,
 enabled structures, and event and command index structures).  If however the
 value @('nil') is supplied, then this default behavior is defeated.  In that
 case, you can still arrange to print the logical world as a symbol and to
 print @(see stobj)s without breaking the trace printing: see @(see
 set-trace-evisc-tuple) for how to do this globally, or similarly use the
 @(':evisc-tuple') option to @('trace$') to do this with a single trace spec.
 Note however that with value @('nil') specified for @(':hide'), such use of an
 evisc-tuple will not deal properly with local stobjs (see @(see
 with-local-stobj)) or stobjs bound by @(tsee stobj-let), or with the
 aforementioned large structures other than the logical @(see world).</p>

 <p>@(':NATIVE')</p>

 <p>If @(':native') is supplied with a non-@('nil') value, then the trace spec
 is passed to the native Lisp trace (after removing the @(':native') option).
 A trust tag (see @(see defttag)) is required in order to use this option,
 because no syntactic check is made on the @(':cond'), @(':entry'), or
 @(':exit') forms &mdash; arbitrary raw Lisp may occur in them!</p>

 <p>Note that by ``native Lisp trace'' we mean the currently installed
 @('trace').  As discussed briefly elsewhere (see @(see trace)), ACL2 has
 modified that trace to be more useful if the underlying host Lisp is GCL,
 Allegro CL, or CCL (OpenMCL).  If you need the original trace utility supplied
 for those Lisps, quit the ACL2 loop with @(':q') and call @('old-trace') and
 @('old-untrace') in raw Lisp where you would otherwise call @('trace') and
 @('untrace').  Note that the original trace utility supplied with a given Lisp
 will not hide the ACL2 logical @(see world) or give special treatment to @(see
 stobj)s.</p>

 <p>It is important to understand that if @(':native t') is specified, then all
 other options are interpreted by the native Lisp trace.  For example, that
 trace probably has no understanding of the use of @(':fmt') described above
 for @(':entry') or @(':exit').  Indeed, the native trace may not even accept
 any of @(':cond'), @(':entry') or @(':exit'), let alone any of the advanced
 options!  Moreover, if @(':native t') is specified, then even a
 @(':multiplicity') option does not provide the meaning of the variable
 @('values') that one might desire.  In GCL for example, in the case of an
 @(tsee mv) return of a function defined only in raw Lisp (not in ACL2), this
 variable will be bound to a list containing only the first result.</p>

 <p>@(':NOTINLINE')</p>

 <p>By default, a new definition installed by @('trace$') will include a
 @('notinline') declaration so that recursive calls will always be traced.  To
 avoid this declaration, supply value @('nil').</p>

 <p>A special value for @(':notinline'), @(':fncall'), will cause the traced
 function to call its original definition.  Without this special value, the new
 installed definition for the traced function will include the body of the
 original definition.  This @(':fncall') behavior is the default only in the
 following cases:</p>

 <ul>

 <li>for functions whose definitions are built into ACL2;</li>

 <li>for functions that have been added (using a trust tag, an advanced
 feature, so most users can probably ignore this case) to either of the @(tsee
 state) global variables @('program-fns-with-raw-code') or
 @('logic-fns-with-raw-code');</li>

 <li>for @(tsee memoize)d functions.</li>

 </ul>

 <p>The legal values for @(':notinline') are @('t') (the default for other than
 the cases displayed above), @('nil'), and @(':fncall').</p>

 <p><b>Remarks</b>.</p>

 <p>(1) If some of the given trace specs have errors, then @('trace$') will
 generally print error messages for those but will still process those that do
 not have errors.  The value returned will indicate the trace specs that were
 processed successfully.</p>

 <p>(2) If you certify or include a book that redundantly defines a function
 that is currently traced, then tracing behavior may disappear if a compiled
 definition is installed for the submitted function or its
 executable-counterpart (see @(see evaluation) for relevant background).</p>

 <p>(3) Some predefined functions are called during tracing.  In order to avoid
 infinite loops, such calls of traced predefined functions will be made using
 the original predefined functions, not using their code installed by
 @('trace$').</p>

 <p>(4) For a @(see wormhole) such as the @(see break-rewrite) loop, all calls
 of @('trace$') and $(tsee untrace$) inside that wormhole are undone upon exit
 from the wormhole.  In particular, if you trace or untrace a function during a
 @(tsee brr) break, then effects of that trace or untrace will disappear when
 you proceed using a keyword such as @(':eval') or @(':go').</p>")

(defxdoc trans
  :parents (macros)
  :short "Print the macroexpansion of a form"
  :long "@({
  Examples:
  :trans (list a b c)
  :trans (caddr x)
  :trans (cond (p q) (r))
 })

 <p>This function takes one argument, an alleged term, and translates it,
 expanding the macros in it completely.  Either an error is caused or the
 formal meaning of the term is printed.  We also print the ``output signature''
 which indicates how many results are returned and which are single-threaded
 objects.  For example, a term that returns one ordinary object (e.g., an
 object other than @(tsee STATE) or a user-defined single-threaded object (see
 @(see defstobj))) has the output signature</p>

 @({
  => *
 })

 <p>A term that returns the single-threaded object @('STATE') has the output
 signature</p>

 @({
  => STATE
 })

 <p>and a term that returns four results might have the output signature</p>

 @({
  => (MV $MEM * * STATE)
 })

 <p>This signature indicates that the first result is the (user defined)
 single-threaded object @('$MEM'), that the next two results are ordinary, and
 that the last result is @('STATE').</p>

 <p>See @(see trans!) for a corresponding command that does not enforce
 restrictions of single-threaded objects.</p>

 <p>It is sometimes more convenient to use @(tsee trans1) which is like trans
 but which only does top-level macroexpansion.</p>

 <p>For more, see @(see term).</p>")

(defxdoc trans!
  :parents (macros)
  :short "Print the macroexpansion of a form without single-threadedness concerns"
  :long "@({
  Examples:
  :trans! (list a b c)
  :trans! (append x state)
 })

 <p>@(':Trans!') is identical to @(':')@(tsee trans), except that unlike
 @(':trans'), @(':trans!') ignores single-threadedness restrictions.  Thus, the
 second form above is legal for @(':trans!').  Also see @(see trans) and see
 @(see trans1).</p>")

(defxdoc trans-eval
  :parents (system-utilities)
  :short "Evaluate a form"
  :long "<p>This relatively advanced system utility translates and evaluates a
 form.  The following examples illustrate that an @(see error-triple) is
 returned whose value component is @('(stobjs-out . values)').</p>

 @({
 ACL2 !>(trans-eval '(+ 3 4) 'my-ctx state nil)
  ((NIL) . 7)
 ACL2 !>(trans-eval '(mv (+ 3 4) (car '(5))) 'my-ctx state nil)
  ((NIL NIL) 7 5)
 ACL2 !>
 })

 @({
 General Form:

 (trans-eval form  ; an untranslated form
             ctx   ; a context
             state
             aokp) ; allow attachments
 })

 <p>The result is an @(see error-triple), @('(mv erp val state)').  The value
 of @('erp') is non-@('nil') if there is an error when translating @('form').
 Otherwise @('erp') is typically @('nil'), in which case @('val') is a
 @('cons') pair whose @('car') is the @(tsee stobjs-out) &mdash; a list whose
 length is the number of values returned, with @('nil') in each position except
 when occupied by a returned @(see stobj) for that position &mdash; and whose
 @('cdr') is the returned value or list of values in the multiple-values
 case.</p>

 <p>Also see @('simple-translate-and-eval-cmp') in the ACL2 sources, and see
 @(see trans-eval-error-triple) (and, which is perhaps less useful, @(see
 trans-eval-state)).</p>

 <p>If you use @('trans-eval') then you may see a warning, for example as
 follows.</p>

 @({
 ACL2 !>(foo st state)

 ACL2 Warning [User-stobjs-modified] in FOO:  A call of the ACL2 evaluator
 on the term (UPDATE-FLD '4 ST) has modified the user stobj ST.  See
 :DOC user-stobjs-modified-warning.

 (4 <state> <st>)
 ACL2 !>
 })

 <p>To avoid such warnings, see @(see user-stobjs-modified-warnings).</p>")

(defxdoc trans1
  :parents (macros)
  :short "Print the one-step macroexpansion of a form"
  :long "@({
  Examples:
  :trans1 (list a b c)
  :trans1 (caddr x)
  :trans1 (cond (p q) (r))
 })

 <p>This function takes one argument, an alleged term, and expands the
 top-level macro in it for one step only.  Either an error is caused, which
 happens when the form is not a call of a macro, or the result is printed.
 Also see @(see trans), which translates the given form completely.</p>")

(defxdoc true-list-listp
  :parents (lists true-listp acl2-built-ins)
  :short "Recognizer for true (proper) lists of true lists"
  :long "<p>@('True-list-listp') is the function that checks whether its
 argument is a list that ends in, or equals, @('nil'), and furthermore, all of
 its elements have that property.  Also see @(see true-listp).</p>

 @(def true-list-listp)")

(defxdoc true-listp
  :parents (lists acl2-built-ins)
  :short "Recognizer for proper (null-terminated) lists"
  :long "<p>@('True-listp') is the function that checks whether its argument is
 a list that ends in, or equals, @('nil').</p>

 For a discussion of whether requiring lists to be @('nil')-terminated is right
 for you, see @(see std::strict-list-recognizers).

 @(def true-listp)")

(defxdoc truncate
  :parents (numbers acl2-built-ins)
  :short "Division returning an integer by truncating toward 0"
  :long "@({
  Example Forms:
  ACL2 !>(truncate 14 3)
  4
  ACL2 !>(truncate -14 3)
  -4
  ACL2 !>(truncate 14 -3)
  -4
  ACL2 !>(truncate -14 -3)
  4
  ACL2 !>(truncate -15 -3)
  5
  ACL2 !>(truncate 10/4 3/4)
  3
 })

 <p>@('(Truncate i j)') is the result of taking the quotient of @('i') and
 @('j') and dropping the fraction.  For example, the quotient of @('-14') by
 @('3') is @('-4 2/3'), so dropping the fraction @('2/3'), we obtain a result
 for @('(truncate -14 3)') of @('-4').</p>

 <p>The @(see guard) for @('(truncate i j)') requires that @('i') and @('j')
 are rational (@(see real), in ACL2(r)) numbers and @('j') is non-zero.</p>

 <p>@('Truncate') is a Common Lisp function.  However, note that unlike Common
 Lisp, the ACL2 @('truncate') function returns only a single value, Also see
 @(see nonnegative-integer-quotient), which is appropriate for integers and may
 simplify reasoning, unless a suitable arithmetic library is loaded, but be
 less efficient for evaluation on concrete objects.</p>

 @(def truncate)")

(defxdoc ttags-seen
  :parents (miscellaneous)
  :short "List some declared trust tags (ttags)"
  :long "@({
  General Forms:
  :ttags-seen
  (ttags-seen)
 })

 <p>Suppose the output is as follows.</p>

 @({
  (T NIL)
  (FOO \"/home/bob/bar.lisp\"
       \"/home/cindy/bar.lisp\")
  Warning: This output is minimally trustworthy (see :DOC TTAGS-SEEN).
 })

 <p>This output indicates that the current logical @(see world) has seen the
 declaration of trust tag @('T') at the top-level (see @(see defttag)) and the
 declaration of trust tag @('FOO') in the two books included from the listed
 locations.  The warning emphasizes that this command cannot be used to
 validate the ``purity'' of an ACL2 session, because using a ttag renders
 enough power to hide from this or any other command the fact that the ttag was
 ever declared.</p>

 <p>As discussed elsewhere (see @(see defttag)), the only reliable way to
 validate the ``purity'' of a session is to watch for ``@('TTAG NOTE')''
 output.</p>

 <p>Another shortcoming of this command is that it only checks the current
 logical @(see world) for ttag declarations.  For example, one could execute a
 @(tsee defttag) event; then use @(tsee progn!) and @(tsee set-raw-mode) to
 replace system functions with corrupt definitions or to introduce inconsistent
 axioms in the @(tsee ground-zero) @(see world); and finally, execute
 @(':')@(tsee ubt!)@(' 1') to remove all evidence of the ttag in the @(see
 world) while leaving in place the corrupt definitions or axioms.  The base
 world is now tainted, meaning we could prove @('nil') or certify a book that
 proves @('nil'), but the resulting session or book would contain no trace of
 the ttag that tainted it!</p>

 <p>Despite shortcomings, this command might be useful to system hackers.  It
 also serves to illustrate the inherent flaw in asking a session whether or how
 it is ``tainted'', justifying the ``@('TTAG NOTE')'' approach (see @(see
 defttag)).</p>")

(defxdoc tthm
  :parents (history measure)
  :short "The @(see measure) (termination) theorem for a given function symbol"
  :long "@({
 Example Forms:
 :tthm FN
 (tthm 'FN) ; equivalent to the above
 })

 <p>where @('FN') is a function symbol.  This shows the @(see
 measure) (termination) theorem for @('FN').  More precisely, evaluation of a
 call of this macro &mdash; pronounced ``tee-thumb'' &mdash; either results in
 an error or returns an @(see error-triple) whose value component is the
 user-level (untranslated) version of that termination theorem.  Also see @(see
 lemma-instance) for discussion of a related @(':termination-theorem') prover
 hint.</p>

 <p>Technical note: a corresponding evaluation that provides a (translated)
 @(see termp) is: @('(termination-theorem 'FN (w state))').</p>")

(defxdoc ttree
  :parents (system-development)
  :short "Tag-trees"
  :long "<p>Many low-level ACL2 functions take and return ``tag trees'' or
 ``ttrees'' (pronounced ``tee-trees'') which contain various useful bits of
 information such as the lemmas used, the linearize assumptions made, etc.</p>

 <p>Abstractly a tag-tree represents a list of sets, each member set having a
 name given by one of the ``tags'' (which are symbols) of the ttree.  The
 elements of the set named @('tag') are all of the objects tagged @('tag') in
 the tree.  You are invited to browse the source code.  Definitions of
 primitives are labeled with the comment ``; Note: Tag-tree primitive''.</p>

 <p>The rewriter, for example, takes a term and a ttree (among other things),
 and returns a new term, term', and new ttree, ttree'.  Term' is equivalent to
 term (under the current assumptions) and the ttree' is an extension of ttree.
 If we focus just on the set associated with the tag @('LEMMA') in the ttrees,
 then the set for ttree' is the extension of that for ttree obtained by
 unioning into it all the @(see rune)s used by the rewrite.  The set associated
 with @('LEMMA') can be obtained by @('(tagged-objects 'LEMMA ttree)').</p>")

(defxdoc tutorial1-towers-of-hanoi
  :parents (annotated-acl2-scripts)
  :short "The Towers of Hanoi Example"
  :long "<p>This example was written almost entirely by Bill Young of
 Computational Logic, Inc.</p>

 <p>We will formalize and prove a small theorem about the famous ``Towers of
 Hanoi'' problem.  This problem is illustrated by the following picture.</p>

 @({
            |        |        |
            |        |        |
           ---       |        |
          -----      |        |
         -------     |        |

            A        B        C
 })

 <p>We have three pegs &mdash; @('a'), @('b'), and @('c') &mdash; and @('n')
 disks of different sizes.  The disks are all initially on peg @('a').  The
 goal is to move all disks to peg @('c') while observing the following two
 rules.</p>

 <p>1. Only one disk may be moved at a time, and it must start and finish the
 move as the topmost disk on some peg;</p>

 <p>2. A disk can never be placed on top of a smaller disk.</p>

 <p>Let's consider some simple instances of this problem.  If @('n') = 1, i.e.,
 only one disk is to be moved, simply move it from @('a') to @('c').  If @('n')
 = 2, i.e., two disks are to be moved, the following sequence of moves
 suffices: move from @('a') to @('b'), move from @('a') to @('c'), move from
 @('b') to @('c').</p>

 <p>In this doc topic we will show an ACL2 function that generates a suitable
 list of moves for a tower of @('n') disks.  Then we will use ACL2 to prove
 that the number of moves is @('(- (expt 2 n) 1)').  For an ACL2 script that
 proves the correctness of (a version of) this function, see the community book
 @('\"misc/hanoi.lisp\"') in the @('books') directory of your ACL2 sources.</p>

 <p>In general, this problem has a straightforward recursive solution.  Suppose
 that we desire to move @('n') disks from @('a') to @('c'), using @('b') as the
 intermediate peg.  For the basis, we saw above that we can always move a
 single disk from @('a') to @('c').  Now if we have @('n') disks and assume
 that we can solve the problem for @('n-1') disks, we can move @('n') disks as
 follows.  First, move @('n-1') disks from @('a') to @('b') using @('c') as the
 intermediate peg; move the single disk from @('a') to @('c'); then move
 @('n-1') disks from @('b') to @('c') using @('a') as the intermediate peg.</p>

 <p>In ACL2, we can write a function that will return the sequence of moves.
 One such function is as follows.  Notice that we have two base cases.  If
 @('(zp n)') then @('n') is not a positive integer; we treat that case as if
 @('n') were 0 and return an empty list of moves.  If @('n') is 1, then we
 return a list containing the single appropriate move.  Otherwise, we return
 the list containing exactly the moves dictated by our recursive analysis
 above.</p>

 @({
    (defun move (a b)
      (list 'move a 'to b))

    (defun hanoi (a b c n)
      (if (zp n)
          nil
        (if (equal n 1)
            (list (move a c))
          (append (hanoi a c b (1- n))
                  (cons (move a c)
                        (hanoi b a c (1- n)))))))
 })

 <p>Notice that we give @('hanoi') four arguments: the three pegs, and the
 number of disks to move.  It is necessary to supply the pegs because, in
 recursive calls, the roles of the pegs differ.  In any execution of the
 algorithm, a given peg will sometimes be the source of a move, sometimes the
 destination, and sometimes the intermediate peg.</p>

 <p>After submitting these functions to ACL2, we can execute the @('hanoi')
 function on various specific arguments.  For example:</p>

 @({
    ACL2 !>(hanoi 'a 'b 'c 1)
    ((MOVE A TO C))

    ACL2 !>(hanoi 'a 'b 'c 2)
    ((MOVE A TO B)
     (MOVE A TO C)
     (MOVE B TO C))

    ACL2 !>(hanoi 'a 'b 'c 3)
    ((MOVE A TO C)
     (MOVE A TO B)
     (MOVE C TO B)
     (MOVE A TO C)
     (MOVE B TO A)
     (MOVE B TO C)
     (MOVE A TO C))
 })

 <p>From the algorithm it is clear that if it takes @('m') moves to transfer
 @('n') disks, it will take @('(m + 1 + m) = 2m + 1') moves for @('n+1') disks.
 From some simple calculations, we see that we need the following number of
 moves in specific cases:</p>

 @({
     Disks   0   1   2   3   4   5   6   7  ...
     Moves   0   1   3   7  15  31  63  127 ...
 })

 <p>The pattern is fairly clear.  To move @('n') disks requires @('(2^n - 1)')
 moves.  Let's attempt to use ACL2 to prove that fact.</p>

 <p>First of all, how do we state our conjecture?  Recall that @('hanoi')
 returns a list of moves.  The length of the list (given by the function
 @('len')) is the number of moves required.  Thus, we can state the following
 conjecture.</p>

 @({
    (defthm hanoi-moves-required-first-try
      (equal (len (hanoi a b c n))
             (1- (expt 2 n))))
 })

 <p>When we submit this to ACL2, the proof attempt fails.  Along the way we
 notice subgoals such as:</p>

 @({
    Subgoal *1/1'
    (IMPLIES (NOT (< 0 N))
             (EQUAL 0 (+ -1 (EXPT 2 N)))).
 })

 <p>This tells us that the prover is considering cases that are uninteresting
 to us, namely, cases in which @('n') might be negative.  The only cases that
 are really of interest are those in which @('n') is a non-negative natural
 number.  Therefore, we revise our theorem as follows:</p>

 @({
    (defthm hanoi-moves-required
      (implies (and (integerp n)
                    (<= 0 n))    ;; n is at least 0
               (equal (len (hanoi a b c n))
                      (1- (expt 2 n)))))
 })

 <p>and submit it to ACL2 again.</p>

 <p>Again the proof fails.  Examining the proof script we encounter the
 following text.  (How did we decide to focus on this goal?  Some information
 is provided in ACLH, and the ACL2 documentation on @(see tips) may be helpful.
 But the simplest answer is: this was the first goal suggested by the ``@(see
 proof-tree)'' tool below the start of the proof by induction.  See @(see
 proof-tree).)</p>

 @({
    Subgoal *1/5''
    (IMPLIES (AND (INTEGERP N)
                  (< 0 N)
                  (NOT (EQUAL N 1))
                  (EQUAL (LEN (HANOI A C B (+ -1 N)))
                         (+ -1 (EXPT 2 (+ -1 N))))
                  (EQUAL (LEN (HANOI B A C (+ -1 N)))
                         (+ -1 (EXPT 2 (+ -1 N)))))
             (EQUAL (LEN (APPEND (HANOI A C B (+ -1 N))
                                 (CONS (LIST 'MOVE A 'TO C)
                                       (HANOI B A C (+ -1 N)))))
                    (+ -1 (* 2 (EXPT 2 (+ -1 N))))))
 })

 <p>It is difficult to make much sense of such a complicated goal.  However, we
 do notice something interesting.  In the conclusion is a @(see term) of the
 following shape.</p>

 @({
     (LEN (APPEND ... ...))
 })

 <p>We conjecture that the length of the @(tsee append) of two lists should be
 the sum of the lengths of the lists.  If the prover knew that, it could
 possibly have simplified this @(see term) earlier and made more progress in
 the proof.  Therefore, we need a @(see rewrite) rule that will suggest such a
 simplification to the prover.  The appropriate rule is:</p>

 @({
    (defthm len-append
      (equal (len (append x y))
             (+ (len x) (len y))))
 })

 <p>We submit this to the prover, which proves it by a straightforward
 induction.  The prover stores this lemma as a @(see rewrite) rule and will
 subsequently (unless we @(see disable) the rule) replace @(see term)s matching
 the left hand side of the rule with the appropriate instance of the @(see
 term) on the right hand side.</p>

 <p>We now resubmit our lemma @('hanoi-moves-required') to ACL2.  On this
 attempt, the proof succeeds and we are done.</p>

 <p>One bit of cleaning up is useful.  We needed the hypotheses that:</p>

 @({
    (and (integerp n) (<= 0 n)).
 })

 <p>This is an awkward way of saying that @('n') is a natural number; natural
 is not a primitive data type in ACL2.  We could define a function
 @('naturalp'), but it is somewhat more convenient to define a macro as
 follows:</p>

 @({
    (defmacro naturalp (x)
      (list 'and (list 'integerp x)
                    (list '<= 0 x)))
 })

 <p>Subsequently, we can use @('(naturalp n)') wherever we need to note that a
 quantity is a natural number.  See @(see defmacro) for more information about
 ACL2 macros.  With this macro, we can reformulate our theorem as follows:</p>

 @({
    (defthm hanoi-moves-required
      (implies (naturalp n)
               (equal (len (hanoi a b c n))
                      (1- (expt 2 n))))).
 })

 <p>Another interesting (but much harder) theorem asserts that the list of
 moves generated by our @('hanoi') function actually accomplishes the desired
 goal while following the rules.  When you can state and prove that theorem,
 you'll be a very competent ACL2 user.</p>

 <p>By the way, the name ``Towers of Hanoi'' derives from a legend that a group
 of Vietnamese monks works day and night to move a stack of 64 gold disks from
 one diamond peg to another, following the rules set out above.  We're told
 that the world will end when they complete this task.  From the theorem above,
 we know that this requires 18,446,744,073,709,551,615 moves:</p>

 @({
    ACL2 !>(1- (expt 2 64))
    18446744073709551615
    ACL2 !>
 })

 <p>We're guessing they won't finish any time soon.</p>")

(defxdoc tutorial2-eights-problem
  :parents (annotated-acl2-scripts)
  :short "The Eights Problem Example"
  :long "<p>This example was written almost entirely by Bill Young of
 Computational Logic, Inc.</p>

 <p>This simple example was brought to our attention as one that Paul Jackson
 has solved using the NuPrl system.  The challenge is to prove the theorem:</p>

 @({
    for all n > 7, there exist naturals i and j such that: n = 3i + 5j.
 })

 <p>In ACL2, we could phrase this theorem using quantification.  However we
 will start with a constructive approach, i.e., we will show that values of
 @('i') and @('j') exist by writing a function that will construct such values
 for given @('n').  Suppose we had a function @('(split n)') that returns an
 appropriate pair @('(i . j)').  Our theorem would be as follows:</p>

 @({
    (defthm split-splits
      (let ((i (car (split n)))
            (j (cdr (split n))))
        (implies (and (integerp n)
                      (< 7 n))
                 (and (integerp i)
                      (<= 0 i)
                      (integerp j)
                      (<= 0 j)
                      (equal (+ (* 3 i) (* 5 j))
                             n)))))
 })

 <p>That is, assuming that @('n') is a natural number greater than 7, @('(split
 n)') returns values @('i') and @('j') that are in the appropriate relation to
 @('n').</p>

 <p>Let's look at a few cases:</p>

 @({
    8 = 3x1 + 5x1;    11 = 3x2 + 5x1;     14 = 3x3 + 5x1;   ...
    9 = 3x3 + 5x0;    12 = 3x4 + 5x0;     15 = 3x5 + 5x0;   ...
   10 = 3x0 + 5x2;    13 = 3x1 + 5x2;     16 = 3x2 + 5x2;   ...
 })

 <p>Maybe you will have observed a pattern here; any natural number larger than
 10 can be obtained by adding some multiple of 3 to 8, 9, or 10.  This gives us
 the clue to constructing a proof.  It is clear that we can write split as
 follows:</p>

 @({
    (defun bump-i (x)
      ;; Bump the i component of the pair
      ;; (i . j) by 1.
      (cons (1+ (car x)) (cdr x)))

    (defun split (n)
      ;; Find a pair (i . j) such that
      ;; n = 3i + 5j.
      (if (or (zp n) (< n 8))
          nil ;; any value is really reasonable here
        (if (equal n 8)
            (cons 1 1)
          (if (equal n 9)
              (cons 3 0)
            (if (equal n 10)
                (cons 0 2)
              (bump-i (split (- n 3))))))))
 })

 <p>Notice that we explicitly compute the values of @('i') and @('j') for the
 cases of 8, 9, and 10, and for the degenerate case when @('n') is not a
 natural or is less than 8.  For all naturals greater than @('n'), we decrement
 @('n') by 3 and bump the number of 3's (the value of i) by 1.  We know that
 the recursion must terminate because any integer value greater than 10 can
 eventually be reduced to 8, 9, or 10 by successively subtracting 3.</p>

 <p>Let's try it on some examples:</p>

 @({
    ACL2 !>(split 28)
    (6 . 2)

    ACL2 !>(split 45)
    (15 . 0)

    ACL2 !>(split 335)
    (110 . 1)
 })

 <p>Finally, we submit our theorem @('split-splits'), and the proof succeeds.
 In this case, the prover is ``smart'' enough to induct according to the
 pattern indicated by the function split.</p>

 <p>For completeness, we'll note that we can state and prove a quantified
 version of this theorem.  We introduce the notion @('split-able') to mean that
 appropriate @('i') and @('j') exist for @('n').</p>

 @({
    (defun-sk split-able (n)
      (exists (i j)
              (equal n (+ (* 3 i) (* 5 j)))))
 })

 <p>Then our theorem is given below.  Notice that we prove it by observing that
 our previous function @('split') delivers just such an @('i') and @('j') (as
 we proved above).</p>

 @({
    (defthm split-splits2
      (implies (and (integerp n)
                    (< 7 n))
               (split-able n))
      :hints ((\"Goal\" :use (:instance split-able-suff
                                      (i (car (split n)))
                                      (j (cdr (split n)))))))
 })

 <p>Unfortunately, understanding the mechanics of the proof requires knowing
 something about the way @(tsee defun-sk) works.  See @(see defun-sk) or see
 @(see Tutorial4-Defun-Sk-Example) for more on that subject.</p>")

(defxdoc tutorial3-phonebook-example
  :parents (annotated-acl2-scripts)
  :short "A Phonebook Specification"
  :long "<p>The other tutorial examples are rather small and entirely self
 contained.  The present example is rather more elaborate, and makes use of a
 feature that really adds great power and versatility to ACL2, namely: the use
 of previously defined collections of lemmas, in the form of ``@(see
 books).''</p>

 <p>This example was written almost entirely by Bill Young of Computational
 Logic, Inc.</p>

 <p>This example is based on one developed by Ricky Butler and Sally Johnson of
 NASA Langley for the PVS system, and subsequently revised by Judy Crow, <i>et
 al</i>, at SRI.  It is a simple phone book specification.  We will not bother
 to follow their versions closely, but will instead present a style of
 specification natural for ACL2.</p>

 <p>The idea is to model an electronic phone book with the following
 properties.</p>

 <blockquote>

 <p>Our phone book will store the phone numbers of a city.</p>

 <p>It must be possible to retrieve a phone number, given a name.</p>

 <p>It must be possible to add and delete entries.</p>

 </blockquote>

 <p>Of course, there are numerous ways to construct such a model.  A natural
 approach within the Lisp/ACL2 context is to use ``association lists'' or
 ``alists.''  Briefly, an alist is a list of pairs @('(key .  value)')
 associating a value with a key.  A phone book could be an alist of pairs
 @('(name . pnum)').  To find the phone number associated with a given name, we
 merely search the alist until we find the appropriate pair.  For a large city,
 such a linear list would not be efficient, but at this point we are interested
 only in <b>modeling</b> the problem, not in deriving an efficient
 implementation.  We could address that question later by proving our alist
 model equivalent, in some desired sense, to a more efficient data
 structure.</p>

 <p>We could build a theory of alists from scratch, or we can use a previously
 constructed theory (book) of alist definitions and facts.  By using an
 existing book, we build upon the work of others, start our specification and
 proof effort from a much richer foundation, and hopefully devote more of our
 time to the problem at hand.  Unfortunately, it is not completely simple for
 the new user to know what @(see books) are available and what they contain.
 We hope later to improve the documentation of the growing collection of
 @(see community-books) that are typically downloaded with ACL2; for now, the
 reader is encouraged to look in the README.html file in the books' top-level
 directory.  For present purposes, the beginning user can simply take our word
 that a book exists containing useful alist definitions and facts.  These
 definitions and lemmas can be introduced into the current theory using the
 @(see command):</p>

 @({
    (include-book \"data-structures/alist-defthms\" :dir :system)
 })

 <p>This book has been ``certified,'' which means that the definitions and
 lemmas have been mechanically checked and stored in a safe manner.  (See @(see
 books) and see @(see include-book) for details.)</p>

 <p>Including this book makes available a collection of functions including the
 following:</p>

 @({
  (ALISTP A)    ; is A an alist (actually a primitive ACL2 function)

  (BIND X V A)  ; associate the key X with value V in alist A

  (BINDING X A) ; return the value associated with key X in alist A

  (BOUND? X A)  ; is key X associated with any value in alist A

  (DOMAIN A)    ; return the list of keys bound in alist A

  (RANGE A)     ; return the list of values bound to keys in alist A

  (REMBIND X A) ; remove the binding of key X in alist A
 })

 <p>Along with these function definitions, the book also provides a number of
 proved lemmas that aid in simplifying expressions involving these functions.
 (See @(see rule-classes) for the way in which lemmas are used in
 simplification and rewriting.)  For example,</p>

 @({
    (defthm bound?-bind
      (equal (bound? x (bind y v a))
             (or (equal x y)
                 (bound? x a))))
 })

 <p>asserts that @('x') will be bound in @('(bind y v a)') if and only if:
 either @('x = y') or @('x') was already bound in @('a').  Also,</p>

 @({
    (defthm binding-bind
      (equal (binding x (bind y v a))
             (if (equal x y)
                 v
               (binding x a))))
 })

 <p>asserts that the resulting binding will be @('v'), if @('x = y'), or the
 binding that @('x') had in @('a') already, if not.</p>

 <p>Thus, the inclusion of this book essentially extends our specification and
 reasoning capabilities by the addition of new operations and facts about these
 operations that allow us to build further specifications on a richer and
 possibly more intuitive foundation.</p>

 <p>However, it must be admitted that the use of a book such as this has two
 potential limitations:</p>

 <blockquote>

 <p>the definitions available in a book may not be ideal for your particular
 problem;</p>

 <p>it is (extremely) likely that some useful facts (especially, @(see rewrite)
 rules) are not available in the book and will have to be proved.</p>

 </blockquote>

 <p>For example, what is the value of @('binding') when given a key that is not
 bound in the alist?  We can find out by examining the function definition.
 Look at the definition of the @('binding') function (or any other defined
 function), using the @(':')@(tsee pe) command:</p>

 @({
    ACL2 !>:pe binding
       d     33  (INCLUDE-BOOK
                      \"/slocal/src/acl2/v1-9/books/public/alist-defthms\")

    >V d          (DEFUN BINDING (X A)
                         \"The value bound to X in alist A.\"
                         (DECLARE (XARGS :GUARD (ALISTP A)))
                         (CDR (ASSOC-EQUAL X A)))
 })

 <p>This tells us that @('binding') was introduced by the given @(tsee
 include-book) form, is currently @(see disable)d in the current theory, and
 has the definition given by the displayed @(tsee defun) form.  We see that
 @('binding') is actually defined in terms of the primitive @(tsee assoc-equal)
 function.  If we look at the definition of @(tsee assoc-equal):</p>

 @({
    ACL2 !>:pe assoc-equal
     V     -489  (DEFUN ASSOC-EQUAL (X ALIST)
                        (DECLARE (XARGS :GUARD (ALISTP ALIST)))
                        (COND ((ENDP ALIST) NIL)
                              ((EQUAL X (CAR (CAR ALIST)))
                               (CAR ALIST))
                              (T (ASSOC-EQUAL X (CDR ALIST)))))
 })

 <p>we can see that @(tsee assoc-equal) returns @('nil') upon reaching the end
 of an unsuccessful search down the alist.  So @('binding') returns @('(cdr
 nil)') in that case, which is @('nil').  Notice that we could also have
 investigated this question by trying some simple examples.</p>

 @({
    ACL2 !>(binding 'a nil)
    NIL

    ACL2 !>(binding 'a (list (cons 'b 2)))
    NIL
 })

 <p>These definitions aren't ideal for all purposes. For one thing, there's
 nothing that keeps us from having @('nil') as a value bound to some key in the
 alist.  Thus, if @('binding') returns @('nil') we don't always know if that is
 the value associated with the key in the alist, or if that key is not bound.
 We'll have to keep that ambiguity in mind whenever we use @('binding') in our
 specification.  Suppose instead that we wanted @('binding') to return some
 error string on unbound keys.  Well, then we'd just have to write our own
 version of @('binding').  But then we'd lose much of the value of using a
 previously defined book.  As with any specification technique, certain
 tradeoffs are necessary.</p>

 <p>Why not take a look at the definitions of other alist functions and see how
 they work together to provide the ability to construct and search alists?
 We'll be using them rather heavily in what follows so it will be good if you
 understand basically how they work.  Simply start up ACL2 and execute the form
 shown earlier, but substituting our directory name for the top-level ACL2
 directory with yours.  Alternatively, just</p>

 @({
    (include-book \"data-structures/alist-defthms\" :dir :system)
 })

 <p>Then, you can use @(':')@(see pe) to look at function definitions.  You'll
 soon discover that almost all of the definitions are built on definitions of
 other, more primitive functions, as @('binding') is built on @(tsee
 assoc-equal).  You can look at those as well, of course, or in many cases
 visit their documentation.</p>

 <p>The other problem with using a predefined book is that it will seldom be
 ``sufficiently complete,'' in the sense that the collection of @(see rewrite)
 rules supplied won't be adequate to prove everything we'd like to know about
 the interactions of the various functions.  If it were, there'd be no real
 reason to know that @('binding') is built on top of @(tsee assoc-equal),
 because everything we'd need to know about @('binding') would be nicely
 expressed in the collection of theorems supplied with the book.  However,
 that's very seldom the case.  Developing such a collection of rules is
 currently more art than science and requires considerable experience.  We'll
 encounter examples later of ``missing'' facts about @('binding') and our other
 alist functions.  So, let's get on with the example.</p>

 <p>Notice that alists are mappings of keys to values; but, there is no notion
 of a ``type'' associated with the keys or with the values.  Our phone book
 example, however, does have such a notion of types; we map names to phone
 numbers.  We can introduce these ``types'' by explicitly defining them, e.g.,
 names are strings and phone numbers are integers.  Alternatively, we can
 <b>partially define</b> or axiomatize a recognizer for names without giving a
 full definition.  A way to safely introduce such ``constrained'' function
 symbols in ACL2 is with the @(tsee encapsulate) form.  For example, consider
 the following form.</p>

 @({
    (encapsulate
      ;; Introduce a recognizer for names and give a ``type'' lemma.
      (((namep *) => *))
      ;;
      (local (defun namep (x)
               ;; This declare is needed to tell
               ;; ACL2 that we're aware that the
               ;; argument x is not used in the body
               ;; of the function.
               (declare (ignore x))
               t))
      ;;
      (defthm namep-booleanp
        (booleanp (namep x))))
 })

 <p>This @(tsee encapsulate) form introduces the new function @('namep') of one
 argument and one result and constrains @('(namep x)') to be Boolean, for all
 inputs @('x').  More generally, an encapsulation establishes an environment in
 which functions can be defined and theorems and rules added without
 necessarily introducing those functions, theorems, and rules into the
 environment outside the encapsulation.  To be admissible, all the events in
 the body of an encapsulate must be admissible.  But the effect of an
 encapsulate is to assume only the non-local events.</p>

 <p>The first ``argument'' to @('encapsulate'), @('(((namep *) => *))') above,
 declares the intended @(see signature)s of new function symbols that will be
 ``exported'' from the encapsulation without definition.  The @(tsee local)
 @(tsee defun) of @('name') defines name within the encapsulation always to
 return @('t').  The @('defthm') event establishes that @('namep') is Boolean.
 By making the @('defun') local but the @('defthm') non-@('local') this
 encapsulate constrains the undefined function @('namep') to be Boolean; the
 admissibility of the encapsulation establishes that there exists a Boolean
 function (namely the constant function returning @('t')).</p>

 <p>We can subsequently use @('namep') as we use any other Boolean function,
 with the proviso that we know nothing about it except that it always returns
 either @('t') or @('nil').  We use @('namep') to ``recognize'' legal keys for
 our phonebook alist.</p>

 <p>We wish to do something similar to define what it means to be a legal phone
 number.  We submit the following form to ACL2:</p>

 @({
    (encapsulate
      ;; Introduce a recognizer for phone numbers.
      (((pnump *) => *))
      ;;
      (local (defun pnump (x)
               (not (equal x nil))))
      ;;
      (defthm pnump-booleanp
        (booleanp (pnump x)))
      ;;
      (defthm nil-not-pnump
        (not (pnump nil)))).
 })

 <p>This introduces a Boolean-valued recognizer @('pnump'), with the additional
 proviso that the constant @('nil') is not a @('pnump').  We impose this
 restriction to guarantee that we'll never bind a name to @('nil') in our phone
 book and thereby introduce the kind of ambiguity described above regarding the
 use of @('binding').</p>

 <p>Now a legal phone book is an alist mapping from @('namep')s to @('pnump')s.
 We can define this as follows:</p>

 @({
    (defun name-phonenum-pairp (x)
      ;; Recognizes a pair of (name . pnum).
      (and (consp x)
           (namep (car x))
           (pnump (cdr x))))

    (defun phonebookp (l)
      ;; Recognizes a list of such pairs.
      (if (not (consp l))
          (null l)
        (and (name-phonenum-pairp (car l))
             (phonebookp (cdr l)))))
 })

 <p>Thus, a phone book is really a list of pairs @('(name . pnum)').  Notice
 that we have not assumed that the keys of the phone book are distinct.  We'll
 worry about that question later.  (It is not always desirable to insist that
 the keys of an alist be distinct.  But it may be a useful requirement for our
 specific example.)</p>

 <p>Now we are ready to define some of the functions necessary for our
 phonebook example.  The functions we need are:</p>

 @({
  (IN-BOOK? NM BK)          ; does NM have a phone number in BK

  (FIND-PHONE NM BK)        ; find NM's phone number in phonebook BK

  (ADD-PHONE NM PNUM BK)    ; give NM the phone number PNUM in BK

  (CHANGE-PHONE NM PNUM BK) ; change NM's phone number to PNUM in BK

  (DEL-PHONE NM PNUM)       ; remove NM's phone number from BK
 })

 <p>Given our underlying theory of alists, it is easy to write these functions.
 But we must take care to specify appropriate ``boundary'' behavior.  Thus,
 what behavior do we want when, say, we try to change the phone number of a
 client who is not currently in the book?  As usual, there are numerous
 possibilities; here we'll assume that we return the phone book unchanged if we
 try anything ``illegal.''</p>

 <p>Possible definitions of our phone book functions are as follows.
 (Remember, an @('include-book') form such as the ones shown earlier must be
 executed in order to provide definitions for functions such as
 @('bound?').)</p>

 @({
    (defun in-book? (nm bk)
      (bound? nm bk))

    (defun find-phone (nm bk)
      (binding nm bk))

    (defun add-phone (nm pnum bk)
      ;; If nm already in-book?, make no change.
      (if (in-book? nm bk)
          bk
        (bind nm pnum bk)))

    (defun change-phone (nm pnum bk)
      ;; Make a change only if nm already has a phone number.
      (if (in-book? nm bk)
          (bind nm pnum bk)
        bk))

    (defun del-phone (nm bk)
      ;; Remove the binding from bk, if there is one.
      (rembind nm bk))
 })

 <p>Notice that we don't have to check whether a name is in the book before
 deleting, because @('rembind') is essentially a no-op if @('nm') is not bound
 in @('bk').</p>

 <p>In some sense, this completes our specification.  But we can't have any
 real confidence in its correctness without validating our specification in
 some way.  One way to do so is by proving some properties of our
 specification.  Some candidate properties are:</p>

 <blockquote>

 <p>1. A name will be in the book after we add it.</p>

 <p>2. We will find the most recently added phone number for a client.</p>

 <p>3. If we change a number, we'll find the change.</p>

 <p>4. Changing and then deleting a number is the same as just deleting.</p>

 <p>5. A name will not be in the book after we delete it.</p></blockquote>

 <p>Let's formulate some of these properties.  The first one, for example,
 is:</p>

 @({
    (defthm add-in-book
      (in-book? nm (add-phone nm pnum bk))).
 })

 <p>You may wonder why we didn't need any hypotheses about the ``types'' of the
 arguments.  In fact, @('add-in-book') is really expressing a property that is
 true of alists in general, not just of the particular variety of alists we are
 dealing with.  Of course, we could have added some extraneous hypotheses and
 proved:</p>

 @({
    (defthm add-in-book
      (implies (and (namep nm)
                    (pnump pnum)
                    (phonebookp bk))
               (in-book? nm (add-phone nm pnum bk)))),
 })

 <p>but that would have yielded a weaker and less useful lemma because it would
 apply to fewer situations.  In general, it is best to state lemmas in the most
 general form possible and to eliminate unnecessary hypotheses whenever
 possible.  The reason for that is simple: lemmas are usually stored as rules
 and used in later proofs.  For a lemma to be used, its hypotheses must be
 relieved (proved to hold in that instance); extra hypotheses require extra
 work.  So we avoid them whenever possible.</p>

 <p>There is another, more important observation to make about our lemma.  Even
 in its simpler form (without the extraneous hypotheses), the lemma
 @('add-in-book') may be useless as a @(see rewrite) rule.  Notice that it is
 stated in terms of the non-recursive functions @('in-book?') and
 @('add-phone').  If such functions appear in the left hand side of the
 conclusion of a lemma, the lemma may not ever be used.  Suppose in a later
 proof, the theorem prover encountered a @(see term) of the form:</p>

 @({
    (in-book? nm (add-phone nm pnum bk)).
 })

 <p>Since we've already proved @('add-in-book'), you'd expect that this would
 be immediately reduced to true.  However, the theorem prover will often
 ``expand'' the non-recursive definitions of @('in-book?')  and @('add-phone')
 using their definitions <b>before</b> it attempts rewriting with lemmas.
 After this expansion, lemma @('add-in-book') won't ``match'' the @(see term)
 and so won't be applied.  Look back at the proof script for @('add-in-proof')
 and you'll notice that at the very end the prover warned you of this potential
 difficulty when it printed:</p>

 @({
    Warnings:  Non-rec
    Time:  0.18 seconds (prove: 0.05, print: 0.00, other: 0.13)
    ADD-IN-BOOK
 })

 <p>The ``Warnings'' line notifies you that there are non-recursive function
 calls in the left hand side of the conclusion and that this problem might
 arise.  Of course, it may be that you don't ever plan to use the lemma for
 rewriting or that your intention is to @(see disable) these functions.  @(see
 Disable)d functions are not expanded and the lemma should apply.  However, you
 should always take note of such warnings and consider an appropriate response.
 By the way, we noted above that @('binding') is @(see disable)d.  If it were
 not, none of the lemmas about @('binding') in the book we included would
 likely be of much use for exactly the reason we just gave.</p>

 <p>For our current example, let's assume that we're just investigating the
 properties of our specifications and not concerned about using our lemmas for
 rewriting.  So let's go on.  If we really want to avoid the warnings, we can
 add @(':rule-classes nil') to each @('defthm') event; see @(see
 rule-classes).</p>

 <p>Property 2 is: we always find the most recently added phone number for a
 client.  Try the following formalization:</p>

 @({
    (defthm find-add-first-cut
      (equal (find-phone nm (add-phone nm pnum bk))
             pnum))
 })

 <p>and you'll find that the proof attempt fails.  Examining the proof attempt
 and our function definitions, we see that the lemma is false if @('nm') is
 already in the book.  We can remedy this situation by reformulating our lemma
 in at least two different ways:</p>

 @({
    (defthm find-add1
      (implies (not (in-book? nm bk))
               (equal (find-phone nm (add-phone nm pnum bk))
                      pnum)))

    (defthm find-add2
      (equal (find-phone nm (add-phone nm pnum bk))
             (if (in-book? nm bk)
                 (find-phone nm bk)
                 pnum)))
 })

 <p>For technical reasons, lemmas such as @('find-add2'), i.e., which do not
 have hypotheses, are usually slightly preferable.  This lemma is stored as an
 ``unconditional'' @(see rewrite) rule (i.e., has no hypotheses) and,
 therefore, will apply more often than @('find-add1').  However, for our
 current purposes either version is all right.</p>

 <p>Property 3 says: If we change a number, we'll find the change.  This is
 very similar to the previous example.  The formalization is as follows.</p>

 @({
    (defthm find-change
      (equal (find-phone nm (change-phone nm pnum bk))
             (if (in-book? nm bk)
                 pnum
               (find-phone nm bk))))
 })

 <p>Property 4 says: changing and then deleting a number is the same as just
 deleting.  We can model this as follows.</p>

 @({
    (defthm del-change
      (equal (del-phone nm (change-phone nm pnum bk))
             (del-phone nm bk)))
 })

 <p>Unfortunately, when we try to prove this, we encounter subgoals that seem
 to be true, but for which the prover is stumped.  For example, consider the
 following goal.  (Note: @('endp') holds of lists that are empty.)</p>

 @({
    Subgoal *1/4
    (IMPLIES (AND (NOT (ENDP BK))
                  (NOT (EQUAL NM (CAAR BK)))
                  (NOT (BOUND? NM (CDR BK)))
                  (BOUND? NM BK))
             (EQUAL (REMBIND NM (BIND NM PNUM BK))
                    (REMBIND NM BK))).
 })

 <p>Our intuition about @('rembind') and @('bind') tells us that this goal
 should be true even without the hypotheses.  We attempt to prove the following
 lemma.</p>

 @({
    (defthm rembind-bind
      (equal (rembind nm (bind nm pnum bk))
             (rembind nm bk)))
 })

 <p>The prover proves this by induction, and stores it as a rewrite rule.
 After that, the prover has no difficulty in proving @('del-change').</p>

 <p>The need to prove lemma @('rembind-bind') illustrates a point we made early
 in this example: the collection of @(see rewrite) rules supplied by a
 previously certified book will almost never be everything you'll need.  It
 would be nice if we could operate purely in the realm of names, phone numbers,
 and phone books without ever having to prove any new facts about alists.
 Unfortunately, we needed a fact about the relation between @('rembind') and
 @('bind') that wasn't supplied with the alists theory.  Hopefully, such
 omissions will be rare.</p>

 <p>Finally, let's consider our property 5 above: a name will not be in the
 book after we delete it.  We formalize this as follows:</p>

 @({
    (defthm in-book-del
      (not (in-book? nm (del-phone nm bk))))
 })

 <p>This proves easily.  But notice that it's only true because @('del-phone')
 (actually @('rembind')) removes <b>all</b> occurrences of a name from the
 phone book.  If it only removed, say, the first one it encountered, we'd need
 a hypothesis that said that @('nm') occurs at most once in @('bk').  Ah, maybe
 that's a property you hadn't considered.  Maybe you want to ensure that
 <b>any</b> name occurs at most once in any valid phonebook.</p>

 <p>To complete this example, let's consider adding an <b>invariant</b> to our
 specification.  In particular, suppose we want to assure that no client has
 more than one associated phone number.  One way to ensure this is to require
 that the domain of the alist is a ``set'' (has no duplicates).</p>

 @({
    (defun setp (l)
      (if (atom l)
          (null l)
        (and (not (member-equal (car l) (cdr l)))
             (setp (cdr l)))))

    (defun valid-phonebookp (bk)
      (and (phonebookp bk)
           (setp (domain bk))))
 })

 <p>Now, we want to show under what conditions our operations preserve the
 property of being a @('valid-phonebookp').  The operations @('in-book?')  and
 @('find-phone') don't return a phone book, so we don't really need to worry
 about them.  Since we're really interested in the ``types'' of values
 preserved by our phonebook functions, let's look at the types of those
 operations as well.</p>

 @({
    (defthm in-book-booleanp
      (booleanp (in-book? nm bk)))

    (defthm in-book-namep
      (implies (and (phonebookp bk)
                    (in-book? nm bk))
               (namep nm))
      :hints ((\"Goal\" :in-theory (enable bound?))))

    (defthm find-phone-pnump
      (implies (and (phonebookp bk)
                    (in-book? nm bk))
               (pnump (find-phone nm bk)))
      :hints ((\"Goal\" :in-theory (enable bound? binding))))
 })

 <p>Note the ``@(':')@(tsee hints)'' on the last two lemmas.  Neither of these
 would prove without these @(see hints), because once again there are some
 facts about @('bound?') and @('binding') not available in our current context.
 Now, we could figure out what those facts are and try to prove them.
 Alternatively, we can @(see enable) @('bound?') and @('binding') and hope that
 by opening up these functions, the conjectures will reduce to versions that
 the prover does know enough about or can prove by induction.  In this case,
 this strategy works.  The hints tell the prover to @(see enable) the functions
 in question when considering the designated goal.</p>

 <p>Below we develop the theorems showing that @('add-phone'),
 @('change-phone'), and @('del-phone') preserve our proposed invariant.  Notice
 that along the way we have to prove some subsidiary facts, some of which are
 pretty ugly.  It would be a good idea for you to try, say,
 @('add-phone-preserves-invariant') without introducing the following four
 lemmas first.  See if you can develop the proof and only add these lemmas as
 you need assistance.  Then try @('change-phone-preserves-invariant') and
 @('del-phone-preserves-invariant').  They will be easier.  It is illuminating
 to think about why @('del-phone-preserves-invariant') does not need any
 ``type'' hypotheses.</p>

 @({
    (defthm bind-preserves-phonebookp
      (implies (and (phonebookp bk)
                    (namep nm)
                    (pnump num))
               (phonebookp (bind nm num bk))))

    (defthm member-equal-strip-cars-bind
      (implies (and (not (equal x y))
                    (not (member-equal x (strip-cars a))))
               (not (member-equal x (strip-cars (bind y z a))))))

    (defthm bind-preserves-domain-setp
      (implies (and (alistp bk)
                    (setp (domain bk)))
               (setp (domain (bind nm num bk))))
      :hints ((\"Goal\" :in-theory (enable domain))))

    (defthm phonebookp-alistp
      (implies (phonebookp bk)
               (alistp bk)))

    (defthm ADD-PHONE-PRESERVES-INVARIANT
      (implies (and (valid-phonebookp bk)
                    (namep nm)
                    (pnump num))
               (valid-phonebookp (add-phone nm num bk)))
      :hints ((\"Goal\" :in-theory (disable domain-bind))))

    (defthm CHANGE-PHONE-PRESERVES-INVARIANT
      (implies (and (valid-phonebookp bk)
                    (namep nm)
                    (pnump num))
               (valid-phonebookp (change-phone nm num bk)))
      :hints ((\"Goal\" :in-theory (disable domain-bind))))

    (defthm remove-equal-preserves-setp
      (implies (setp l)
               (setp (remove-equal x l))))

    (defthm rembind-preserves-phonebookp
      (implies (phonebookp bk)
               (phonebookp (rembind nm bk))))

    (defthm DEL-PHONE-PRESERVES-INVARIANT
      (implies (valid-phonebookp bk)
               (valid-phonebookp (del-phone nm bk))))
 })

 <p>As a final test of your understanding, try to formulate and prove an
 invariant that says that no phone number is assigned to more than one name.
 The following hints may help.</p>

 <blockquote>

 <p>1. Define the appropriate invariant.  (Hint: remember the function
 @('range').)</p>

 <p>2. Do our current definitions of @('add-phone') and @('change-phone')
 necessarily preserve this property?  If not, consider what hypotheses are
 necessary in order to guarantee that they do preserve this property.</p>

 <p>3. Study the definition of the function @('range') and notice that it is
 defined in terms of the function @(tsee strip-cdrs).  Understand how this
 defines the range of an alist.</p>

 <p>4. Formulate the correctness theorems and attempt to prove them.  You'll
 probably benefit from studying the invariant proof above.  In particular, you
 may need some fact about the function @(tsee strip-cdrs) analogous to the
 lemma @('member-equal-strip-cars-bind') above.</p>

 </blockquote>

 <p>Below is one solution to this exercise.  Don't look at the solution,
 however, until you've struggled a bit with it.  Notice that we didn't actually
 change the definitions of @('add-phone') and @('change-phone'), but added a
 hypothesis saying that the number is ``new.''  We could have changed the
 definitions to check this and return the phonebook unchanged if the number was
 already in use.</p>

 @({
    (defun pnums-in-use (bk)
      (range bk))

    (defun phonenums-unique (bk)
      (setp (pnums-in-use bk)))

    (defun new-pnump (pnum bk)
      (not (member-equal pnum (pnums-in-use bk))))

    (defthm member-equal-strip-cdrs-rembind
      (implies (not (member-equal x (strip-cdrs y)))
               (not (member-equal x (strip-cdrs (rembind z y))))))

    (defthm DEL-PHONE-PRESERVES-PHONENUMS-UNIQUE
      (implies (phonenums-unique bk)
               (phonenums-unique (del-phone nm bk)))
      :hints ((\"Goal\" :in-theory (enable range))))

    (defthm strip-cdrs-bind-non-member
      (implies (and (not (bound? x a))
                    (alistp a))
               (equal (strip-cdrs (bind x y a))
                      (append (strip-cdrs a) (list y))))
      :hints ((\"Goal\" :in-theory (enable bound?))))

    (defthm setp-append-list
      (implies (setp l)
               (equal (setp (append l (list x)))
                      (not (member-equal x l)))))

    (defthm ADD-PHONE-PRESERVES-PHONENUMS-UNIQUE
      (implies (and (phonenums-unique bk)
                    (new-pnump pnum bk)
                    (alistp bk))
               (phonenums-unique (add-phone nm pnum bk)))
      :hints ((\"Goal\" :in-theory (enable range))))

    (defthm member-equal-strip-cdrs-bind
      (implies (and (not (member-equal z (strip-cdrs a)))
                    (not (equal z y)))
               (not (member-equal z (strip-cdrs (bind x y a))))))

    (defthm CHANGE-PHONE-PRESERVES-PHONENUMS-UNIQUE
      (implies (and (phonenums-unique bk)
                    (new-pnump pnum bk)
                    (alistp bk))
               (phonenums-unique (change-phone nm pnum bk)))
      :hints ((\"Goal\" :in-theory (enable range))))
 })")

(defxdoc tutorial4-defun-sk-example
  :parents (annotated-acl2-scripts)
  :short "Example of quantified notions"
  :long "<p>This example illustrates the use of @(tsee defun-sk) and @(tsee
 defthm) @(see events) to reason about quantifiers.  See @(see defun-sk).  For
 a more through, systematic beginner's introduction to quantification in ACL2,
 see @(see quantifier-tutorial).</p>

 <p>Many users prefer to avoid the use of quantifiers, since ACL2 provides only
 very limited support for reasoning about quantifiers.</p>

 <p>Here is a list of @(see events) that proves that if there are arbitrarily
 large numbers satisfying the disjunction @('(OR P R)'), then either there are
 arbitrarily large numbers satisfying @('P') or there are arbitrarily large
 numbers satisfying @('R').</p>

 @({
  ; Introduce undefined predicates p and r.
  (defstub p (x) t)
  (defstub r (x) t)

  ; Define the notion that something bigger than x satisfies p.
  (defun-sk some-bigger-p (x)
    (exists y (and (< x y) (p y))))

  ; Define the notion that something bigger than x satisfies r.
  (defun-sk some-bigger-r (x)
    (exists y (and (< x y) (r y))))

  ; Define the notion that arbitrarily large x satisfy p.
  (defun-sk arb-lg-p ()
    (forall x (some-bigger-p x)))

  ; Define the notion that arbitrarily large x satisfy r.
  (defun-sk arb-lg-r ()
    (forall x (some-bigger-r x)))

  ; Define the notion that something bigger than x satisfies p or r.
  (defun-sk some-bigger-p-or-r (x)
    (exists y (and (< x y) (or (p y) (r y)))))

  ; Define the notion that arbitrarily large x satisfy p or r.
  (defun-sk arb-lg-p-or-r ()
    (forall x (some-bigger-p-or-r x)))

  ; Prove the theorem promised above.  Notice that the functions open
  ; automatically, but that we have to provide help for some rewrite
  ; rules because they have free variables in the hypotheses.  The
  ; ``witness functions'' mentioned below were introduced by DEFUN-SK.

  (thm
   (implies (arb-lg-p-or-r)
            (or (arb-lg-p)
                (arb-lg-r)))
   :hints ((\"Goal\"
            :use
            ((:instance some-bigger-p-suff
                        (x (arb-lg-p-witness))
                        (y (some-bigger-p-or-r-witness
                            (max (arb-lg-p-witness)
                                 (arb-lg-r-witness)))))
             (:instance some-bigger-r-suff
                        (x (arb-lg-r-witness))
                        (y (some-bigger-p-or-r-witness
                            (max (arb-lg-p-witness)
                                 (arb-lg-r-witness)))))
             (:instance arb-lg-p-or-r-necc
                        (x (max (arb-lg-p-witness)
                                (arb-lg-r-witness))))))))

  ; And finally, here's a cute little example.  We have already
  ; defined above the notion (some-bigger-p x), which says that
  ; something bigger than x satisfies p.  Let us introduce a notion
  ; that asserts that there exists both y and z bigger than x which
  ; satisfy p.  On first glance this new notion may appear to be
  ; stronger than the old one, but careful inspection shows that y and
  ; z do not have to be distinct.  In fact ACL2 realizes this, and
  ; proves the theorem below automatically.

  (defun-sk two-bigger-p (x)
    (exists (y z) (and (< x y) (p y) (< x z) (p z))))

  (thm (implies (some-bigger-p x) (two-bigger-p x)))

  ; A technical point:  ACL2 fails to prove the theorem above
  ; automatically if we take its contrapositive, unless we disable
  ; two-bigger-p as shown below.  That is because ACL2 needs to expand
  ; some-bigger-p before applying the rewrite rule introduced for
  ; two-bigger-p, which contains free variables.  The moral of the
  ; story is:  Don't expect too much automatic support from ACL2 for
  ; reasoning about quantified notions.

  (thm (implies (not (two-bigger-p x)) (not (some-bigger-p x)))
       :hints ((\"Goal\" :in-theory (disable two-bigger-p))))
 })")

(defxdoc tutorial5-miscellaneous-examples
  :parents (annotated-acl2-scripts)
  :short "Miscellaneous ACL2 examples"
  :long "<p>The following examples are more advanced examples of usage of ACL2.
 They are included largely for reference, in case someone finds them
 useful.</p>")

(defxdoc type
  :parents (pointers)
  :short "Disambiguation page for <i>type</i>-related concepts."

  :long "<p>The word <b>type</b> might mean many things in ACL2.</p>

<dl>

<dt>Built-in Types</dt>

<dd>ACL2 can reason about and compute with certain different kinds of objects,
such as @(see numbers), @(see strings), @(see characters), and @(see conses).
See @(see |About Types|) for basic background on the different kinds of ACL2
objects.</dd>

<dt>User-Defined Types</dt>

<dd>When modeling systems with ACL2, you may often want to introduce certain
concepts as new data types.  For instance, if you are modeling a network, you
might want @('host') and @('connection') objects.  ACL2 does not directly
support introducing new types.  Instead, such types are usually ``emulated'' by
introducing a new <i>recognizer</i> function, say @('hostp'), and perhaps some
related <i>constructor</i> and <i>accessor</i> functions, say @('make-host')
and @('host->name').  Macro libraries can help to assist with introducing
common types.  See for instance @(see std::std/util), @(see defdata::defdata),
or @(see fty::fty).</dd>

<dt>Type Declarations</dt>

<dd>For more efficient Common Lisp execution, ACL2 functions can be annotated
with Common Lisp type specifiers (see @(see type-spec)) that may boost
performance by reducing run-time type checking.  This mechanism is integrated
with ACL2's @(see guard) mechanism, so you can prove your type declarations are
correct.  See also @(see declare) and @(see the), and also @(see
patbind-the).</dd>

<dt>Type Prescriptions</dt>

<dd>ACL2 includes a limited but efficient ``@(see type-set) reasoning engine
for determining whether objects are of certain <b>built-in</b> types.  This
engine can be extended with @(see type-prescription) rules.  Such rules are
often inferred automatically when new functions are introduced with @(see
defun).  Type-set reasoning can assist other reasoning engines like @(see
forward-chaining), @(see linear-arithmetic), and rewriting.  Type-set
information is stored in a @(see type-alist) data structure.</dd>

<dt>Tau</dt>

<dd>ACL2 includes another reasoning engine, the @(see tau-system), for
reasoning about type-like predicates.  Unlike @(see type-set), Tau can also be
used for reasoning about <b>user-defined types</b>, and can also carry out
certain interval arithmetic reasoning.  See the @(see
introduction-to-the-tau-system) for more information about Tau.</dd>

</dl>")

(defxdoc type-alist
  :parents (type-set)
  :short "An ACL2 representation of contextual knowledge"
  :long "<p>The ACL2 prover maintains many structures that need not be
  understood by the user.  One of these, the <i>type-alist</i> structure, is
  usually in this category.  But some utilities refer to the type-alist, so we
  summarize it here.</p>

  <p>A type-alist is an association list, each element of which is of the form
  <tt>(u ts . ttree)</tt>, where @('u') is a @(see term) (in internal,
  ``translated'' form), @('ts') is a @(see type-set), and @('ttree') is a
  tag-tree (see @(see ttree)).  Such an element means that the term @('u') has
  the type-set @('ts'), which is a number.  While you are welcome to see the
  @(see documentation) of @(see type-set) for details, this is not necessary,
  since user-level utilities generally display a type-alist without displaying
  numeric type-sets.  Instead, they often use a symbol of the form
  <tt>*TS-typ*</tt> to denote the type described by <tt>typ</tt>, and for
  complements they use <tt>(TS-COMPLEMENT *TS-typ*)</tt>.  For example, a
  context in which the terms <tt>(p x y)</tt>, @('(no-duplicatesp-equal y)'),
  and @('(natp x)') are assumed to be true (i.e., non-@('nil')) may be
  displayed using the following lines.</p>

  @({
  -----
  Terms with type *TS-T*:
  (NO-DUPLICATESP-EQUAL Y)
  -----
  Terms with type (TS-COMPLEMENT *TS-NIL*):
  (P X Y)
  -----
  Terms with type *TS-NON-NEGATIVE-INTEGER*:
  X
  -----
  })

  <p>These lines says that @('(no-duplicatesp-equal y)') is the symbol @('t'),
  <tt>(p x y)</tt> is not the symbol @('nil'), and @('x') is a non-negative
  integer (i.e., a @(tsee natp)).</p>

  <p>ACL2 computes a type-alist based on contextual information including the
  hypotheses of the current goal (technically: the negations of the literals in
  the goal that are not currently being rewritten), @(see forward-chaining)
  from those literals, and the surrounding tests in calls of @('if').  The
  type-alist is of course not all that is known, since an entire logical @(see
  world) of facts is also known; and additional known information may be
  recorded in the current database of @(see linear) rules.</p>")

(defxdoc type-prescription
  :parents (rule-classes)
  :short "Make a rule that specifies the type of a term"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.  In this topic we focus on
 user-defined type-prescription rules, but note that ACL2 also introduces
 type-prescription rules when introducing a function with @(tsee defun); see
 @(see type-prescription-debugging) for discussion of how to influence the
 generation of such rules.</p>

 @({
  Examples:
  (defthm integerp-foo                       ; Assumes that foo has been
    (integerp (foo x y))                     ; defined; then, states that
    :rule-classes :type-prescription)        ; (foo x y) is of type integer.

  (defthm characterp-nth-type-prescription   ; (Nth n lst) is of type character
    (implies                                 ; provided the hypotheses can be
     (and (character-listp lst)              ; established by type reasoning.
          (<= 0 n)
          (< n (len lst)))
     (characterp (nth n lst)))
    :rule-classes :type-prescription)

  (defthm characterp-nth-type-prescription-alt ; equivalent to the above
    (implies
     (and (character-listp lst)
          (<= 0 n)
          (< n (len lst)))
     (characterp (nth n lst)))
    :rule-classes ((:type-prescription :typed-term (nth n lst))))

  (defthm demodulize-type-for-quote-value  ; (Demodulize a lst 'value ans) is
    (implies                               ; either a nonnegative integer or
     (and (atom a)                         ; of the same type as ans, provided
          (true-listp lst)                 ; the hyps can be established by type
          (member-equal a lst))            ; reasoning
     (or (and (integerp (demodulize a lst 'value ans))
              (>= (demodulize a lst 'value ans) 0))
       (equal (demodulize a lst 'value ans) ans)))
    :rule-classes :type-prescription)
 })

 <p>To specify the term whose type (see @(see type-set)) is described by the
 rule, provide that term as the value of the @(':typed-term') field of the rule
 class object.</p>

 @({
  General Form (after preprocessing; see below):
  (implies hyps
           (or type-restriction1-on-pat
               ...
               type-restrictionk-on-pat
               (equal pat var1)
               ...
               (equal pat varj)))
 })

 <p>where @('pat') is the application of some function symbol to some
 arguments, each @('type-restrictioni-on-pat') is a term involving @('pat') and
 containing no variables outside of the occurrences of @('pat'), and each
 @('vari') is one of the variables of @('pat').  Generally speaking, the
 @('type-restriction') terms ought to be terms that inform us as to the type of
 @('pat').  Ideally, they should be ``primitive recognizing expressions'' about
 @('pat'); see @(see compound-recognizer).  We describe preprocessing at the
 end of this topic.</p>

 <p>If the @(':typed-term') is not provided in the rule class object, it is
 computed heuristically by looking for a term in the conclusion whose type is
 being restricted.  An error is caused if no such term is found.</p>

 <p>Roughly speaking, the effect of adding such a rule is to inform the ACL2
 typing mechanism that @('pat') has the type described by the conclusion, when
 the hypotheses are true.  In particular, the type of @('pat') is within the
 union of the types described by the several disjuncts.  The ``type described
 by'' @('(equal pat vari)') is the type of @('vari').</p>

 <p>More operationally, when asked to determine the type of a term that is an
 instance of @('pat'), ACL2 will first attempt to establish the hypotheses.
 <b>This is done by type reasoning alone, not rewriting!</b> However, if some
 hypothesis is a call of @(tsee force), then forcing may occur, which may
 ultimately invoke the rewriter; see @(see force) and see @(see case-split).
 So-called free variables in hypotheses are treated specially; see @(see
 free-variables).  Provided the hypotheses are established by type reasoning,
 ACL2 then unions the types described by the @('type-restrictioni-on-pat')
 terms together with the types of those subexpressions of @('pat') identified
 by the @('vari').  The final type computed for a term is the intersection of
 the types implied by each applicable rule.  Type prescription rules may be
 disabled.</p>

 <p>You can limit the recursive establishment of hypotheses of rules; see @(see
 set-backchain-limit).</p>

 <p>Because only type reasoning is used to establish the hypotheses of
 @(':type-prescription') rules, some care must be taken with the hypotheses.
 Suppose, for example, that the non-recursive function @('my-statep') is
 defined as</p>

 @({
    (defun my-statep (x)
      (and (true-listp x)
           (equal (len x) 2)))
 })

 <p>and suppose @('(my-statep s)') occurs as a hypothesis of a
 @(':type-prescription') rule that is being considered for use in the proof
 attempt for a conjecture with the hypothesis @('(my-statep s)').  Since the
 hypothesis in the conjecture is rewritten, it will become the conjunction of
 @('(true-listp s)') and @('(equal (len s) 2)').  Those two terms will be
 assumed to have type @('t') in the context in which the
 @(':type-prescription') rule is tried.  But type reasoning will be unable to
 deduce that @('(my-statep s)') has type @('t') in this context.  Thus, either
 @('my-statep') should be disabled (see @(see disable)) during the proof
 attempt or else the occurrence of @('(my-statep s)') in the
 @(':type-prescription') rule should be replaced by the conjunction into which
 it rewrites.</p>

 <p>While this example makes it clear how non-recursive predicates can cause
 problems, non-recursive functions in general can cause problems.  For example,
 if @('(mitigate x)') is defined to be @('(if (rationalp x) (1- x) x)') then
 the hypothesis @('(pred (mitigate s))') in the conjecture will rewrite,
 opening @('mitigate') and splitting the conjecture into two subgoals, one in
 which @('(rationalp s)') and @('(pred (1- x))') are assumed and the other in
 which @('(not (rationalp s))') and @('(pred x)') are assumed.  But @('(pred
 (mitigate s))') will not be typed as @('t') in either of these contexts.  The
 moral is: beware of non-recursive functions occurring in the hypotheses of
 @(':type-prescription') rules.</p>

 <p>Because of the freedom one has in forming the conclusion of a
 type-prescription, we have to use heuristics to recover the pattern, @('pat'),
 whose type is being specified.  In some cases our heuristics may not identify
 the intended term and the @(':type-prescription') rule will be rejected as
 illegal because the conclusion is not of the correct form.  When this happens
 you may wish to specify the @('pat') directly.  This may be done by using a
 suitable rule class token.  In particular, when the token
 @(':type-prescription') is used it means ACL2 is to compute pat with its
 heuristics; otherwise the token should be of the form @('(:type-prescription
 :typed-term pat)'), where @('pat') is the term whose type is being
 specified.</p>

 <p>The defun event may generate a @(':type-prescription') rule.  Suppose
 @('fn') is the name of the function concerned.  Then @('(:type-prescription
 fn)') is the rune given to the type-prescription, if any, generated for
 @('fn') by @(tsee defun).  (The trivial rule, saying @('fn') has unknown type,
 is not stored, but @(tsee defun) still allocates the rune and the corollary of
 this rune is known to be @('t').)</p>

 <p>We close with a discussion of how, before a term is parsed into a
 @(':type-prescription') rule, it is preprocessed.  We describe this
 preprocessing in some detail below, but first consider the following
 (contrived) example.</p>

 @({
  (defthm append-tp-example
    (let ((result (append x y)))
      (implies (nat-listp x)
               (implies (let ((second-hyp (integer-listp y)))
                          second-hyp)
                        (true-listp result))))
    :rule-classes :type-prescription)
 })

 <p>This theorem is parsed into a type-prescription rule with the following
 hypotheses and conclusion.</p>

 @({
  (nat-listp x) ; first hypothesis
  ((lambda (second-hyp) second-hyp) (integer-listp y)) ; second hypothesis
  (true-listp (binary-append x y)) ; conclusion
 })

 <p>Notice that the top-level @(tsee LET) was expanded, i.e., @('(append x y)')
 was substituted for @('result') &mdash; more accurately, @('(binary-append x
 y)') was substituted for @('result'), since @(tsee append) is a macro that
 abbreviates @(tsee binary-append).  Also notice that the two hypotheses were
 ``flattened'' in the sense that they were gathered up into a list.  Finally,
 notice that the @(tsee LET) in the second hypothesis was not expanded (it was
 merely translated to internal form, using @('LAMBDA')).  If you actually
 submit the theorem above, you will get warnings, which you may choose to
 ignore; the application of @('type-prescription') rules is somewhat subtle, so
 if you use them then you may wish to experiment to see which forms work best
 for you.</p>

 <p>Here is the detail promised above, for parsing a term into a
 @(':type-prescription') rule.  There are two steps.  (1) ACL2 first translates
 the term, expanding all macros (see @(see trans)) and also removing @(see
 guard-holders).  (2) Then the the translated term is traversed top-down,
 expanding away @('lambda')s (@(tsee let), @(tsee let*), and @(tsee mv-let)
 expressions) and flattening the @(tsee IMPLIES) structure, until the
 conclusion is exposed; then the conclusion's @('lambda')s are also expanded
 away.  The simplest way to understand (2) may be to look at the definition of
 ACL2 source function @('unprettyify-tp'), which implements Step (2), say by
 evaluating @(':')@(tsee pe)@(' unprettyify-tp').</p>")

(defxdoc type-prescription-debugging
  :parents (debugging type-prescription)
  :short "Improve a built-in @(see type-prescription) rule"
  :long "<p>A @(see type-prescription) rule is introduced automatically when a
 function is defined (see @(see defun)).  However, that rule might not be what
 you expect.  In this topic we explore how you might be able to improve that
 rule, by way of an example.</p>

 <p>First consider the following definition.</p>

 @({
 ACL2 !>(defun f (x) (alistp x))

 Since F is non-recursive, its admission is trivial.  We observe that
 the type of F is described by the theorem
 (OR (EQUAL (F X) T) (EQUAL (F X) NIL)).  We used the :type-prescription
 rule ALISTP.

 Summary
 Form:  ( DEFUN F ...)
 Rules: ((:TYPE-PRESCRIPTION ALISTP))
 Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.00)
  F
 ACL2 !>
 })

 <p>Notice in particular the phrase, ``We used the :type-prescription
 rule ALISTP,'' and the corresponding @(see rune) @('(:TYPE-PRESCRIPTION
 ALISTP)') in the list of rules printed in the summary.  These are telling us
 that ACL2 used the indicated rule during the process of computing a
 (@see type-prescription) rule for @('f').</p>

 <p>Now suppose that in a different session we instead proceed as follows.</p>

 @({
 ACL2 !>(in-theory (disable (:type-prescription alistp)))

 Summary
 Form:  ( IN-THEORY (DISABLE ...))
 Rules: NIL
 Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
  (:NUMBER-OF-ENABLED-RUNES 3298)
 ACL2 !>(defun f (x) (alistp x))

 Since F is non-recursive, its admission is trivial.  We could deduce
 no constraints on the type of F.

 Summary
 Form:  ( DEFUN F ...)
 Rules: NIL
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  F
 ACL2 !>
 })

 <p>Notice that this time ``We could deduce no constraints on the type of F,''
 because in this context, @(see type-set) reasoning does not see that the body
 of @('f') is a Boolean, because @('(:type-prescription alistp)') has been
 @(see disable)d.  Thus, the ``Rules'' field of the summary is empty this
 time.</p>

 <p>Consider the following story.  On Monday, you run the first session, and a
 subsequent proof uses @(see type-set) reasoning to conclude that @('(f x)') is
 Boolean, even after you @(see disable) the @(see definition) of @('f').  Then
 on Tuesday, you run the second session, and are surprised to find that ACL2 no
 longer reasons (during that same subsequent proof attempt) that @('(f x)') is
 Boolean.  You want to debug this problem, so you look back in the log where
 you defined @('f'), and you see the ``deduce no constraints'' message &mdash;
 but then you look further back, at Monday's log, where you find the definition
 of @('f') ``used the :type-prescription rule ALISTP'' to conclude that ``the
 type of F is described by the theorem (OR (EQUAL (F X) T) (EQUAL (F X)
 NIL))''.  The mention of ALISTP in that definition's output from Monday,
 together with the corresponding mention of @('(:TYPE-PRESCRIPTION ALISTP)') in
 the ``Rules'' field of the summary, leads you to resolve the issue as follows.
 On Monday, when @('(:TYPE-PRESCRIPTION ALISTP)') was @(see enable)d, ACL2 used
 type-set reasoning to conclude that the body of @('f') is Boolean, but on
 Tuesday, @('(:TYPE-PRESCRIPTION ALISTP)') was disabled at that point and hence
 the body of @('f') was not known to be Boolean by type-set reasoning.  Hence
 on Tuesday, no Boolean type-prescription rule was stored for @('f') at
 definition time, which is why the subsequent proof attempt failed to use such
 a rule.  So you avoid disabling @('(:TYPE-PRESCRIPTION ALISTP)') until after
 submitting the @(tsee defun) for @('f'), and now ACL2's type reasoning knows
 that @('f') returns a Boolean.</p>")

(defxdoc type-set
  :parents (miscellaneous)
  :short "How type information is encoded in ACL2"
  :long "<p>To help you experiment with type-sets we briefly note the following
 utility functions.</p>

 <p>@('(type-set-quote x)') will return the type-set of the object @('x').  For
 example, @('(type-set-quote \"test\")') is @('2048') and @('(type-set-quote
 '(a b c))') is @('512').</p>

 <p>@('(type-set 'term nil nil nil (ens state) (w state) nil nil nil)') will
 return the type-set of @('term') with respect to the current world and the
 top-level enabled structure.  For example,</p>

 @({
  (type-set '(integerp x) nil nil nil (ens state) (w state) nil nil nil)
 })

 <p>will return (mv 192 nil).  192, otherwise known as @('*ts-boolean*'), is
 the type-set containing @('t') and @('nil').  The second result may be ignored
 in these experiments.  @('Term') must be in the @('translated'), internal form
 shown by @(':')@(tsee trans).  See @(see trans) and see @(see term).</p>

 <p>@('(type-set-implied-by-term 'x nil 'term (ens state)(w state) nil)') will
 return the type-set deduced for the variable symbol @('x') assuming the
 @('translated') term, @('term'), true.  The second result may be ignored in
 these experiments.  For example,</p>

 @({
  (type-set-implied-by-term 'v nil '(integerp v)
                            (ens state) (w state) nil)
 })

 <p>returns @('11').</p>

 <p>@('(convert-type-set-to-term 'x ts (ens state) (w state) nil)') will return
 a term whose truth is equivalent to the assertion that the term @('x') has
 type-set @('ts').  The second result may be ignored in these experiments.  For
 example</p>

 @({
  (convert-type-set-to-term 'v 523 (ens state) (w state) nil)
 })

 <p>returns a term expressing the claim that @('v') is either an integer or a
 non-@('nil') true-list.  @('523') is the @('logical-or') of @('11') (which
 denotes the integers) with @('512') (which denotes the non-@('nil')
 true-lists).</p>

 <p>The ``actual primitive types'' of ACL2 are listed in
 @('*actual-primitive-types*'), whose elements are shown below.  Each actual
 primitive type denotes a set &mdash; sometimes finite and sometimes not
 &mdash; of ACL2 objects and these sets are pairwise disjoint.  For example,
 @('*ts-zero*') denotes the set containing 0 while @('*ts-negative-integer*')
 denotes the set containing all of the negative integers.</p>

 @({
  *TS-ZERO*                  ;;; {0}
  *TS-ONE*                   ;;; {1}
  *TS-INTEGER>1*             ;;; integers greater than 1
  *TS-POSITIVE-RATIO*        ;;; positive non-integer rationals
  *TS-NEGATIVE-INTEGER*      ;;; negative integers
  *TS-NEGATIVE-RATIO*        ;;; negative non-integer rationals
  *TS-COMPLEX-RATIONAL*      ;;; complex rationals
  *TS-NIL*                   ;;; {nil}
  *TS-T*                     ;;; {t}
  *TS-NON-T-NON-NIL-SYMBOL*  ;;; symbols other than nil, t
  *TS-PROPER-CONS*           ;;; null-terminated non-empty lists
  *TS-IMPROPER-CONS*         ;;; conses that are not proper
  *TS-STRING*                ;;; strings
  *TS-CHARACTER*             ;;; characters
 })

 <p>The actual primitive types were chosen by us to make theorem proving
 convenient.  Thus, for example, the actual primitive type @('*ts-nil*')
 contains just @('nil') so that we can encode the hypothesis ``@('x') is
 @('nil')'' by saying ``@('x') has type @('*ts-nil*')'' and the hypothesis
 ``@('x') is non-@('nil')'' by saying ``@('x') has type complement of
 @('*ts-nil*').''  We similarly devote a primitive type to @('t'), @('*ts-t*'),
 and to a third type, @('*ts-non-t-non-nil-symbol*'), to contain all the other
 ACL2 symbols.</p>

 <p>Let @('*ts-other*') denote the set of all Common Lisp objects other than
 those in the actual primitive types.  Thus, @('*ts-other*') includes such
 things as floating point numbers and CLTL array objects.  The actual primitive
 types together with @('*ts-other*') constitute what we call @('*universe*').
 Note that @('*universe*') is a finite set containing one more object than
 there are actual primitive types; that is, here we are using @('*universe*')
 to mean the finite set of primitive types, not the infinite set of all objects
 in all of those primitive types.  @('*Universe*') is a partitioning of the set
 of all Common Lisp objects: every object belongs to exactly one of the sets in
 @('*universe*').</p>

 <p>Abstractly, a ``type-set'' is a subset of @('*universe*').  To say that a
 term, @('x'), ``has type-set @('ts')'' means that under all possible
 assignments to the variables in @('x'), the value of @('x') is a member of
 some member of @('ts').  Thus, @('(cons x y)') has type-set
 @('{*ts-proper-cons* *ts-improper-cons*}').  A term can have more than one
 type-set.  For example, @('(cons x y)') also has the type-set
 @('{*ts-proper-cons* *ts-improper-cons* *ts-nil*}').  Extraneous types can be
 added to a type-set without invalidating the claim that a term ``has'' that
 type-set.  Generally we are interested in the smallest type-set a term has,
 but because the entire theorem-proving problem for ACL2 can be encoded as a
 type-set question, namely, ``Does @('p') have type-set complement of
 @('*ts-nil*')?,'' finding the smallest type-set for a term is an undecidable
 problem.  When we speak informally of ``the'' type-set we generally mean ``the
 type-set found by our heuristics'' or ``the type-set assumed in the current
 context.''</p>

 <p>Note that if a type-set, @('ts'), does not contain @('*ts-other*') as an
 element then it is just a subset of the actual primitive types.  If it does
 contain @('*ts-other*') it can be obtained by subtracting from @('*universe*')
 the complement of @('ts').  Thus, every type-set can be written as a (possibly
 complemented) subset of the actual primitive types.</p>

 <p>By assigning a unique bit position to each actual primitive type we can
 encode every subset, @('s'), of the actual primitive types by the nonnegative
 integer whose ith bit is on precisely if @('s') contains the ith actual
 primitive type.  The type-sets written as the complement of @('s') are encoded
 as the @('twos-complement') of the encoding of @('s').  Those type-sets are
 thus negative integers.  The bit positions assigned to the actual primitive
 types are enumerated from @('0') in the same order as the types are listed in
 @('*actual-primitive-types*').  At the concrete level, a type-set is an
 integer between @('*min-type-set*') and @('*max-type-set*'), inclusive.</p>

 <p>For example, @('*ts-nil*') has bit position @('7').  The type-set
 containing just @('*ts-nil*') is thus represented by @('128').  If a term has
 type-set @('128') then the term is always equal to @('nil').  The type-set
 containing everything but @('*ts-nil*') is the twos-complement of @('128'),
 which is @('-129').  If a term has type-set @('-129'), it is never equal to
 @('nil').  By ``always'' and ``never'' we mean under all, or under no,
 assignments to the variables, respectively.</p>

 <p>Here is a more complicated example.  Let @('s') be the type-set containing
 all of the symbols and the natural numbers.  The relevant actual primitive
 types, their bit positions and their encodings are:</p>

 @({
  actual primitive type       bit    value

  *ts-zero*                    0       1
  *ts-one*                     1       2
  *ts-integer>1*               2       4
  *ts-nil*                     7     128
  *ts-t*                       8     256
  *ts-non-t-non-nil-symbol*    9     512
 })

 <p>Thus, the type-set @('s') is represented by @('(+ 1 2 4 128 256 512)') =
 @('903').  The complement of @('s'), i.e., the set of all objects other than
 the natural numbers and the symbols, is @('-904').  We can get ACL2 to provide
 such information as follows.</p>

 @({
 ACL2 !>(decode-type-set 903)
 (TS-UNION *TS-SYMBOL* *TS-NON-NEGATIVE-INTEGER*)
 ACL2 !>(decode-type-set -904)
 (TS-COMPLEMENT (TS-UNION *TS-SYMBOL* *TS-NON-NEGATIVE-INTEGER*))
 ACL2 !>
 })")

(defxdoc type-set-inverter
  :parents (rule-classes)
  :short "Exhibit a new decoding for an ACL2 type-set"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 @({
  Example Rule Class:
  (:type-set-inverter
    :corollary (equal (and (counting-number x) (not (equal x 0)))
                      (and (integerp x) (< 0 x)))
    :type-set 2)

  General Forms of Rule Class:
  :type-set-inverter, or
  (:type-set-inverter :type-set n)

  General Form of Theorem or Corollary:
  (EQUAL new-expr old-expr)
 })

 <p>where @('n') is a @(tsee type-set) (see @(see type-set)) and @('old-expr')
 is the term containing @('x') as a free variable that ACL2 currently uses to
 recognize @(tsee type-set) @('n').  For a given @('n'), the exact form of
 @('old-expr') is generated by</p>

 @({
  (convert-type-set-to-term 'x n (ens state) (w state) nil)].
 })

 <p>If the @(':')@(tsee type-set) field of the rule-class is omitted, we
 attempt to compute it from the right-hand side, @('old-expr'), of the
 corollary.  That computation is done by @('type-set-implied-by-term') (see
 @(see type-set)).  However, it is possible that the type-set we compute from
 @('lhs') does not have the required property that when inverted with
 @('convert-type-set-to-term') the result is @('lhs').  If you omit
 @(':')@(tsee type-set) and an error is caused because @('lhs') has the
 incorrect form, you should manually specify both @(':')@(tsee type-set) and
 the @('lhs') generated by @('convert-type-set-to-term').</p>

 <p>The rule generated will henceforth make @('new-expr') be the term used by
 ACL2 to recognize type-set @('n').  If this rule is created by a @(tsee
 defthm) event named @('name') then the rune of the rule is
 @('(:type-set-inverter name)') and by disabling that rune you can prevent its
 being used to decode type-sets.</p>

 <p>Type-sets are inverted when forced assumptions are turned into formulas to
 be proved.  In their internal form, assumptions are essentially pairs
 consisting of a context and a goal term, which was forced.  Abstractly a
 context is just a list of hypotheses which may be assumed while proving the
 goal term.  But actually contexts are alists which pair terms with type-sets,
 encoding the current hypotheses.  For example, if the original conjecture
 contained the hypothesis @('(integerp x)') then the context used while working
 on that conjecture will include the assignment to @('x') of the type-set
 @('*ts-integer*').</p>")

(defxdoc type-spec
  :parents (declare the)
  :short "Type specifiers can be used in Common Lisp type declarations and
 @(see the) forms, and may result in improved efficiency of execution."

  :long "<p>ACL2 permits the use of type declarations in certain contexts; see
 @(see declare) for background.  Here is an example of a type declaration; here
 the symbol, @('integer'), is what we refer to as a ``type-spec'':</p>

 @({
     (let ((x (+ a b)))
       (declare (type integer x))   ;; <-- type declaration
       (+ 1 x))
 })

 <p>A Common Lisp compiler might be able to use the above declaration to
 improve the execution efficiency of the resulting code.  In particular, the
 Common Lisp @(see +) operation is rather elaborate: it must be capable of
 adding together integers, rationals, floats, etc.  When we tell the compiler
 that this @('x') is surely an integer, it may be able to use a more efficient
 version of @('(+ 1 x)') that only deals with the integer case.</p>

 <p>Type declarations can be added to functions, @(tsee let) bindings, and
 other places as described in @(see declare), and interact with the ACL2's
 @(see guard) mechanism.  For instance, during guard verification, the above
 type declaration will result in a guard obligation: we will need to prove that
 @('(+ a b)') is always an integer.  Type declarations about the formals of a
 function generally become part of the guard of the function, but see also
 @(see split-types) for a way to gain more control over this.</p>

 <p>Whether or not a particular type declaration will actually improve the
 efficiency of your functions depends on the Lisp compiler.  For instance, many
 Lisp compilers will not benefit much from a plain @('integer') declaration.
 If you are trying to optimize code by adding type declarations, it may be
 useful to use @(see disassemble$) to inspect the impact that your declarations
 have on the resulting code.</p>

 <h3>Type Specs</h3>

 <p>The syntax that Common Lisp compilers use for these type
 declarations&mdash;e.g., the symbol @('integer') above&mdash;is different than
 the usual syntax of ACL2.</p>

 <p>We use the name <b>type-spec</b> to refer to the supported types that can
 be mentioned in declarations.  For instance:</p>

 <table>
 <tr><th>Declaration</th>                            <th>Type-Spec</th></tr>
 <tr><td>@('(type string x y z)')</td>     <td>@('string')</td></tr>
 <tr><td>@('(type (integer 0 7) x)')</td>  <td>@('(integer 0 7)')</td></tr>
 <tr><td>@('(type rational x)')</td>       <td>@('rational')</td></tr>
 <tr><td>@('(type (rational 1 *) x)')</td> <td>@('(rational 1 *)')</td></tr>
 </table>

 <p>The supported type-specs and their meanings (when applied to the variable
 @('x') as in @('(declare (type type-spec x))') are given below.</p>

 @({
  type-spec              meaning
  ----------------------------------------------------------------------
  (AND type1 ... typek)  (AND (p1 X) ... (pk X))
                         where (pj x) is the meaning for type-spec typej
  ATOM                   (ATOM X)
  BIT                    (OR (EQUAL X 1) (EQUAL X 0))
  CHARACTER              (CHARACTERP X)
  COMPLEX                (AND (COMPLEX-RATIONALP X)
                              (RATIONALP (REALPART X))
                              (RATIONALP (IMAGPART X)))
  (COMPLEX RATIONAL)     same as COMPLEX, above
  (COMPLEX type)         (AND (COMPLEX-RATIONALP X)
                              (p (REALPART X))
                              (p (IMAGPART X)))
                         where (p x) is the meaning for type-spec type
  CONS                   (CONSP X)
  INTEGER                (INTEGERP X)
  (INTEGER i j)          (AND (INTEGERP X)   ; See notes below
                              (<= i X)
                              (<= X j))
  (MEMBER x1 ... xn)     (MEMBER X '(x1 ... xn))
  (MOD i)                same as (INTEGER 0 i-1)
  NIL                    NIL
  (NOT type)             (NOT (p X))
                         where (p x) is the meaning for type-spec type
  NULL                   (EQ X NIL)
  (OR type1 ... typek)   (OR (p1 X) ... (pk X))
                         where (pj x) is the meaning for type-spec typej
  RATIO                  (AND (RATIONALP X) (NOT (INTEGERP X)))
  RATIONAL               (RATIONALP X)
  (RATIONAL i j)         (AND (RATIONALP X)  ; See notes below
                              (<= i X)
                              (<= X j))
  REAL                   (RATIONALP X)       ; (REALP X) in ACL2(r)
  (REAL i j)             (AND (RATIONALP X)  ; See notes below
                              (<= i X)
                              (<= X j))
  (SATISFIES pred)       (pred X) ; Lisp requires a unary function, not a macro
  SIGNED-BYTE            (INTEGERP X)
  (SIGNED-BYTE i)        same as (INTEGER k m) where k=-2^(i-1), m=2^(i-1)-1
  STANDARD-CHAR          (STANDARD-CHARP X)
  STRING                 (STRINGP X)
  (STRING max)           (AND (STRINGP X) (EQUAL (LENGTH X) max))
  SYMBOL                 (SYMBOLP X)
  T                      T
  UNSIGNED-BYTE          same as (INTEGER 0 *)
  (UNSIGNED-BYTE i)      same as (INTEGER 0 (2^i)-1)
  ----------------------------------------------------------------------
 })

 <h5>Notes</h5>

 <p>In general, @('(integer i j)') means</p>

 @({
       (AND (INTEGERP X)
            (<= i X)
            (<= X j)).
 })

 <p>But if @('i') is the symbol @('*'), the first inequality is omitted.  If
 @('j') is the symbol @('*'), the second inequality is omitted.  If instead of
 being an integer, the second element of the type specification is a list
 containing an integer, @('(i)'), then the first inequality is made strict.  An
 analogous remark holds for the @('(j)') case.  The @('rational') and @('real')
 type specifiers are similarly generalized.</p>

 <p>Common Lisp itself supports richer type specifiers than ACL2.  Some
 resources:</p>

 <ul>

 <li>A <a
 href='http://sellout.github.io/2012/03/03/common-lisp-type-hierarchy/'>nice
 picture of the Common Lisp Type Hierarchy</a> by Greg Pfeil.</li>

 </ul>")

(defxdoc |The Admission of App|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Admission of App"
  :long "<p><see topic='@(url |Revisiting the Admission of App|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>Here is what it looks like to submit the definition of @('app') to
 ACL2:</p>

 <p><img src='res/tours/green-line.gif'></img></p>

 <code>
 ACL2 !&gt;<b>(defun app (x y)</b>
   <b>(cond ((endp x) y)</b>
         <b>(t (cons (car x) </b>
                  <b>(app (cdr x) y)))))</b>

 The admission of APP is trivial, using the relation O&lt; (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 APP is
 described by the theorem (OR (CONSP (APP X Y)) (EQUAL (APP X Y) Y)).
 We used primitive type reasoning.

 Summary
 Form:  ( DEFUN APP ...)
 Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
 Warnings:  None
 Time:  0.03 seconds (prove: 0.00, print: 0.00, other: 0.03)
  APP
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>The text between the lines above is one interaction with the ACL2 command
 loop.  Interacting with the latest version of ACL2 may not produce the very
 same output, but we trust you'll recognize the basics.</p>

 <p>Above you see the user's <b>input</b> and how the system responds.  This
 little example shows you what the syntax looks like and is a very typical
 <b>successful</b> interaction with the definitional principle.</p>

 <p>Let's look at it a little more closely.</p>

 <p><see topic='@(url |Revisiting the Admission of App|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |The Associativity of App|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Associativity of App"
  :long "<p><see topic='@(url |The Theorem that App is Associative|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p><img src='res/tours/green-line.gif'></img></p>

 <code>
 ACL2!&gt;<b>(let ((a '(1 2))</b>
             <b>(b '(3 4))</b>
             <b>(c '(5 6)))</b>
         <b>(equal (app (app a b) c)</b>
                <b>(app a (app b c))))</b>
 T
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Observe that, for the particular @('a'), @('b'), and @('c') above, @('(app
 (app a b) c)') returns the same thing as @('(app a (app b c))').  Perhaps
 @('app') is <b>associative</b>.  Of course, to be associative means that the
 above property must hold for all values of @('a'), @('b'), and @('c'), not
 just the ones <b>tested</b> above.</p>

 <p>Wouldn't it be cool if you could type</p>

 <code>
 ACL2!&gt;<b>(equal (app (app a b) c)</b>
              <b>(app a (app b c)))</b>

 </code>

 <p>and have ACL2 compute the value @('T')?  Well, <b>you can't!</b> If you try
 it, you'll get an error message!  The message says we can't evaluate that form
 because it contains <b>free</b> variables, i.e., variables not given values.
 Click <see topic='@(url |Free Variables in Top-Level Input|)'>here</see> to
 see the message.</p>

 <p>We cannot evaluate a form on an infinite number of cases.  But we can prove
 that a form is a theorem and hence know that it will always evaluate to
 true.</p>

 <p><see topic='@(url |The Theorem that App is Associative|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |The Base Case in the App Example|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Base Case in the App Example"
  :long "<p>This formula is the <b>Base Case</b>.  It consists of two parts, a
 test identifying the non-inductive case and the conjecture to prove.</p>

 <code>
 (IMPLIES (ENDP A)                 <b>; Test</b>
          (:P A B C))              <b>; Conjecture</b>
 </code>

 <p>When we prove this we can assume</p>

 <code> * @('A') is empty </code>

 <p>and we have to prove the conjecture for @('A').</p>")

(defxdoc |The End of the Flying Tour|
  :parents (|Pages Written Especially for the Tours|)
  :short "The End of the Flying Tour"
  :long "<p><img src='res/tours/landing.gif'></img></p>

 <p>This completes the Flying Tour.</p>

 <p>We recommend that you now take <see topic='@(url
 |A Walking Tour of ACL2|)'>A Walking Tour of ACL2</see>.</p>

 <p>Thanks.<br></br>

 Matt Kaufmann and J Moore</p>

 <p><see topic='@(url |A Walking Tour of ACL2|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |The End of the Proof of the Associativity of App|
  :parents (|Pages Written Especially for the Tours|)
  :short "The End of the Proof of the Associativity of App"
  :long "<p><see topic='@(url |Guiding the ACL2 Theorem Prover|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <code>
 That <see topic='@(url |Popping out of an Inductive Proof|)'>completes</see> the proof of *1.

 <see topic='@(url |The Q.E.D. Message|)'>Q.E.D.</see>

 Summary
 Form:  ( DEFTHM ASSOCIATIVITY-OF-APP ...)
 <see topic='@(url |The Rules used in the Associativity of App Proof|)'>Rules</see>: ((:REWRITE CDR-CONS)
         (:REWRITE CAR-CONS)
         (:DEFINITION NOT)
         (:DEFINITION ENDP)
         (:FAKE-RUNE-FOR-TYPE-SET NIL)
         (:DEFINITION APP))
 Warnings:  None
 Time:  0.27 seconds (prove: <see topic='@(url |The Time Taken to do the Associativity of App Proof|)'>0.10</see>, print: 0.05, other: 0.12)
  ASSOCIATIVITY-OF-APP
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p><see topic='@(url |Guiding the ACL2 Theorem Prover|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |The End of the Walking Tour|
  :parents (|Pages Written Especially for the Tours|)
  :short "The End of the Walking Tour"
  :long "<p><img src='res/tours/sitting.gif'></img></p>

 <p>This completes the Walking Tour.</p>

 <p>We intend to document many other parts of the system this way, but we just
 haven't gotten around to it.</p>

 <p>To start the two tours over again from the beginning, click on the icons
 below.  If you are really interested in learning how to use ACL2, we recommend
 that you repeat each tour at least once more to explore branches of the tour
 that you might have missed.</p>

 <p>If you want to learn how to use the theorem prover, we now recommend that
 you devote the time necessary to work your way through the extended
 introduction to how to use the prover.</p>

 <p>See @(see introduction-to-the-theorem-prover).</p>

 <p>This will explain how to interact with ACL2 and has some sample problems
 for you to solve including some challenge proofs to make ACL2 find.</p>

 <p>We hope you enjoy ACL2.  We do.</p>

 <p>Matt Kaufmann and J Strother Moore</p>

 <p><see topic='@(url |A Flying Tour of ACL2|)'><img
 src='res/tours/flying.gif'></img></see> <see topic='@(url
 |A Walking Tour of ACL2|)'><img src='res/tours/walking.gif'></img></see></p>")

(defxdoc |The Event Summary|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Event Summary"
  :long "<p>At the conclusion of most events (click <see
 topic='@(url |About the Prompt|)'>here</see> for a brief discussion of events or
 see @(see events) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>), ACL2 prints a summary.  The summary for @('app')
 is:</p>

 @({
  Summary
  Form:  ( DEFUN APP ...)
  Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
  Warnings:  None
  Time:  0.03 seconds (prove: 0.00, print: 0.00, other: 0.03)
   APP
 })

 <p>The ``rules'' listed are those used in function admission or proof
 summarized.  What is actually listed are ``runes'' (see @(see rune)) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>)
 which are list-structured names for rules in the ACL2 database or ``@(see
 world)'' <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see>.  Using @(see theories) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> you
 can ``enable'' and ``disable'' rules so as to make them available (or not) to
 the ACL2 theorem prover.</p>

 <p>The ``warnings'' mentioned (none are listed for @('app')) remind the reader
 whether the event provoked any warnings.  The warnings themselves would have
 been printed earlier in the processing and this part of the summary just names
 the earlier warnings printed.</p>

 <p>The ``time'' indicates how much processing time was used and is divided
 into three parts: the time devoted to proof, to printing, and to syntactic
 checks, pre-processing and database updates.  Despite the fact that ACL2 is an
 applicative language it is possible to measure time with ACL2 programs.  The
 @(tsee state) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> contains a clock.  The times are printed in decimal
 notation but are actually counted in integral units.  Note that by default,
 each time is a runtime, also known as a cpu time, as opposed to being a real
 time, also known as a wall clock time.</p>

 <p>The final @('APP') is the value of the @('defun') command and was printed
 by the read-eval-print loop.  The fact that it is indented one space is a
 subtle reminder that the command actually returned an ``error triple'',
 consisting of a flag indicating (in this case) that no error occurred, a value
 (in this case the symbol @('APP')), and the final @(tsee state) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>).
 See @(see ld-post-eval-print) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see> for
 some details.  If you really want to follow that link, however, you might see
 @(see ld) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> first.</p>

 <p>You should now return to <see topic='@(url
 |Revisiting the Admission of App|)'>the Walking Tour</see>.</p>")

(defxdoc |The Expansion of ENDP in the Induction Step (Step 0)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Expansion of ENDP in the Induction Step (Step 0)"
  :long "<code>
 Subgoal *1/2
 (IMPLIES (AND (NOT <see topic='@(url |The Expansion of ENDP in the Induction Step (Step 1)|)'>(</see>ENDP A))
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (APP (APP A B) C)
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above (the open parenthesis before @('ENDP')) to replace
 @('(ENDP A)') by its definition.</p>")

(defxdoc |The Expansion of ENDP in the Induction Step (Step 1)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Expansion of ENDP in the Induction Step (Step 1)"
  :long "<code>
 Subgoal *1/2
 (IMPLIES (AND <see topic='@(url |The Expansion of ENDP in the Induction Step (Step 2)|)'>(</see>NOT <b>(NOT (CONSP A))</b>)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (APP (APP A B) C)
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>The <b>bold</b> text is the instantiated definition of @('ENDP').</p>

 <p>Now click on the link above to simplify (NOT (NOT (CONSP A)))</p>")

(defxdoc |The Expansion of ENDP in the Induction Step (Step 2)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Expansion of ENDP in the Induction Step (Step 2)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND <b>(CONSP A)</b>
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (APP (APP A B) C)
                 (APP A (APP B C)))).

 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Note that this is @('Subgoal *1/2'.')</p>

 <p>You may click <see topic='@(url
 |Overview of the Simplification of the Induction Step to T|)'>here</see> to
 return to the main proof.</p>")

(defxdoc |The Falling Body Model|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Falling Body Model"
  :long "<p><img src='res/tours/pisa.gif'></img></p>

 <p>One particularly famous and very simple model is the equation of a falling
 body: the distance d an object falls is proportional to the square of the time
 t.  If the time is measured in seconds and the distance in feet, the equation
 relating these two is</p>

 @({
         2
  d = 16t
 })

 <p>This equation is a <b>model</b> of falling objects.  It can be used to
 predict how long it takes a cannonball to fall from the top of a 200 foot
 tower (3.5 seconds).  This might be important if your product is designed to
 drop cannonballs on moving targets.</p>")

(defxdoc |The Final Simplification in the Base Case (Step 0)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Final Simplification in the Base Case (Step 0)"
  :long "<code>
 Subgoal *1/1'
 (IMPLIES (NOT (CONSP A))
          (EQUAL (APP <see topic='@(url |The Final Simplification in the Base Case (Step 1)|)'>(</see>APP A B) C)
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to replace @('(APP A B)') by its definition.  Note
 that the hypothesis @('(NOT (CONSP A))') allows us to simplify the @('IF') in
 @('APP') to its <b>false branch</b> this time.</p>")

(defxdoc |The Final Simplification in the Base Case (Step 1)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Final Simplification in the Base Case (Step 1)"
  :long "<code>
 Subgoal *1/1'
 (IMPLIES (NOT (CONSP A))
          (EQUAL (APP <b>B</b> C)
                 <see topic='@(url |The Final Simplification in the Base Case (Step 2)|)' use-tsee='yes'>(</see>APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to expand the definition of @('APP').  Again, we
 come out through the false branch because of the hypothesis.</p>")

(defxdoc |The Final Simplification in the Base Case (Step 2)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Final Simplification in the Base Case (Step 2)"
  :long "<code>
 Subgoal *1/1'
 (IMPLIES (NOT (CONSP A))
          <see topic='@(url |The Final Simplification in the Base Case (Step 3)|)'>(</see>EQUAL (APP B C)
                 <b>(APP B C)</b>)).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to use the Axiom @('(EQUAL x x) = t')</p>")

(defxdoc |The Final Simplification in the Base Case (Step 3)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Final Simplification in the Base Case (Step 3)"
  :long "<code>
 Subgoal *1/1'
 (IMPLIES (NOT (CONSP A))
          <b>T</b>)
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Now that its conclusion is identically @('T') the @('IMPLIES') will
 simplify to @('T') (not shown) and we are done with @('Subgoal *1/1'').</p>

 <p>You may click <see topic='@(url
 |Overview of the Simplification of the Base Case to T|)'>here</see> to return
 to the main proof.</p>")

(defxdoc |The First Application of the Associativity Rule|
  :parents (|Pages Written Especially for the Tours|)
  :short "The First Application of the Associativity Rule"
  :long "<p>So here we see our associativity rule being used!</p>

 <p>The rewriter sweeps the conjecture in a <b>leftmost innermost</b> fashion,
 applying rewrite rules as it goes.</p>

 <p>The associativity rule is used many times in this sweep.  The first
 ``target'' is highlighted below.  Click on it to see what happens:</p>

 <code>
 <b>Current Conjecture</b>:
 (equal (app (app <see topic='@(url |A Sketch of How the Rewriter Works|)'>(app (app x1 x2) (app x3 x4))</see> (app x5 x6)) x7)
        (app x1 (app (app x2 x3) (app (app x4 x5) (app x6 x7)))))
 </code>")

(defxdoc |The Induction Scheme Selected for the App Example|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Induction Scheme Selected for the App Example"
  :long "@({
  (AND
     (IMPLIES (AND (NOT (ENDP A))         ; Induction Step: test
                   (:P (CDR A) B C))      ;  and induction hypothesis
              (:P A B C))                 ;  implies induction conclusion.
     (IMPLIES (ENDP A) (:P A B C)))       ; Base Case
 })

 <p>The formula beginning with this parenthesis is the induction scheme
 suggested by @('(APP A B)') applied to @('(P A B C)').</p>

 <p>It is a <b>conjunction</b> (@(tsee AND) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>) of
 two formulas.</p>

 <p>The first is the <b>induction step</b> and the second is the <b>base
 case</b>.</p>")

(defxdoc |The Induction Step in the App Example|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Induction Step in the App Example"
  :long "<p>This formula is the <b>Induction Step</b>.  It basically consists
 of three parts, a test identifying the inductive case, an induction hypothesis
 and an induction conclusion.</p>

 <code>
 (IMPLIES (AND (NOT (ENDP A))      <b>; Test</b>
               (:P (CDR A) B C))   <b>; Induction Hypothesis</b>
          (:P A B C))              <b>; Induction Conclusion</b>
 </code>

 <p>When we prove this we can assume</p>

 <code> * @('A') is not empty, and that

   * the associativity conjecture holds for a ``smaller'' version of @('A'),
     namely, @('(CDR A)').

 </code>

 <p>Under those hypotheses we have to prove the associativity conjecture for
 @('A') itself.</p>")

(defxdoc |The Instantiation of the Induction Scheme|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Instantiation of the Induction Scheme"
  :long "<p>The induction scheme just shown is just an abbreviation for our
 real goal.</p>

 <p>To obtain our actual goals we have to replace the schema @(':P') by the
 associativity conjecture (instantiated as shown in the scheme).</p>

 <p>This produces two actual goals, the induction step and the base case.</p>")

(defxdoc |The Justification of the Induction Scheme|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Justification of the Induction Scheme"
  :long "<p>This paragraph explains why the induction selected is legal.  The
 explanation is basically the same as the explanation for why the recursion in
 @('(APP A B)') terminates.</p>")

(defxdoc |The Proof of the Associativity of App|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Proof of the Associativity of App"
  :long "<p><see topic='@(url
 |Overview of the Simplification of the Induction Step to T|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>Here is the theorem prover's output when it processes the <b>defthm</b>
 command for the associativity of @('app').  We have highlighted text for which
 we offer some explanation, and broken the presentation into several pages.
 (The most recent version of ACL2 may print slightly different output but the
 basics are the same.)  Just follow the Walking Tour after exploring the
 explanations.</p>

 <p>However, before exploring this output you should understand that ACL2 users
 rarely read successful proofs!  Instead, they look at certain subgoals printed
 in failed proofs, figure whether and how those subgoals can be proved, and
 give ACL2 directions for proving them, usually by simply proving other lemmas.
 Furthermore, to be a good user of ACL2 you do not have to understand how the
 theorem prover works.  You just have to understand how to interact with it.
 We explain this in great detail later.  But basically all new users are
 curious to know how ACL2 works and this little tour attempts to give some
 answers, just to satisfy your curiosity.</p>

 <p><img src='res/tours/green-line.gif'></img></p>

 <code>
 ACL2!&gt;<b>(defthm associativity-of-app</b>
         <b>(equal (app (app a b) c)</b>
                <b>(app a (app b c))))</b>

 Name the formula above <see topic='@(url |Name the Formula Above|)'>*1</see>.

 <see topic='@(url |Perhaps|)'>Perhaps</see> we can prove *1 by induction.  Three induction schemes are
 <see topic='@(url |Suggested Inductions in the Associativity of App Example|)'>suggested</see> by this conjecture.  <see topic='@(url |Subsumption of Induction Candidates in App Example|)'>Subsumption</see> reduces that number to two.
 However, one of these is <see topic='@(url |Flawed Induction Candidates in App Example|)'>flawed</see> and so we are left with one viable
 candidate.

 We will induct according to a scheme suggested by (APP A B).  If we
 let  (:P A B C) denote *1 above then the induction scheme we'll use
 is
 <see topic='@(url |The Induction Scheme Selected for the App Example|)'>(</see>AND
    <see topic='@(url |The Induction Step in the App Example|)'>(</see>IMPLIES (AND (NOT (ENDP A))
                  (:P (CDR A) B C))
             (:P A B C))
    <see topic='@(url |The Base Case in the App Example|)'>(</see>IMPLIES (ENDP A) (:P A B C))).
 This induction is <see topic='@(url |The Justification of the Induction Scheme|)'>justified</see> by the same argument used to admit APP,
 namely, the measure (ACL2-COUNT A) is decreasing according to the relation
 O&lt; (which is known to be well-founded on the domain recognized
 by O-P).  When <see topic='@(url |The Instantiation of the Induction Scheme|)'>applied</see> to the goal at hand the above induction
 scheme produces the following two <see topic='@(url |Nontautological Subgoals|)'>nontautological subgoals</see>.

 </code>

 <p><see topic='@(url
 |Overview of the Simplification of the Induction Step to T|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |The Q.E.D. Message|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Q.E.D. Message"
  :long "<p><b>Q.E.D.</b> stands for ``quod erat demonstrandum'' which is Latin
 for ``which was to be demonstrated'' and is the signal that a proof is
 completely done.</p>")

(defxdoc |The Rules used in the Associativity of App Proof|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Rules used in the Associativity of App Proof"
  :long "<p>Note that under <b>Rules</b> we list the <see topic='@(url
 RUNE)'>runes</see> <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> of all the rules used in the proof.  This list says
 that we used the rewrite rules @('CAR-CONS') and @('CDR-CONS'), the
 definitions of the functions @('NOT'), @('ENDP') and @('APP'), and primitive
 type reasoning (which is how we simplified the @('IF') and @('EQUAL')
 terms).</p>

 <p>For what it is worth, @('IMPLIES') and @('AND') are actually <see
 topic='@(url DEFMACRO)'>macros</see> <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 that are expanded into @('IF') expressions before the proof ever begins.  The
 use of macros is not reported among the rules.</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 0)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 0)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (APP <see topic='@(url |The Simplification of the Induction Conclusion (Step 1)|)'>(</see>APP A B) C)
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to replace @('(APP A B)') by its definition.</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 1)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 1)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (APP <b>(IF </b><see topic='@(url |The Simplification of the Induction Conclusion (Step 2)|)'>(</see><b>CONSP A)</b>
                          <b>(CONS (CAR A) (APP (CDR A) B))</b>
                          <b>B)</b>
                      C)
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Note that the @('IF') expression above is the simplified body of @('APP').
 But we know the test @('(CONSP A)') is true, by the first hypothesis.  Click
 on the link above to replace the test by @('T').  Actually this step and
 several subsequent ones are done during the simplification of the body of
 @('APP') but we want to illustrate the basic principles of simplification
 without bothering with every detail.</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 10)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 10)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          <see topic='@(url |The Simplification of the Induction Conclusion (Step 11)|)'>(</see><b>EQUAL (APP (APP (CDR A) B) C)</b>
                 <b>(APP (CDR A) (APP B C)))</b>).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to use the Induction Hypothesis (which is the
 second of the two hypotheses above and which is identical to the rewritten
 conclusion).</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 11)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 11)"
  :long "<code>
 Subgoal *1/2'
 <see topic='@(url |The Simplification of the Induction Conclusion (Step 12)|)'>(</see>IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          <b>T</b>)
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to use the definition of @('IMPLIES').  Since the
 conclusion of the implication is now identically @('T'), the implication
 simplifies to @('T').</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 12)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 12)"
  :long "<code>
 Subgoal *1/2'
 <b>T</b>
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>So, indeed, @('Subgoal *1/2'') <b>does</b> simplify to T!</p>

 <p>You can see that even in an example as simple as this one, quite a lot
 happens in simplification.</p>

 <p>You may click <see topic='@(url
 |Overview of the Simplification of the Induction Step to T|)'>here</see> to
 return to the main proof.</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 2)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 2)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (APP <see topic='@(url |The Simplification of the Induction Conclusion (Step 3)|)'>(</see>IF <b>T</b>
                          (CONS (CAR A) (APP (CDR A) B))
                          B)
                      C)
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to apply the Axiom @('(IF T x y) = x').</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 3)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 3)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL <see topic='@(url |The Simplification of the Induction Conclusion (Step 4)|)'>(</see>APP <b>(CONS (CAR A) (APP (CDR A) B))</b>
                      C)
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to expand the definition of @('APP') here.</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 4)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 4)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (IF <see topic='@(url |The Simplification of the Induction Conclusion (Step 5)|)'>(</see><b>CONSP (CONS (CAR A) (APP (CDR A) B)))</b>
                     <b>(CONS (CAR (CONS (CAR A) (APP (CDR A) B)))</b>
                           <b>(APP (CDR (CONS (CAR A) (APP (CDR A) B)))</b>
                                <b>C))</b>
                     <b>C)</b>
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to apply the Axiom @('(CONSP (CONS x y)) =
 T').</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 5)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 5)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (IF <b>T</b>
                     (CONS <see topic='@(url |The Simplification of the Induction Conclusion (Step 6)|)'>(</see>CAR (CONS (CAR A) (APP (CDR A) B)))
                           (APP (CDR (CONS (CAR A) (APP (CDR A) B)))
                                C))
                     C)
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to apply the Axiom @('(CAR (CONS x y)) = x').</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 6)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 6)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL (IF T
                     (CONS <b>(CAR A)</b>
                           (APP <see topic='@(url |The Simplification of the Induction Conclusion (Step 7)|)'>(</see>CDR (CONS (CAR A) (APP (CDR A) B)))
                                C))
                     C)
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to apply the Axiom @('(CDR (CONS x y)) = y').</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 7)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 7)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL <see topic='@(url |The Simplification of the Induction Conclusion (Step 8)|)'>(</see>IF T
                     (CONS (CAR A)
                           (APP <b>(APP (CDR A) B)</b>
                                C))
                     C)
                 (APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to apply the Axiom @('(IF T x y) = x').</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 8)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 8)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          (EQUAL <b>(CONS (CAR A)</b>
                       <b>(APP (APP (CDR A) B)</b>
                            <b>C))</b>
                 <see topic='@(url |The Simplification of the Induction Conclusion (Step 9)|)'>(</see>APP A (APP B C)))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to expand the definition of @('APP') here.  This
 time, we'll do the whole expansion at once, including the simplification of
 the resulting @('IF').  This is how ACL2 actually does it.</p>")

(defxdoc |The Simplification of the Induction Conclusion (Step 9)|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Simplification of the Induction Conclusion (Step 9)"
  :long "<code>
 Subgoal *1/2'
 (IMPLIES (AND (CONSP A)
               (EQUAL (APP (APP (CDR A) B) C)
                      (APP (CDR A) (APP B C))))
          <see topic='@(url |The Simplification of the Induction Conclusion (Step 10)|)'>(</see>EQUAL (CONS (CAR A)
                       (APP (APP (CDR A) B)
                            C))
                 <b>(CONS (CAR A)</b>
                       <b>(APP (CDR A) (APP B C))</b>))).
 </code>

 <p><img src='res/tours/green-line.gif'></img></p>

 <p>Click on the link above to apply the Axiom that @('(EQUAL (CONS x y) (CONS
 u v))') is equal to the conjunction of @('(EQUAL x u)') and @('(EQUAL y v)').
 In this case, @('(EQUAL x u)') is trivial, @('(EQUAL (CAR A) (CAR A))').</p>")

(defxdoc |The Summary of the Proof of the Trivial Consequence|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Summary of the Proof of the Trivial Consequence"
  :long "<p>Note that at the conclusion of the proof, the system reminds you of
 the earlier <b>Warning</b>.</p>

 <p>It is a good idea, when the <b>Q.E.D.</b> flies by, to see if there were any
 Warnings.</p>")

(defxdoc |The Theorem that App is Associative|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Theorem that App is Associative"
  :long "<p><see topic='@(url |The Proof of the Associativity of App|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <code>
 ACL2!&gt;<b>(defthm associativity-of-app</b>
         <b>(equal (app (app a b) c)</b>
                <b>(app a (app b c))))</b>
 </code>

 <p>The formula above says @('app') is associative.  The @(tsee defthm) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 command instructs ACL2 to prove the formula and to name it
 @('associativity-of-app').  Actually, the @('defthm') command also builds the
 formula into the database as a @(tsee rewrite) <see
 topic='ACL2____A_02Tiny_02Warning_02Sign'><icon src='res/tours/twarning.gif'/></see>
 rule, but we won't go into that just yet.</p>

 <p>What we will consider is how the ACL2 theorem prover proves this
 formula.</p>

 <p>If you proceed you will find the actual output of ACL2 in response to the
 command above.  Some of the text is highlighted for the purposes of the tour.
 ACL2 does not highlight its output.</p>

 <p>You will note that we sometimes highlight a single open parenthesis.  This
 is our way of drawing your attention to the subformula that begins with that
 parenthesis.  By clicking on the parenthesis you will get an explanation of
 the subformula or its processing.</p>

 <p><see topic='@(url |The Proof of the Associativity of App|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc |The Time Taken to do the Associativity of App Proof|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Time Taken to do the Associativity of App Proof"
  :long "<p>The time it took us to explain this proof may leave the impression
 that the proof is complicated.  In a way, it is.  But it happens quickly.</p>

 <p>The time taken to do this proof is about 1/10 second.  The rest of the time
 (about 2/10 seconds) is spent in pre- and post-processing.</p>

 <p>Basically, this proof flashes across your screen before you can read it;
 you see the <b>Q.E.D.</b> and don't bother to scroll back to read it.  You
 have more important things to do than read successful proofs.</p>")

(defxdoc |The Tours|
  :parents (|Pages Written Especially for the Tours|)
  :short "The Tours"
  :long "<p>ACL2 is a very large, multipurpose system.  You can use it as a
 programming language, a specification language, a modeling language, a formal
 mathematical logic, or a semi-automatic theorem prover, just to name its most
 common uses.  It has been used on a number of <see topic='@(url
 INTERESTING-APPLICATIONS)'>industrial applications</see>.  If you're uncertain
 as to whether your project is appropriate for ACL2 we urge you to look over
 this list or contact the ACL2 developers.</p>

 <p>This home page includes all of ACL2's online documentation, which is quite
 extensive (over 4 megabytes).  To help ease your introduction to ACL2, we have
 built two tours through this documentation.</p>

 <p>If you are familiar with at least some of the <see topic='@(url
 INTERESTING-APPLICATIONS)'>industrial applications</see> of ACL2, then you
 will understand the distance between the simple examples we talk about in
 these tours and the kinds of things ACL2 users do with the system.</p>

 <p>Newcomers to ACL2 should first take the ``Flying Tour.''  Then, if you want
 to know more, take the ``Walking Tour.''  On your first reading, follow the
 two Tours linearly, clicking only on the icon of the Tour you're on.  Beware
 of other links, which might jump you from one tour to the other or into the
 ACL2 User's Manual!  Once you've had a coherent overview of the system, you
 might quickly repeat both Tours to see if there are unvisited links you're
 interested in, using your browser's Back Button to return to your starting
 points.</p>

 <p>If after all this you want to learn how to use the theorem prover (!), see
 @(see introduction-to-the-theorem-prover).</p>

 <p>To start a tour, click on the appropriate icon below.</p>

 <p><see topic='@(url |A Flying Tour of ACL2|)'><img
 src='res/tours/flying.gif'></img></see> <see topic='@(url
 |A Walking Tour of ACL2|)'><img src='res/tours/walking.gif'></img></see></p>

 <p>If you take the tours in a text-based format (such as using the :DOC
 command in Emacs), they will probably be unsatisfying because we use gif files
 and assume you can navigate ``back.''</p>")

(defxdoc |The WARNING about the Trivial Consequence|
  :parents (|Pages Written Especially for the Tours|)
  :short "The WARNING about the Trivial Consequence"
  :long "<p>This <b>Warning</b> alerts us to the fact that when treated as a
 <b>rewrite</b> rule, the new rule @('TRIVIAL-CONSEQUENCE'), rewrites terms of
 the same form as a rule we have already proved, namely
 @('ASSOCIATIVITY-OF-APP').</p>

 <p>When you see this warning you should <b>think about your rules</b>!</p>

 <p>In the current case, it would be a good idea <b>not</b> to make
 @('TRIVIAL-CONSEQUENCE') a rule at all.  We could do this with @(':')@(tsee
 rule-classes) <see topic='ACL2____A_02Tiny_02Warning_02Sign'><icon
 src='res/tours/twarning.gif'/></see> nil.</p>

 <p>ACL2 proceeds to try to prove the theorem, even though it printed some
 warnings.  The basic assumption in ACL2 is that the <b>user</b> <b>understands
 what he or she is doing</b> but may need a little reminding just to manage a
 complicated set of facts.</p>")

(defxdoc u
  :parents (history undo)
  :short "Undo last @(see command), without a query"
  :long "<p>See @(see undo) for an introduction to undoing commands.</p>

 @({
  Example:
  :u
 })

 <p>The keyword @(see command) @(':u') is the same as @(':')@(tsee ubt!)
 @(':x').  @(':')@(tsee Oops) will undo the last @(':u').  See @(see
 ubt!).</p>")

(defxdoc ubt
  :parents (history undo)
  :short "Undo the @(see command)s back through a @(see command) descriptor"
  :long "<p>See @(see undo) for an introduction to undoing commands.</p>

 @({
  Examples:
  :ubt :max      ; undo back through the most recent command
                 ; (which just means undo the most recent command)
  :ubt :x        ; same as :ubt :max
  :u             ; same as :ubt :max with no questions asked
  :ubt fn        ; undo back through the introduction of fn
                 ; (including all the other events in fn's block)
  :ubt 5         ; undo back through the fifth command executed
  :ubt (:max -4) ; undo back through the most recent five commands
  :ubt (:x -4)   ; undo back through the most recent five commands
 })

 <p>See @(see command-descriptor).</p>

 <p>@('Ubt') takes one argument, a @(see command) descriptor, and undoes the
 @(see command)s from @(':')@(tsee max) (aka @(':x')) through the one
 described.  See @(see command-descriptor).  @(tsee Pbt) will print the @(see
 command)s that @('ubt') will undo.  @(':')@(tsee Oops) will undo the undo.
 See @(see oops).</p>

 <p>@('Ubt') can cause errors but not queries.  To get queries as well, see
 @(see ubt?).  To get neither errors nor queries, see @(see ubt!)..</p>

 <p>It is important to remember that a @(see command) may create several @(see
 events).  That is, the @(see command) that introduces @('fn1') may also
 introduce @('fn2').  Undoing the @(see command) that created either of these
 will undo them both.  The @(see events) created by a @(see command) constitute
 the @(see command)'s ``block'' and we can only undo entire blocks.  Use @(tsee
 pcb) to print the @(see command) block of a @(see command) if you wish to see
 what will be lost by undoing the @(see command).</p>

 <p>@('Ubt') will not undo into ``prehistory''.  @(':Ubt 1') will undo all of
 your @(see command)s.  But @(':ubt -5') will cause an error, warning you that
 @(':ubt') cannot undo system initialization.</p>

 <p>See @(see u) for how to undo just the latest command.  See @(see ubu),
 @(see ubu!), and @(see ubu?) for how to undo back up to, but not including,
 the current command.</p>")

(defxdoc ubt!
  :parents (history undo)
  :short "Undo @(see command)s, without a query or an error"
  :long "<p>See @(see undo) for an introduction to undoing commands.</p>

 @({
  Example:
  :ubt! :x-4
 })

 <p>The keyword @(see command) @(':ubt!') is the same as @(':')@(tsee ubt), but
 with a guarantee that it is ``error-free.''  More precisely, the value
 returned by @(':ubt!')  will always be of the form @('(mv nil val state)').
 @(':')@(tsee Oops) will undo the last @(':ubt!').  See @(see ubt), @(see
 ubt?), @(see ubu!), @(see ubu), @(see ubu?), and @(see u).</p>")

(defxdoc ubt?
  :parents (history undo)
  :short "Undo @(see command)s, with queries as appropriate"
  :long "<p>See @(see undo) for an introduction to undoing commands.</p>

 @({
  Example:
  :ubt? :x-4
 })

 <p>The keyword @(see command) @(':ubt?') is the same as @(':')@(tsee ubt), but
 with appropriate queries made.  @(':')@(tsee Oops) will undo the last
 @(':ubt?').  See @(see ubt!), @(see ubt), @(see ubu!), @(see ubu), @(see
 ubu?), and @(see u).</p>")

(defxdoc ubt-prehistory
  :parents (history undo)
  :short "Undo the @(see command)s back through the last @(tsee reset-prehistory) event"
  :long "<p>See @(see undo) for an introduction to undoing commands.</p>

 <p>This command is only used to eliminate a @(tsee reset-prehistory) event.
 If your most recent @('reset-prehistory') event does not have a flag argument
 of @('t'), then @(':ubt-prehistory') undoes all command back through, and
 including, that @('reset-prehistory') event.</p>")

(defxdoc ubu
  :parents (history undo)
  :short "Undo the @(see command)s back up to (not including) a @(see command) descriptor"
  :long "<p>See @(see undo) for an introduction to undoing commands.</p>

 @({
  Examples:
  :ubu :x-3      ; undo the last three commands (same as :ubt :x-2)
  :ubu (:x -3)   ; same as above
  :ubu fn        ; undo back up to, but not including the introduction of fn
                 ; (so fn will continue to be defined)
  :ubu 5         ; undo back up to, but not including, the fifth command
                 ; executed (leaving the first five commands in place)
 })

 <p>See @(see command-descriptor).</p>

 <p>@('Ubu') takes one argument, a @(see command) descriptor, and undoes the
 @(see command)s from @(':')@(tsee max) (aka @(':x')) up to, but not including,
 the indicated command.  See @(see command-descriptor).</p>

 <p>@('Ubu') can cause errors.  To avoid these, see @(see ubu!).</p>

 <p>For appropriate queries to be made, see @(see ubu?).</p>

 <p>Also see @(see ubt), which is similar but also undoes the indicated
 command.  As for @(':')@(tsee ubt), @(':')@(tsee oops) will undo the undo (see
 @(see oops)) and @(tsee ubu) will not undo into ``prehistory''.</p>

 <p>See @(see u) for how to undo just the latest command, and see @(see ubt),
 @(see ubt!), and @(see ubt?) for how to undo back through (that is, including)
 the current command.</p>")

(defxdoc ubu!
  :parents (history undo)
  :short "Undo @(see command)s, without a query or an error"
  :long "<p>See @(see undo) for an introduction to undoing commands.</p>

 @({
  Example:
  :ubu! :x-4
 })

 <p>The keyword @(see command) @(':ubu!') is the same as @(':')@(tsee ubu), but
 with a guarantee that it is ``error-free.''  More precisely, the @(see
 error-triple) returned by @(':ubu!')  will always be of the form @('(mv nil
 val state)').  @(':')@(tsee Oops) will undo the last @(':ubu!').  Also see
 @(see ubu), @(see ubu?), @(see ubt), @(see ubt!), @(see ubt?), and @(see
 u).</p>")

(defxdoc ubu?
  :parents (history undo)
  :short "Undo @(see command)s, with queries as appropriate"
  :long "<p>See @(see undo) for an introduction to undoing commands.</p>

 @({
  Example:
  :ubu? :x-4
 })

 <p>The keyword @(see command) @(':ubu?') is the same as @(':')@(tsee ubu), but
 with appropriate queries made.  @(':')@(tsee Oops) will undo the last
 @(':ubu?').  Also see @(see ubu!), @(see ubu), @(see ubt!), @(see ubt), @(see
 ubt?), and @(see u).</p>")

(defxdoc unary--
  :parents (numbers acl2-built-ins)
  :short "Arithmetic negation function"
  :long "<p>Completion Axiom (@('completion-of-unary-minus')):</p>

 @({
  (equal (unary-- x)
         (if (acl2-numberp x)
             (unary-- x)
           0))
 })

 <p>@(see Guard) for @('(unary-- x)'):</p>

 @({
  (acl2-numberp x)
 })

 <p>Notice that like all arithmetic functions, @('unary--') treats non-numeric
 inputs as @('0').</p>

 <p>Calls of the macro @(tsee -) on one argument expand to calls of
 @('unary--'); see @(see -).</p>")

(defxdoc unary-/
  :parents (numbers acl2-built-ins)
  :short "Reciprocal function"
  :long "<p>Completion Axiom (@('completion-of-unary-/')):</p>

 @({
  (equal (unary-/ x)
         (if (and (acl2-numberp x)
                  (not (equal x 0)))
             (unary-/ x)
           0))
 })

 <p>@(see Guard) for @('(unary-/ x)'):</p>

 @({
  (and (acl2-numberp x)
       (not (equal x 0)))
 })

 <p>Notice that like all arithmetic functions, @('unary-/') treats non-numeric
 inputs as @('0').</p>

 <p>Calls of the macro @(tsee /) on one argument expand to calls of
 @('unary-/'); see @(see /).</p>")

(defxdoc uncertified-books
  :parents (books)
  :short "Invalid @(see certificate)s and uncertified @(see books)"
  :long "<p>For relevant background see @(see books), see @(see certificate),
 and see @(see portcullis).</p>

 <p>@(tsee Include-book) has a special provision for dealing with an
 uncertified book, i.e., a file with no @(see certificate) or an invalid @(see
 certificate) (i.e., one whose @(see book-hash) values describe files other
 than the ones actually read).  In this case, a warning is printed and the book
 is otherwise processed much as though it were certified and had an open @(see
 portcullis).</p>

 <p>If a book @('B.lisp') is uncertified and a file @('B.port') exists, then
 the forms in @('B.port') are evaluated before the forms in @('B.lisp').  Such
 a file @('B.port') is typically created calling @(tsee certify-book) on book
 @('\"B\"') with argument @(':write-port t'), so that @('B.port') contains the
 @(see portcullis) @(see command)s for @('B') (the commands present in the
 @(see world) when that certification was attempted).  To avoid loading
 @('.port') files, see @(see compilation).</p>

 <p>Inclusion of uncertified books can be handy, but it can have disastrous
 consequences.</p>

 <p>The provision allowing uncertified @(see books) to be included can have
 disastrous consequences, ranging from hard lisp errors, to damaged memory, to
 quiet logical inconsistency.</p>

 <p>It is possible for the inclusion of an uncertified book to render the logic
 inconsistent.  For example, one of its non-@(tsee local) @(see events) might
 be @('(defthm t-is-nil (equal t nil))').  It is also possible for the
 inclusion of an uncertified book to cause hard errors or @(see breaks) into
 raw Common Lisp.  For example, if the file has been edited since it was
 certified, it may contain too many open parentheses, causing Lisp to read past
 ``end of file.'' Similarly, it might contain non-ACL2 objects such as
 @('3.1415') or ill-formed event forms that cause ACL2 code to break.</p>

 <p>Even if a book is perfectly well formed and could be certified (in a
 suitable extension of ACL2's initial @(see world)), its uncertified inclusion
 might cause Lisp errors or inconsistencies!  For example, it might mention
 packages that do not exist in the host @(see world), especially if the
 @('.port') file (discussed above) does not exist from an earlier certification
 attempt.  The @(see portcullis) of a certified book ensures that the correct
 @(tsee defpkg)s have been admitted, but if a book is read without actually
 raising its @(see portcullis), symbols in the file, e.g.,
 @('acl2-arithmetic::fn'), could cause ``unknown package'' errors in Common
 Lisp.  Perhaps the most subtle disaster occurs if the host @(see world) does
 have a @(tsee defpkg) for each package used in the book but the host @(tsee
 defpkg) imports different symbols than those required by the @(see
 portcullis).  In this case, it is possible that formulas which were theorems
 in the certified book are non-theorems in the host @(see world), but those
 formulas can be read without error and will then be quietly assumed.</p>

 <p>In short, if you include an uncertified book, <b>all bets are off</b>
 regarding the validity of the future behavior of ACL2.</p>

 <p>That said, it should be noted that ACL2 is pretty tough and if errors don't
 occur, the chances are that deductions after the inclusion of an uncertified
 book are probably justified in the (possibly inconsistent) logical extension
 obtained by assuming the admissibility and validity of the definitions and
 conjectures in the book.</p>")

(defxdoc undo
  :parents (history)
  :short "Undoing and perhaps redefining"
  :long "<p>This topic provides a high-level view of how one can undo a
 definition, perhaps replacing it with a new definition.  We begin with some
 background.</p>

 <p>ACL2 maintains a stack of @(see command)s.  For example, suppose we submit
 the following @(see events) in a new session.</p>

 @({
 (defun f (x) x)
 (defun g (x) (* x x))
 (defthm f^2-is-g
   (equal (expt (f x) 2) (g x))
   :hints ((\"Goal\" :expand ((expt x 2)))))
 })

 <p>Then we can see the stack of commands by using @(':')@(tsee pcb) (``Print
 Command Block'') back to command 0, that is back to the start.</p>

 @({
 ACL2 !>:pbt 0
            0  (EXIT-BOOT-STRAP-MODE)
  L         1  (DEFUN F (X) ...)
  L         2  (DEFUN G (X) ...)
            3:x(DEFTHM F^2-IS-G ...)
 ACL2 !>
 })

 <p>Now suppose that we want to redefine @('g').  The cleanest, safest way is
 to unwind the stack with @(':')@(tsee ubt) (``Undo Back Through'') all the way
 back through (and including) @('g').</p>

 @({
 ACL2 !>:ubt g
  L         1:x(DEFUN F (X) ...)
 ACL2 !>:pbt 0
            0  (EXIT-BOOT-STRAP-MODE)
  L         1:x(DEFUN F (X) ...)
 ACL2 !>
 })

 <p>Now we can define @('g') again and proceed from there.</p>

 @({
 ACL2 !>(defun g (x) (expt x 2))
 [[.. output omitted here ..]]
  G
 ACL2 !>:pbt 0
            0  (EXIT-BOOT-STRAP-MODE)
  L         1  (DEFUN F (X) ...)
  L         2:x(DEFUN G (X) ...)
 ACL2 !>(defthm f^2-is-g
          (equal (expt (f x) 2) (g x)))
 [[.. output omitted here ..]]
  F^2-IS-G
 ACL2 !>:pbt 0
            0  (EXIT-BOOT-STRAP-MODE)
  L         1  (DEFUN F (X) ...)
  L         2  (DEFUN G (X) ...)
            3:x(DEFTHM F^2-IS-G ...)
 ACL2 !>
 })

 <p>See @(see ubt) for more information, including variants such as @(':u'),
 which undoes a single command (the most recent one).  Also see @(see oops) for
 how to undo an undo.</p>

 <p>It can occasionally be inconvenient to undo a large number of commands when
 one's goal is only to redefine a single function.  In such cases one might
 wish to enable redefinition, even though it can be unsafe.  Here is an
 example (admittedly contrived) for how to continue the session above.  Note
 that there are variants of @(':redef') &mdash; see @(see redef) &mdash; for
 example to avoid the query shown below and answered with `@('y')'.</p>

 @({
 ACL2 !>:redef
  (:QUERY . :OVERWRITE)
 ACL2 !>(defun f (x) (+ 10 x))

 ACL2 Query (:REDEF):  The name F is in use as a function.  Its current
 defun-mode is :logic. Do you want to redefine it?  (N, Y, E, O or ?):
 y

 Since F is non-recursive, its admission is trivial.  We observe that
 the type of F is described by the theorem (ACL2-NUMBERP (F X)).  We
 used primitive type reasoning.

 Summary
 Form:  ( DEFUN F ...)
 Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
 Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
  F
 ACL2 !>:pbt 0
            0  (EXIT-BOOT-STRAP-MODE)
  L         1  (DEFUN F (X) ...)
  L         2  (DEFUN G (X) ...)
            3  (DEFTHM F^2-IS-G ...)
  L         4:x(DEFUN F (X) ...)
 ACL2 !>
 })

 <p>Notice that the ``theorem'' @('f^2-is-g') is still in our session, even
 though it is no longer valid now that @('f') has been redefined.  This shows
 one reason we say that redefinition can be unsafe; it can be unsound!  Other
 possible dangers include execution errors and ignoring, in existing
 definitions, redefinitions of constants and macros.  Thus, undoing (and then
 redoing) is generally preferable to redefinition.  Indeed, redefinition is
 disallowed in @(see books).</p>

 <p>You can inspect both commands that introduce a definition for @('f') with
 @(':pcb') (``Print Command Block'' in full; see @(see pcb)).</p>

 @({
 ACL2 !>:pcb! 1
  L         1  (DEFUN F (X) X)
 ACL2 !>:pcb! 3
  L         3:x(DEFUN F (X) (CAR (CONS X X)))
 ACL2 !>
 })")

(defxdoc union$
  :parents (lists acl2-built-ins)
  :short "A list that contains exactly the elements of the given lists"
  :long "@({
  General Forms:
  (union$ l1 l2 ... lk)
  (union$ l1 l2 ... lk :test 'eql) ; same as above
  (union$ l1 l2 ... lk :test 'eq)    ; same, but eq is equality test
  (union$ l1 l2 ... lk :test 'equal) ; same, but equal is equality test
 })

 <p>@('(Union$ x y)') equals a list that contains both the members of @('x')
 and the members of @('y').  More precisely, the resulting list is the same as
 one would get by first deleting the members of @('y') from @('x'), and then
 concatenating the result to the front of @('y').  The optional keyword,
 @(':TEST'), has no effect logically, but provides the test (default @(tsee
 eql)) used for comparing members of the two lists.</p>

 <p>@('Union$') need not take exactly two arguments: @('(union$)') is @('nil'),
 @('(union$ x)') is @('x'), @('(union$ x y z ... :test test)') is @('(union$ x
 (union$ y z ... :test test) :test test)'), and if @(':TEST') is not supplied,
 then @('(union$ x y z ...)') is @('(union$ x (union$ y z ...))').  For the
 discussion below we restrict ourselves, then, to the cases @('(union$ x y)')
 and @('(union$ x y :test test)').</p>

 <p>The @(see guard) for a call of @('union$') (in the two cases just above)
 depends on the test.  In all cases, both arguments must satisfy @(tsee
 true-listp).  If the test is @(tsee eql), then one of the arguments must
 satisfy @(tsee eqlable-listp).  If the test is @(tsee eq), then one of the
 arguments must satisfy @(tsee symbol-listp).</p>

 <p>See @(see equality-variants) for a discussion of the relation between
 @('union$') and its variants:</p>

 <blockquote><p>@('(union-eq x lst)') is equivalent to @('(union$ x lst :test
 'eq)');</p>

 <p>@('(union-equal x lst)') is equivalent to @('(union$ x lst :test
 'equal)').</p></blockquote>

 <p>In particular, reasoning about any of these primitives reduces to reasoning
 about the function @('union-equal').</p>

 @(def union-equal)

 <p>Note that @('union-eq') can take any number of arguments, in analogy to
 @('union$'); indeed, @('(union-eq ...)') expands to @('(union$ ... :test
 'eq)').  However, @('union-equal') is a function, not a macro, and takes
 exactly two arguments.</p>

 <p>@('Union$') is similar to the Common Lisp primitive @('union').  However,
 Common Lisp does not specify the order of elements in the result of a call of
 @('union').</p>")

(defxdoc union-theories
  :parents (theories theory-functions)
  :short "Union two @(see theories)"
  :long "@({
  Example:
  (union-theories (current-theory 'lemma3)
                  (theory 'arith-patch))

  General Form:
  (union-theories th1 th2)
 })

 <p>where @('th1') and @('th2') are theories (see @(see theories)).  To each of
 the arguments there corresponds a runic theory.  This function returns the
 union of those two runic @(see theories), represented as a list and ordered
 chronologically.</p>

 <p>This ``function'' is actually a macro that expands to a term mentioning the
 single free variable @(tsee world).  When theory expressions are evaluated by
 @(tsee in-theory) or the @(':')@(tsee in-theory) hint, @(tsee world) is bound
 to the current ACL2 @(see world).</p>")

(defxdoc universal-theory
  :parents (theories theory-functions)
  :short "All rules as of logical name"
  :long "@({
  Examples:
  (universal-theory :here)
  (universal-theory 'lemma3)
 })

 <p>See @(see logical-name).</p>

 @({
  General Form:
  (universal-theory logical-name)
 })

 <p>Returns the theory consisting of all the @(see rune)s that existed
 immediately after @(tsee logical-name) was introduced.  See @(see theories)
 and see @(see logical-name).  The theory includes @(tsee logical-name) itself
 (if there is a rule by that name).  (Note that since some @(see events) do not
 introduce rules (e.g., @(tsee defmacro), @(tsee defconst) or @(tsee defthm)
 with @(':')@(tsee rule-classes) @('nil')), the universal-theory does not
 necessarily include a @(see rune) for every event name.)  The universal-theory
 is very long and you will probably regret printing it.</p>

 <p>You may experience a fencepost problem in deciding which @(see
 logical-name) to use.  @(tsee Deflabel) can always be used to mark
 unambiguously for future reference a particular point in the development of
 your theory.  This is convenient because @(tsee deflabel) does not introduce
 any rules and hence it doesn't matter if you count it as being in the interval
 or not.  The order of @(see events) in the vicinity of an @(tsee encapsulate)
 is confusing.  See @(see encapsulate).</p>

 <p>This ``function'' is actually a macro that expands to a term mentioning the
 single free variable @(tsee world).  When theory expressions are evaluated by
 @(tsee in-theory) or the @(':')@(tsee in-theory) hint, @(tsee world) is bound
 to the current ACL2 @(see world).</p>

 <p>Also see @(see current-theory).  @('Current-theory') is much more commonly
 used than @('universal-theory').  The former includes only the @(see enable)d
 @(see rune)s as of the given @(tsee logical-name), which is probably what you
 want, while the latter includes @(see disable)d ones as well.</p>")

(defxdoc unmemoize
  :parents (memoize programming hons-and-memoization events)
  :short "Turn off memoization for the specified function"
  :long "@({
  Example:
  (unmemoize 'foo) ; turn off memoization of foo

  General Form:
  (unmemoize fn)
 })

 <p>where @('fn') evaluates to a function symbol that is currently memoized;
 see @(see memoize).  An exception is that as with @(tsee memoize), @('fn') may
 evaluate to the name of a macro that is associated with such a function
 symbol; see @(see macro-aliases-table).</p>

 <p>Calls of this macro generate events of the form @('(table memoize-table fn
 nil)').  When successful, the returned value is of the form @('(mv nil
 function-symbol state)').</p>

 <p>To remove the effects of all @(tsee memoize) @(see events), evaluate:
 @('(clear-memo-table)').  To save and restore memoization, see @(see
 save-and-clear-memoization-settings) and see @(see
 restore-memoization-settings).</p>")

(defxdoc unmonitor
  :parents (break-rewrite)
  :short "To stop monitoring a rule name"
  :long "@({
  Examples:
  (unmonitor '(:rewrite assoc-of-app))
  :unmonitor (:rewrite assoc-of-app)
  :unmonitor :all

  General Forms:
  (unmonitor rune)
  (unmonitor :all)
 })

 <p>Here, @('rune') is a @(see rune) that is currently among those with break
 points installed.  This function removes the break.</p>

 <p>Subtle point: Because you may want to unmonitor a ``@(see rune)'' that is
 no longer a @(see rune) in the current ACL2 @(see world), we don't actually
 check this about @(see rune).  Instead, we simply check that @(see rune) is a
 @('consp') beginning with a @('keywordp').  That way, you'll know you've made
 a mistake if you try to @(':unmonitor binary-append') instead of @(':unmonitor
 (:definition binary-append)'), for example.</p>")

(defxdoc unquote
  :parents (quote acl2-built-ins)
  :short "Obtain the object being quoted"
  :long "<p>@('Unquote') is just an abbreviation for @(tsee cadr).  Its
 intended use is to obtain an object being quoted.  For example, if @('x') is
 @('(quote (3 4))') then @('(unquote x)') is @('(3 4)'):</p>

 @({
 ACL2 !>(let ((x '(quote (3 4))))
          (unquote x))
 (3 4)
 ACL2 !>
 })")

(defxdoc unsave
  :parents (proof-builder)
  :short "Remove a @(see proof-builder) state"
  :long "@({
  Example:
  (unsave assoc-of-append)

  General Form:
  (unsave name)
 })

 <p>Eliminates the association of an interactive @(see proof-builder) state
 with @('name').  See @(see unsave) or see @(see acl2-pc::unsave).</p>

 <p>Also see @(see acl2-pc::save) and see @(see retrieve).</p>")

(defxdoc unsigned-byte-p
  :parents (numbers acl2-built-ins)
  :short "Recognizer for natural numbers that fit in a specified bit width"
  :long "<p>@('(Unsigned-byte-p bits x)') is @('T') when @('bits') is a
 positive integer and @('x') is a nonnegative integer that fits into a
 bit-width of @('bits'), i.e., @('0 <= x < 2^bits').</p>

 <p>Note that a @(see type-spec) of @('(unsigned-byte i)') for a variable
 @('x') in a function's @(tsee declare) form translates to a @(see guard)
 condition of @('(unsigned-byte-p i x)').</p>

 <p>The @(see guard) for @('unsigned-byte-p') is @('T').</p>

 @(def unsigned-byte-p)")

(defxdoc unsupported-parallelism-features
  :parents (parallelism)
  :short "ACL2 features not supported in ACL2(p)"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).  See @(see parallelism-tutorial) for an introduction to parallel
 programming in ACL2.</p>

 <p>For proof features of ACL2 that are not yet supported when parallel
 execution is enabled for the primary ACL2 proof process, generally known as
 ``the waterfall'', see @(see unsupported-waterfall-parallelism-features).</p>

 <p>Please note that this topic discusses ACL2 features that are disabled when
 using ACL2(p) (see @(see compiling-acl2p)).  These features are disabled
 regardless of whether waterfall parallelism is enabled.</p>

 <p>Calls of @(tsee observation-cw) simply convert to calls of @(tsee cw), so
 suppressing @(tsee observation)s (see @(see set-inhibit-output-lst)) will not
 suppress these messages.</p>

 <p>Memoization is not supported when executing in parallel.  See @(see
 Unsupported-waterfall-parallelism-features) for memoization details related to
 waterfall parallelism.</p>

 <p>Since, as of April 2012, garbage collection is inherently sequential,
 ACL2(p) minimizes the use of garbage collection by setting a high garbage
 collection threshold.  As a result, ACL2(p) is not expected to perform well on
 machines with less memory than this threshold (1 gigabyte, as of April
 2012).</p>

 <p>In CCL, the underlying parallel execution engine is tuned for the number of
 CPU cores (or hardware threads) actually available in the machine.  SBCL and
 LispWorks are tuned for a machine with 16 CPU cores.</p>

 <p>CCL is considered to be the ``flagship Lisp'' for parallel execution in
 ACL2.  The SBCL and LispWorks implementations are thought to be generally
 stable.  However, due to their relatively less common use, the SBCL and
 LispWorks implementations are likely less robust than the CCL
 implementation.</p>

 <p>The @(tsee time-tracker) utility is a no-op for ACL2(p).</p>")

(defxdoc unsupported-waterfall-parallelism-features

; For a discussion of the wormhole issue referenced in the :doc string below,
; see ACL2 source function waterfall-print-clause-id@par.

; Parallelism no-fix: the problem below related to interrupts is potentially
; somewhat serious, but probably quite rare.  Moreover, it seems potentially
; quite difficult to fix, as it would likely involve multi-threaded Lisp issues
; as well as acl2-unwind-protect issues.

  :parents (parallel-proof)
  :short "Proof features not supported with waterfall-parallelism enabled"
  :long "<p>For a general introduction to ACL2(p), an experimental extension of
 ACL2 that supports parallel execution and proof, see @(see parallelism).
 Please note that although this extension is usable and, we hope, robust in its
 behavior, there are still known issues to address beyond those listed
 explicitly below.  While we expect ACL2(p) to perform correctly, it may never
 have the same level of attention to correctness as is given to ACL2; see @(see
 parallelism), specifically the ``IMPORTANT NOTE'' there.</p>

 <p>Below we list proof features of ACL2 that are not yet supported when
 parallel execution is enabled for the primary ACL2 proof process, generally
 known as ``the waterfall'', typically by calling @(tsee
 set-waterfall-parallelism).</p>

 <p>Please note that this topic is limited to the case that such waterfall
 parallelism is enabled.  We believe that all ACL2 proof procedures are
 supported when waterfall parallelism is disabled, even in executables that
 support parallelism (see @(see compiling-acl2p)).</p>

 <p>Without a trust tag (see @(see defttag)): We support @(see
 clause-processor)s, @(see computed-hints), and @(see custom-keyword-hints)
 that do not modify @(see state), but we do not permit @(see override-hints),
 regardless of whether they modify state.  With a trust tag, the user can use
 @(see clause-processor)s that modify state and can also use @(see
 override-hints) (see @(see set-waterfall-parallelism-hacks-enabled) for a
 convenient mechanism for adding a trust tag).  See @(see
 error-triples-and-parallelism) for a discussion of how to avoid modifying
 state in such situations.  Regardless of whether a trust tag is active: We do
 not support checkers of @(see custom-keyword-hints) to be anything but the
 default checker.</p>

 <p>GNU Make versions 3.81 and 3.82 formerly caused a lot of problems (version
 3.80 somewhat less so), at least on Linux, when certifying books with ACL2
 built on a host Lisp of CCL using `make'.  CCL was updated around March 23,
 2011 to fix this problem, so if you get segfaults (for example) with CCL, try
 updating your CCL installation.</p>

 <p>Book certification should generally work but may present some issues,
 including the following.</p>

 <ul>

 <li>The standard `make'-based process for book certification will
 not use @(see waterfall-parallelism), which is disabled by default (even when
 @(see compiling-acl2p) by using the @('ACL2_PAR') flag).  See @(see
 books-certification) and see @(see books-certification-classic), which explain
 that @(see acl2-customization) files are ignored during that process unless
 specified explicitly on the command line or in the environment.</li>

 <li>A book certified with ACL2(p) might subsequently cause an error when
 included with ACL2.  As of this writing, however, we have only seen this for a
 book in which @(tsee deftheory-static) is used.</li>

 <li>In general, ACL2(p) is primarily intended to support more rapid
 interactive development.  While we are unaware of an unsoundness likely to
 affect an ACL2(p) user, we suggest using ACL2 for final book certification,
 rather than ACL2(p), to lower the risk of unsound book
 certification.</li>

 </ul>

 <p>Proof output can contain repeated printing of the same subgoal name.</p>

 <p>@(see Gag-mode) isn't officially supported, although it has proved helpful
 to use ACL2(p) in conjunction with @('(set-gag-mode t)') (because this setting
 suppresses the output that occurs outside the waterfall).  This being said,
 ACL2(p) also prints key checkpoints (for example see @(see
 introduction-to-key-checkpoints)), but with a notion of ``key checkpoint''
 that does not take into account whether the goal is later proved by induction.
 See @(see acl2p-key-checkpoints) for further explanation of these key
 checkpoints.  Note that @(tsee pso) is also not supported.</p>

 <p>The @(':')@(tsee brr) utility is not supported.</p>

 <p>The @(tsee accumulated-persistence) utility is not supported.</p>

 <p>Tracking for @(see forward-chaining-reports) is not supported (see @(see
 set-fc-criteria)).</p>

 <p>Time limits (see @(see with-prover-time-limit)) aren't supported.</p>

 <p>The timing information printed at the end of a proof attempt, which is
 intended to represent cpu time (not wall-clock time), may be somewhat
 inaccurate when @(see waterfall-parallelism) is non-@('nil').  Consider using
 @(tsee time$) to obtain timing information.</p>

 <p>Use @(tsee wormhole)s at your own risk.  Although they use locks, there has
 been some concern that they may cause race conditions.  They are used in
 ACL2(p) source code (macro @(tsee observation-cw)), however, thus we have hope
 that they perform acceptably.</p>

 <p>Output specific to @(':OR') @(see hints) is disabled.</p>

 <p>Proof trees are likely not to work as originally designed.</p>

 <p>The use of @(tsee set-inhibit-output-lst) may not fully inhibit proof
 output.</p>

 <p>Reporting of @(see splitter) rules is currently unsupported when
 waterfall-parallelism is on.</p>

 <p>Interrupting a proof attempt is not yet properly supported.  At a minimum,
 interrupts are trickier with waterfall parallelism enabled.  For one, the user
 typically needs to issue the interrupt twice before the proof attempt is
 actually interrupted.  Additionally, on rare occasions the theorem is
 registered as proved, even though the prover did not finish the proof.  If
 this occurs, issue a @(':u') (see @(see ubt)) and you will likely be at a
 stable state.</p>

 <p>Also with regards to interrupting a proof attempt, sometimes the user may
 need to issue a @(':q') and @('lp') to reset properly the parallelism
 implementation to a stable state.  The primary symptom that the user is
 experiencing this issue is that threads will continue to compute in the
 background, even though there should be no proof attempt in progress.  The
 user can observe this symptom by examining the CPU utilization of their ACL2
 process, for example on Linux/Unix with the shell process @('top').  Lisp
 usage greater than a few percent is indicative of this problem.</p>

 <p>Because of how ACL2 @(see arrays) are designed, the user may find that, in
 practice, ACL2 arrays work (but perhaps with some @(see slow-array-warning)
 messages).  However, we are aware of race conditions that can cause
 problems.</p>

 <p>Instead of dynamically monitoring rewrites, @(see dmr) instead dynamically
 outputs information helpful for debugging the performance of proof
 parallelism.  The instructions concerning how to see this debugging
 information are the same as the instructions for enabling @(see dmr) mode.</p>

 <p>If you are working with LispWorks 6.0 or 6.0.1, then you may see messages
 about misaligned conses.  The state of the system may be corrupted after such
 a message has been printed.  This LispWorks bug is fixed in LispWorks 6.1.</p>

 <p>The waterfall parallelism mode @(':resource-and-timing-based') is not fully
 supported when the host Lisp is other than CCL.  It may work, but we have not
 attempted to address a potential race condition.</p>

 <p>Proof output for splitter rules (see @(see splitter)) is currently
 unsupported when waterfall-parallelism is enabled.</p>

 <p>Profiling may cause proofs to hang when waterfall-parallelism is enabled
 (GitHub Issue #638).</p>")

(defxdoc untouchable
  :parents (defttag)
  :short "Function symbols and state globals that cannot be referenced"
  :long "<p>Untouchables are functions or macros that cannot be called, as well
 as @(see state) global variables (see @(see programming-with-state)) that
 cannot be modified or unbound.  To add or remove untouchables, see @(see
 push-untouchable) and see @(see remove-untouchable).</p>")

(defxdoc untrace$
  :parents (trace)
  :short "Untrace functions"
  :long "@({
  Examples:
  (untrace$)         ; untrace all functions previously
                     ; traced (e.g. with trace$ or trace!)
  (untrace$ foo bar) ; as above, except only untrace foo and bar

  General Forms:
  (untrace$)                 ; untrace all (as noted above)
  (untrace$ fn1 fn2 ... fnk) ; untrace the indicated functions
 })

 <p>where the @('fni') were previously traced (e.g. with @(tsee trace$) or
 @(tsee trace!)).</p>

 <p>@('Untrace$') undoes the effect of @(tsee trace$).  See @(see trace$).  The
 value returned by @('untrace$') gives the list of functions for which tracing
 is being removed.</p>")

(defxdoc untrans-table
  :parents (macros)
  :short "Associates a function symbol with a macro for printing user-level terms"
  :long "@({
  Examples:
  ACL2 !>(untrans-table (w state))
  ((BINARY-+ + . T)
   (BINARY-* * . T)
   (BINARY-APPEND APPEND . T)
   (BINARY-LOGAND LOGAND . T)
   (BINARY-LOGIOR LOGIOR . T)
   (BINARY-LOGXOR LOGXOR . T)
   (BINARY-LOGEQV LOGEQV . T)
   (BINARY-POR POR . T)
   (BINARY-PAND PAND . T))
 })

 <p>See @(see table) for a general discussion of tables.</p>

 <p>See @(see add-macro-fn) for a more general discussion of this @(see table)
 and for a way to associate a macro name with a function name in theory
 events.</p>")

(defxdoc untranslate
  :parents (system-utilities)
  :short "Show a user-level representation of a term"
  :long "<p>ACL2 uses a strict notion of ``@(see term)'' for its internal
 computations; see @(see pseudo-termp).  Such expressions are sometimes called
 ``translated terms''.  However, ACL2 provides user-level output &mdash;
 for example, in output from the theorem prover &mdash; in the form of
 so-called ``untranslated terms''.  For example, the untranslated term @('(<= 3
 x)') corresponds to the translated term @('(not (< x '3))'), as is illustrated
 by applying @(':')@(tsee trans) to the untranslated term:</p>

 @({
 ACL2 !>:trans (<= 3 x)

 (NOT (< X '3))

 => *

 ACL2 !>
 })

 <p>Notice for example that the macro @('<=') has been eliminated in favors
 of the functions @('not') and @('<'), and that the constant @('3') has been
 quoted.</p>

 <p>The call @('(untranslate term iff-flg wrld)') returns an untranslated term
 corresponding to the given translated term, @('term'), with respect to the
 given logical @(see world), @('wrld').  If @('iff-flg') is not @('nil'), then
 that untranslated term is merely propositionally equivalent to the input term,
 as the following example illustrates.</p>

 @({
 ACL2 !>:trans (and x t)

 (IF X 'T 'NIL)

 => *

 ACL2 !>(untranslate '(IF X 'T 'NIL) nil (w state))
 (AND X T)
 ACL2 !>(untranslate '(IF X 'T 'NIL) t (w state))
 X
 ACL2 !>
 })

 <p>The latter result, @('x'), is what one might want to see if the term is
 being used as the first argument of a call of the function, @('if').  Indeed,
 @('untranslate') is defined so that the @('iff') flag is automatically set in
 the test position of an @('if') call.</p>

 @({
 ACL2 !>:trans (if (and x t) y z)

 (IF (IF X 'T 'NIL) Y Z)

 => *

 ACL2 !>(untranslate '(IF (IF X 'T 'NIL) Y Z) nil (w state))
 (IF X Y Z)
 ACL2 !>
 })

 <p>Also see @(see user-defined-functions-table) and @(see add-macro-fn).</p>")

(defxdoc update-nth
  :parents (lists acl2-built-ins)
  :short "Modify a list by putting the given value at the given position"
  :long "<p>@('(Update-nth key val l)') returns a list that is the same as the
 list @('l'), except that the value at the @('0')-based position @('key')
 (a natural number) is @('val').</p>

 <p>If @('key') is an integer at least as large as the length of @('l'), then
 @('l') will be padded with the appropriate number of @('nil') elements, as
 illustrated by the following example.</p>

 @({
  ACL2 !>(update-nth 8 'z '(a b c d e))
  (A B C D E NIL NIL NIL Z)
 })

 <p>We have the following theorem.</p>

 @({
  (implies (and (true-listp l)
                (integerp key)
                (<= 0 key))
           (equal (length (update-nth key val l))
                  (if (< key (length l))
                      (length l)
                    (+ 1 key))))
 })

 <p>The @(see guard) of @('update-nth') requires that its first (position)
 argument is a natural number and its last (list) argument is a true list.</p>

 @(def update-nth)")

(defxdoc update-nth-array
  :parents (stobj acl2-built-ins)
  :short "Update a stobj array"
  :long "<p>@('Update-nth-array') is called by @(see stobj) updaters to modify
 stobj array fields.  See @(see stobj-example-3) for a discussion of this
 function and how it plays that role.</p>

 @(def update-nth-array)")

(defxdoc upper-case-p
  :parents (characters acl2-built-ins)
  :short "Recognizer for upper case characters"
  :long "<p>@('(Upper-case-p x)') is true if and only if @('x') is an upper
 case character, i.e., a member of the list @('#\\A'), @('#\\B'), ...,
 @('#\\Z').</p>

 <p>The @(see guard) for @('upper-case-p') requires its argument to be a
 standard character (see @(see standard-char-p)).</p>

 <p>@('Upper-case-p') is a Common Lisp function.  See any Common Lisp
 documentation for more information.</p>

 @(def upper-case-p)")

(defxdoc user-defined-functions-table
  :parents (macros)
  :short "An advanced @(see table) used to replace certain system functions"
  :long "@({
  Examples:
  (table user-defined-functions-table 'untranslate-preprocess 'my-preprocess)
  (table user-defined-functions-table 'untranslate 'my-untranslate)
 })

 <p>This feature should perhaps only be used by advanced users who have a
 thorough understanding of the system functions being replaced.  There are
 currently two ways a user can affect the way ACL2 prints terms.</p>

 <p>The first example associates the user-defined function symbol
 @('my-preprocess') with @('untranslate-preprocess').  As a result, when ACL2
 prints a term, say during a proof, using its so-called ``untranslate'' process
 the first thing it does is to call @('my-preprocess') on two arguments: that
 term and the current ACL2 logical @(see world).  If the call produces a
 non-@('nil') result, then that result is passed to the untranslate
 process.</p>

 <p>The second example associates the user-defined function symbol
 @('my-untranslate') with the built-in function symbol @('untranslate').  As a
 result, the code for @('my-untranslate') will be run whenever the untranslate
 process is run.  The formals of the two functions must agree and must not
 contain any @(see stobj) names.  Note that these overrides fail to occur upon
 guard violations and some other evaluation errors.</p>

 <p>The @('untranslate-preprocess') approach may suffice for most cases in
 which a user wants to modify the way output is produced by the theorem prover.
 We present an example immediately below, but see @(see untranslate-patterns)
 for a more elaborate example.  If the @('untranslate-preprocess') approach
 does not seem sufficient for your purposes, you are invited to look at
 community book @('books/misc/rtl-untranslate.lisp') or the source code for
 @(see define) for an example of user-defined @('untranslate') (i.e., following
 the second example displayed above).</p>

 <p>Suppose you have a large constant that you would prefer not to see in
 proofs.  For example, you may have submitted the following definition (but
 imagine a much larger constant, say, a list of length 1,000,000).</p>

 @({
  (defconst *a* '(a b c d))
 })

 <p>If you submit the following (silly) theorem</p>

 @({
  (thm (equal (cons x *a*) (car (cons yyy zzz))))
 })

 <p>then you will see the following output:</p>

 @({
  (EQUAL (CONS X '(A B C D)) YYY).
 })

 <p>If @('*a*') had represented a much larger structure, we would wish we could
 see the following instead.</p>

 @({
  (EQUAL (CONS X *A*) YYY)
 })

 <p>That can be accomplished as follows.  First we make the following
 definition.</p>

 @({
  (defun my-preprocess (term wrld)
    (declare (ignore wrld))
    (if (equal term (list 'quote *a*))
        '*a*
      nil))
 })

 <p>Now we submit the following @(tsee table) event.</p>

 @({
  (table user-defined-functions-table
         'untranslate-preprocess
         'my-preprocess)
 })

 <p>This will install @('my-preprocess') as a preprocessor before the normal
 untranslation routine is applied to printing a term.  When the untranslation
 routine encounters the constant @('(QUOTE (A B C D))'), it will replace it
 with @('*a*'), and the usual untranslation routine will print this as
 @('*A*').</p>")

(defxdoc user-stobjs-modified-warnings
  :parents (trans-eval)
  :short "Warnings of single-threadedness violations"
  :long "<p>The utility, @(tsee trans-eval), may be called to evaluate
 arbitrary ACL2 forms.  It can thus be useful for writers of tools.  This topic
 discusses warnings that may be issued by @('trans-eval'), for example as
 follows.</p>

 @({
 ACL2 !>(foo st state)

 ACL2 Warning [User-stobjs-modified] in FOO:  A call of the ACL2 evaluator
 on the term (UPDATE-FLD '4 ST) has modified the user stobj ST.  See
 :DOC user-stobjs-modified-warning.

 (4 <state> <st>)
 ACL2 !>
 })

 <p>If you see such a warning, it is probably caused by a utility that you are
 invoking.  At this time there are no special tools for identifying which tool
 is issuing those warnings, but the ``context'' on the first line of the
 warning &mdash; @('FOO'), above &mdash; may give a clue.</p>

 <p>The remainder of this topic is directed at tool writers.  It discusses how
 to write tools that avoid producing such warnings, and the advisability (or
 not) of doing so.  For background on @('trans-eval'), see @(see
 trans-eval).</p>

 <p>The following example illustrates the issue.</p>

 @({
 (defstobj st fld)

 (defun foo (st state)
   (declare (xargs :stobjs (st state)
                   :mode :program))
   (let ((st (update-fld 3 st)))
     (mv-let (erp val state)
       (trans-eval '(update-fld 4 st) 'foo state nil)
       (declare (ignore erp val))
       (mv (fld st) state st))))
 })

 <p>After submitting these two forms, we can submit to ACL2 the form @('(foo st
 state)') to produce the log displayed above.</p>

 <p>Consider the definition of @('foo').  Now @('trans-eval') returns an @(see
 error-triple), say @('(mv erp val state)'), where @('erp') and @('val') are
 ordinary (non-@(see stobj)) values.  In particular, @('trans-eval') does not
 return the user-defined stobj, @('st').  It ``should'' follow, then, that the
 only modification to @('st') before returning is by the form @('(update-fld 3
 st)').  So the final value of @('(fld st)') ``should'' be 3; yet, it is 4, not
 3!  One can explain this phenomenon by saying that user-defined stobjs reside
 in the ACL2 state, and indeed that is logically the case; see @(see state), in
 particular the discussion there of the field @('user-stobj-alist') of the
 state.  Nevertheless, the first return value of 4, above, can very reasonably
 be considered a violation of single-threadedness.  ACL2 acknowledges this
 concern by printing the warning displayed above.</p>

 <p>In general, such a warning is printed whenever the @('stobjs-out') returned
 in the @('car') of the value, as discussed above, contains a user-defined
 stobj name, that is, a non-@('nil') value other than @('state').</p>

 <p>Fortunately, this behavior can only happen with @(':')@(tsee program)-mode
 functions; @('trans-eval') will never be in @(':')@(tsee logic) mode, and
 therefore, neither will its callers.  Nevertheless, even without proving
 @('nil') one might reasonably be frustrated by this sort of violation of
 single-threaded behavior of stobjs.  The warning is, at least, an
 acknowledgement of this situation.</p>

 <p>That said, there may be cases in which you want to write a tool that calls
 @('trans-eval') and modifies user-defined stobjs, but you don't want the users
 of your tool to see the warning.  Think carefully about whether you really
 don't want them to see the warning!  After all, they may be relying on
 single-threaded semantics, even with @(':program')-mode functions.</p>

 <p>If indeed you want to avoid warnings, you can call the function
 @('trans-eval-no-warning') exactly as you call @('trans-eval').  For example,
 if you replace @('trans-eval') by @('trans-eval-no-warning') in the definition
 above, and then you evaluate @('(foo st state)'), you will not see the warning
 printed above.  Again, consider whether you really want to suppress that
 warning.</p>

 <p>Remark pertaining to @('(ld ...)').  There is another alternative to
 @('trans-eval'), @('trans-eval-default-warning').  This alternative behaves
 like @('trans-eval') when the @('ld') special,
 @('ld-user-stobjs-modified-warning'), is @('t'); otherwise it behaves like
 @('trans-eval-no-warning').  See @(see ld).  There are several calls of
 @('trans-eval-default-warning') in the ACL2 source code: in function
 @('ld-read-eval-print'), which evaluates on behalf of the top-level loop, and
 in some functions that support @(see events), such as those supporting the
 proof-builder.  But for user-level code it may be more appropriate to call
 @('trans-eval') so that single-threadedness violations are reported.  These
 warnings are unimportant in the top-level loop, because one expects stobjs to
 be updated by evaluation.  End of Remark.</p>

 <p>For @(see trans-eval) and @('trans-eval-default-warning'), the normal way
 of inhibiting warnings is supported: @('(set-inhibit-warnings
 \"User-stobjs-modified\")').</p>")

(defxdoc using-computed-hints
  :parents (computed-hints hints)
  :short "How to use computed hints"
  :long "<p>Computed hints (see @(see computed-hints)) are extraordinarily
 powerful.  We show a few examples here to illustrate their use.  We recommend
 that the @('using-computed-hints-n') topics be read in the order
 @('using-computed-hints-1'), @('using-computed-hints-2'), and so on.</p>")

(defxdoc using-computed-hints-1
  :parents (using-computed-hints)
  :short "Driving Home the Basics"
  :long "<p>The common hint</p>

 @({
  (\"Subgoal 3.2.1''\" :use lemma42)
 })

 <p>has the same effect as the computed hint</p>

 @({
  (if (equal id '((0) (3 2 1) . 2))
      '(:use lemma42)
      nil)
 })

 <p>which, of course, is equivalent to</p>

 @({
  (and (equal id '((0) (3 2 1) . 2))
       '(:use lemma42))
 })

 <p>which is also equivalent to the computed hint</p>

 @({
  my-special-hint
 })

 <p>provided the following @('defun') has first been executed</p>

 @({
  (defun my-special-hint (id clause world)
    (declare (xargs :mode :program)
             (ignore clause world))
    (if (equal id '((0) (3 2 1) . 2))
        '(:use lemma42)
        nil))
 })

 <p>It is permitted for the @('defun') to be in :LOGIC mode (see @(see
 defun-mode)) also.</p>

 <p>Just to be concrete, the following three events all behave the same way (if
 @('my-special-hint') is as above):</p>

 @({
  (defthm main (big-thm a b c)
    :hints ((\"Subgoal 3.2.1''\" :use lemma42)))

  (defthm main (big-thm a b c)
    :hints ((and (equal id '((0) (3 2 1) . 2)) '(:use lemma42))))

  (defthm main (big-thm a b c)
    :hints (my-special-hint))
 })")

(defxdoc using-computed-hints-2
  :parents (using-computed-hints)
  :short "One Hint to Every Top-Level Goal in a Forcing Round"
  :long "<p>Suppose the main proof completes with a forcing round on three
 subgoals, \"[1]Subgoal 3\", \"[1]Subgoal 2\", and \"[1]Subgoal 1\".  Suppose
 you wish to @(':use lemma42') in all top-level goals of the first forcing
 round.  This can be done supplying the hint</p>

 @({
  (if test '(:use lemma42) nil),
 })

 <p>where @('test') is an expression that returns @('t') when @('ID') is one of
 the clause ids in question.</p>

 @({
      goal-spec     (parse-clause-id goal-spec)

  \"[1]Subgoal 3\"        ((1) (3) . 0)
  \"[1]Subgoal 2\"        ((1) (2) . 0)
  \"[1]Subgoal 1\"        ((1) (1) . 0)
 })

 <p>Recall (see @(see clause-identifier)) that @('parse-clause-id') maps from a
 goal spec to a clause id, so you can use that function on the goal specs
 printed in the failed proof attempt to determine the clause ids in
 question.</p>

 <p>So one acceptable @('test') is</p>

 @({
  (member-equal id '(((1) (3) . 0)
                     ((1) (2) . 0)
                     ((1) (1) . 0)))
 })

 <p>or you could use @('parse-clause-id') in your computed hint if you don't
 want to see clause ids in your script:</p>

 @({
  (or (equal id (parse-clause-id \"[1]Subgoal 3\"))
      (equal id (parse-clause-id \"[1]Subgoal 2\"))
      (equal id (parse-clause-id \"[1]Subgoal 1\")))
 })

 <p>or you could use the inverse function (see @(see clause-identifier)):</p>

 @({
  (member-equal (string-for-tilde-@-clause-id-phrase id)
                '(\"[1]Subgoal 3\"
                  \"[1]Subgoal 2\"
                  \"[1]Subgoal 1\"))
 })

 <p>Recall that what we've shown above are the tests to use in the computed
 hint.  The hint itself is @('(if test '(:use lemma42) nil)') or something
 equivalent like @('(and test '(:use lemma42))').</p>

 <p>The three tests above are all equivalent.  They suffer from the problem of
 requiring the explicit enumeration of all the goal specs in the first forcing
 round.  A change in the script might cause more forced subgoals and the ones
 other than those enumerated would not be given the hint.</p>

 <p>You could write a test that recognizes all first round top-level subgoals
 no matter how many there are.  Just think of the programming problem: how do I
 recognize all the clause id's of the form @('((1) (n) . 0)')?  Often you can
 come to this formulation of the problem by using @('parse-clause-id') on a few
 of the candidate goal-specs to see the common structure.  A suitable test in
 this case is:</p>

 @({
  (and (equal (car id) '(1))     ; forcing round 1, top-level (pre-induction)
       (equal (len (cadr id)) 1) ; Subgoal n (not Subgoal n.i ...)
       (equal (cddr id) 0))      ; no primes
 })

 <p>The test above is ``overkill'' because it recognizes precisely the clause
 ids in question.  But recall that once a computed hint is used, it is (by
 default) removed from the hints available to the children of the clause.
 Thus, we can widen the set of clause ids recognized to include all the
 children without worrying that the hint will be applied to those children.</p>

 <p>In particular, the following test supplies the hint to every top-level goal
 of the first forcing round:</p>

 @({
  (equal (car id) '(1))
 })

 <p>You might worry that it would also supply the hint to the subgoal produced
 by the hint &mdash; the cases we ruled out by the ``overkill'' above.  But
 that doesn't happen since the hint is unavailable to the children.  You could
 even write:</p>

 @({
  (equal (car (car id)) 1)
 })

 <p>which would supply the hint to every goal of the form \"[1]Subgoal ...\"
 and again, because we see and fire on the top-level goals first, we will not
 fire on, say, \"[1]Subgoal *1.3/2\", i.e., the id '((1 1 3) (2) . 0) even
 though the test recognizes that id.</p>

 <p>Finally, the following test supplies the hint to every top-level goal of
 every forcing round (except the 0th, which is the ``gist'' of the proof, not
 ``really'' a forcing round):</p>

 @({
  (not (equal (car (car id)) 0))
 })

 <p>Recall again that in all the examples above we have exhibited the @('test')
 in a computed hint of the form @('(if test '(:key1 val1 ...) nil)').</p>")

(defxdoc using-computed-hints-3
  :parents (using-computed-hints)
  :short "Hints as a Function of the Goal (not its Name)"
  :long "<p>Sometimes it is desirable to supply a hint whenever a certain term
 arises in a conjecture.  For example, suppose we have proved</p>

 @({
  (defthm all-swaps-have-the-property
     (the-property (swap x))
     :rule-classes nil)
 })

 <p>and suppose that whenever @('(SWAP A)') occurs in a goal, we wish to add
 the additional hypothesis that @('(THE-PROPERTY (SWAP A))').  Note that this
 is equivalent supplying the hint</p>

 @({
  (if test
      '(:use (:instance all-swaps-have-the-property (x A)))
      nil)
 })

 <p>where @('test') answers the question ``does the clause contain @('(SWAP
 A)')?''  That question can be asked with @('(occur-lst '(SWAP A) clause)').
 Briefly, @('occur-lst') takes the representation of a translated term, x, and
 a list of translated terms, y, and determines whether x occurs as a subterm of
 any term in y.  (By ``subterm'' here we mean proper or improper, e.g., the
 subterms of @('(CAR X)') are @('X') and @('(CAR X)').)</p>

 <p>Thus, the computed hint:</p>

 @({
  (if (occur-lst '(swap a) clause)
      '(:use (:instance all-swaps-have-the-property (x A)))
      nil)
 })

 <p>will add the hypothesis @('(THE-PROPERTY (SWAP A))') to every goal
 containing @('(SWAP A)') &mdash; except the children of goals to which the
 hypothesis was added.</p>

 <p><b>A COMMON MISTAKE</b> users are likely to make is to forget that they are
 dealing with translated terms.  For example, suppose we wished to look for
 @('(SWAP (LIST 1 A))') with @('occur-lst').  We would never find it with</p>

 @({
  (occur-lst '(SWAP (LIST 1 A)) clause)
 })

 <p>because that presentation of the term contains macros and other
 abbreviations.  By using :trans (see @(see trans)) we can obtain the
 translation of the target term.  Then we can look for it with:</p>

 @({
  (occur-lst '(SWAP (CONS '1 (CONS A 'NIL))) clause)
 })

 <p>Note in particular that you must</p>

 @({
  * eliminate all macros and
  * explicitly quote all constants.
 })

 <p>We recommend using @(':trans') to obtain the translated form of the terms
 in which you are interested, before programming your hints.</p>

 <p>An alternative is to use the expression @('(prettyify-clause clause nil
 nil)') in your hint to convert the current goal clause into the s-expression
 that is actually printed.  For example, the clause</p>

 @({
  ((NOT (CONSP X)) (SYMBOLP Y) (EQUAL (CONS '1 (CAR X)) Y))
 })

 <p>``prettyifies'' to</p>

 @({
  (IMPLIES (AND (CONSP X)
                (NOT (SYMBOLP Y)))
           (EQUAL (CONS 1 (CAR X)) Y))
 })

 <p>which is what you would see printed by ACL2 when the goal clause is that
 shown.</p>

 <p>However, if you choose to convert your clauses to prettyified form, you
 will have to write your own explorers (like our @('occur-lst')), because all
 of the ACL2 term processing utilities work on translated and/or clausal forms.
 This should not be taken as a terrible burden.  You will, at least, gain the
 benefit of knowing what you are really looking for, because your explorers
 will be looking at exactly the s-expressions you see at your terminal.  And
 you won't have to wade through our still undocumented term/clause utilities.
 The approach will slow things down a little, since you will be paying the
 price of independently consing up the prettyified term.</p>

 <p>We make one more note on this example.  We said above that the computed
 hint:</p>

 @({
  (if (occur-lst '(swap a) clause)
      '(:use (:instance all-swaps-have-the-property (x A)))
      nil)
 })

 <p>will add the hypothesis @('(THE-PROPERTY (SWAP A))') to every goal
 containing @('(SWAP A)') &mdash; except the children of goals to which the
 hypothesis was added.</p>

 <p>It bears noting that the subgoals produced by induction and top-level
 forcing round goals are not children.  For example, suppose the hint above
 fires on \"Subgoal 3\" and produces, say, \"Subgoal 3'\".  Then the hint will
 not fire on \"Subgoal 3'\" even though it (still) contains @('(SWAP A)')
 because \"Subgoal 3'\" is a child of a goal on which the hint fired.</p>

 <p>But now suppose that \"Subgoal 3'\" is pushed for induction.  Then the
 goals created by that induction, i.e., the base case and induction step, are
 not considered children of \"Subgoal 3'\".  All of the original hints are
 available.</p>

 <p>Alternatively, suppose that \"Subgoal 3' is proved but forces some other
 subgoal, \"[1]Subgoal 1\" which is attacked in Forcing Round 1.  That
 top-level forced subgoal is not a child.  All the original hints are available
 to it.  Thus, if it contains @('(SWAP A)'), the hint will fire and supply the
 hypothesis, producing \"[1]Subgoal 1'\".  This may be unnecessary, as the
 hypothesis might already be present in \"[1]Subgoal 1\".  In this case, no
 harm is done.  The hint won't fire on \"[1]Subgoal 1'\" because it is a child
 of \"[1]Subgoal 1\" and the hint fired on that.</p>")

(defxdoc using-computed-hints-4
  :parents (using-computed-hints)
  :short "Computing the Hints"
  :long "<p>So far we have used computed hints only to compute when a fixed set
 of keys and values are to be used as a hint.  But computed hints can, of
 course, compute the set of keys and values.  You might, for example, write a
 hint that recognizes when a clause ``ought'' to be provable by a @(':BDD')
 hint and generate the appropriate hint.  You might build in a set of useful
 lemmas and check to see if the clause is provable @(':BY') one of them.  You
 can keep all function symbols disabled and use computed hints to compute which
 ones you want to @(':EXPAND').  In general, you can write a theorem prover for
 use in your hints, provided you can get it to do its job by directing our
 theorem prover.</p>

 <p>Suppose for example we wish to find every occurrence of an instance of
 @('(SWAP x)') and provide the corresponding instance of
 @('ALL-SWAPS-HAVE-THE-PROPERTY').  Obviously, we must explore the clause
 looking for instances of @('(SWAP x)') and build the appropriate instances of
 the lemma.  We could do this in many different ways, but below we show a
 general purpose set of utilities for doing it.  The functions are not defined
 in ACL2 but could be defined as shown.</p>

 <p>Our plan is: (1) Find all instances of a given pattern (term) in a clause,
 obtaining a set of substitutions.  (2) Build a set of @(':instance')
 expressions for a given lemma name and set of substitutions.  (3) Generate a
 @(':use') hint for those instances when instances are found.</p>

 <p>The pair of functions below find all instances of a given pattern term in
 either a term or a list of terms.  The functions each return a list of
 substitutions, each substitution accounting for one of the matches of pat to a
 subterm.  At this level in ACL2 substitutions are lists of pairs of the form
 @('(var . term)').  All terms mentioned here are presumed to be in translated
 form.</p>

 <p>The functions take as their third argument a list of substitutions
 accumulated to date and add to it the substitutions produced by matching pat
 to the subterms of the term.  We intend this accumulator to be nil initially.
 If the returned value is nil, then no instances of pat occurred.</p>

 @({
  (mutual-recursion

  (defun find-all-instances (pat term alists)
   (declare (xargs :mode :program))
   (mv-let
    (instancep alist)
    (one-way-unify pat term)
    (let ((alists (if instancep (add-to-set-equal alist alists) alists)))
      (cond
       ((variablep term) alists)
       ((fquotep term) alists)
       (t (find-all-instances-list pat (fargs term) alists))))))

  (defun find-all-instances-list (pat list-of-terms alists)
   (declare (xargs :mode :program))
   (cond
    ((null list-of-terms) alists)
    (t (find-all-instances pat
                           (car list-of-terms)
                           (find-all-instances-list pat
                                                    (cdr list-of-terms)
                                                    alists))))))
 })

 <p>Caveat: The following aside has nothing to do with computed hints.  Does an
 instance of @('(CAR (CDR x))') occur in @('((LAMBDA (V) (CAR V)) (CDR A))')?
 It does if one beta-reduces the lambda-expression to @('(CAR (CDR A))'); the
 appropriate substitution is to replace @('x') by @('A').  But the definition
 of @('find-all-instances') above does <i>not</i> find this instance because it
 does not do beta-reduction.</p>

 <p>We now turn our attention to converting a list of substitutions into a list
 of lemma instances, each of the form</p>

 @({
  (:INSTANCE name (var1 term1) ... (vark termk))
 })

 <p>as written in @(':use') hints.  In the code shown above, substitutions are
 lists of pairs of the form @('(var . term)'), but in lemma instances we must
 write ``doublets.''  So here we show how to convert from one to the other:</p>

 @({
  (defun pairs-to-doublets (alist)
    (declare (xargs :mode :program))
    (cond ((null alist) nil)
          (t (cons (list (caar alist) (cdar alist))
                   (pairs-to-doublets (cdr alist))))))
 })

 <p>Now we can make a list of lemma instances:</p>

 @({
  (defun make-lemma-instances (name alists)
    (declare (xargs :mode :program))
    (cond
     ((null alists) nil)
     (t (cons (list* :instance name (pairs-to-doublets (car alists)))
              (make-lemma-instances name (cdr alists))))))
 })

 <p>Finally, we can package it all together into a hint function.  The function
 takes a pattern, @('pat'), which must be a translated term, the name of a
 lemma, @('name'), and a clause.  If some instances of @('pat') occur in
 @('clause'), then the corresponding instances of @('name') are @(':USE')d in
 the computed hint.  Otherwise, the hint does not apply.</p>

 @({
  (defun add-corresponding-instances (pat name clause)
    (declare (xargs :mode :program))
    (let ((alists (find-all-instances-list pat clause nil)))
      (cond
       ((null alists) nil)
       (t (list :use (make-lemma-instances name alists))))))
 })

 <p>The design of this particular hint function makes it important that the
 variables of the pattern be the variables of the named lemma and that all of
 the variables we wish to instantiate occur in the pattern.  We could, of
 course, redesign it to allow ``free variables'' or some sort of renaming.</p>

 <p>We could now use this hint as shown below:</p>

 @({
  (defthm ... ...
    :hints ((add-corresponding-instances
             '(SWAP x)
             'ALL-SWAPS-HAVE-THE-PROPERTY
             clause)))
 })

 <p>The effect of the hint above is that any time a clause arises in which any
 instance of @('(SWAP x)') appears, we add the corresponding instance of
 @('ALL-SWAPS-HAVE-THE-PROPERTY').  So for example, if Subgoal *1/3.5 contains
 the subterm @('(SWAP (SWAP A))') then this hint fires and makes the system
 behave as though the hint:</p>

 @({
  (\"Subgoal *1/3.5\"
   :USE ((:INSTANCE ALL-SWAPS-HAVE-THE-PROPERTY (X A))
         (:INSTANCE ALL-SWAPS-HAVE-THE-PROPERTY (X (SWAP A)))))
 })

 <p>had been present.</p>")

(defxdoc using-computed-hints-5
  :parents (using-computed-hints)
  :short "Debugging Computed Hints"
  :long "<p>We have found that it is sometimes helpful to define hints so that
 they print out messages to the terminal when they fire, so you can see what
 hint was generated and which of your computed hints did it.</p>

 <p>To that end we have defined a macro we sometimes use.  Suppose you have a
 @(':hints') specification such as:</p>

 @({
  :hints (computed-hint-fn (hint-expr id))
 })

 <p>If you defmacro the macro below you could then write instead:</p>

 @({
  :hints ((show-hint computed-hint-fn 1)
          (show-hint (hint-expr id) 2))
 })

 <p>with the effect that whenever either hint is fired (i.e., returns
 non-@('nil')), a message identifying the hint by the marker (1 or 2, above)
 and the non-@('nil') value is printed.</p>

 @({
  (defmacro show-hint (hint &optional marker)
    (cond
     ((and (consp hint)
           (stringp (car hint)))
      hint)
     (t
      `(let ((marker ,marker)
             (ans ,(if (symbolp hint)
                       `(,hint id clause world stable-under-simplificationp)
                     hint)))
         (if ans
             (prog2$
              (cw \"~%***** Computed Hint~#0~[~/ (from hint ~x1)~]~%~x2~%~%\"
                  (if (null marker) 0 1)
                  marker
                  (cons (string-for-tilde-@-clause-id-phrase id)
                        ans))
              ans)
           nil)))))
 })

 <p>Note that when @('show-hint') is applied to a hint that is a symbol, e.g.,
 @('computed-hint-fn'), it applies the symbol to the four computed-hint
 arguments: @('id'), @('clause'), @('world'), and
 @('stable-under-simplificationp').  If @('computed-hint-fn') is of arity 3 the
 code above would cause an error.  One way to avoid it is to write</p>

 @({
  :hints ((show-hints (computed-hint-fn id clause world) 1)
          (show-hint (hint-expr id) 2)).
 })

 <p>If you only use computed hints of arity 3, you might eliminate the
 occurrence of @('stable-under-simplificationp') in the definition of
 @('show-hint') above.</p>

 <p>Putting a @('show-hint') around a common hint has no effect.  If you find
 yourself using this utility let us know and we'll consider putting it into the
 system itself.  But it does illustrate that you can use computed hints to do
 unusual things.</p>")

(defxdoc using-computed-hints-6
  :parents (using-computed-hints)
  :short "Using the computed-hint-replacement feature"
  :long "<p>So far none of our computed hints have used the
 @(':COMPUTED-HINT-REPLACEMENT') feature.  We now illustrate that.</p>

 <p>The @(':computed-hint-replacement') feature can easily lead to loops.  So
 as you experiment with the examples in this section and your own hints using
 this feature, be ready to interrupt the theorem prover and abort!</p>

 <p>A non-looping use of the @(':computed-hint-replacement') feature would be a
 hint like this:</p>

 @({
  (if (certain-terms-present clause)
      '(:computed-hint-replacement t
        :in-theory (enable lemma25))
      '(:computed-hint-replacement t
        :in-theory (disable lemma25)))
 })

 <p>In this hint, if certain terms are present in @('clause'), as determined by
 the function with the obvious name (here undefined), then this hint enables
 @('lemma25') and otherwise disables it.  @('Lemma25') might be a very
 expensive lemma, e.g., one that matches frequently and has an expensive and
 rarely established hypothesis.  One might wish it enabled only under certain
 conditions.  Recall that theories are inherited by children.  So once
 @('lemma25') is enabled it ``stays'' enabled for the children, until disabled;
 and vice versa.  If the @(':computed-hint-replacement') feature were not
 present and computed hints were always deleted after they had been used, then
 @('lemma25') would be left enabled (or disabled) for all the children produced
 by the first firing of the hint.  But with the arrangement here, every subgoal
 gets a theory deemed suitable by the hint, and the hint persists.</p>

 <p>Now we will set up a toy to allow us to play with computed hints to
 understand them more deeply.  To follow the discussion it is best to execute
 the following events.</p>

 @({
  (defstub wrapper (x) t)
  (defaxiom wrapper-axiom (wrapper x) :rule-classes nil)
 })

 <p>Now submit the following event and watch what happens.</p>

 @({
  (thm (equal u v)
    :hints (`(:use (:instance wrapper-axiom (x a)))))
 })

 <p>The theorem prover adds @('(wrapper a)') to the goal and then abandons the
 proof attempt because it cannot prove the subgoal.  Since the computed hint is
 deleted upon use, the hint is not applied to the subgoal (i.e., the child of
 the goal).</p>

 <p>What happens if we do the following?</p>

 @({
  (thm (equal u v)
    :hints (`(:computed-hint-replacement t
              :use (:instance wrapper-axiom (x a)))))
 })

 <p>As one might expect, this loops forever: The hint is applied to the child
 and adds the hypothesis again.  When the hint fires, nothing is actually
 changed, since @('(wrapper a)') is already in the subgoal.</p>

 <p>So let's change the experiment a little.  Let's make the hint add the
 hypothesis @('(wrapper p)') where @('p') is the first literal of the clause.
 This is silly but it allows us to explore the behavior of computed hints a
 little more.</p>

 @({
  (thm (equal u v)
    :hints (`(:use (:instance wrapper-axiom (x ,(car clause))))))
 })

 <p>So in this case, the theorem prover changes the goal to</p>

 @({
  (IMPLIES (WRAPPER (EQUAL U V)) (EQUAL U V))
 })

 <p>which then simplifies to</p>

 @({
  (IMPLIES (WRAPPER NIL) (EQUAL U V))
 })

 <p>because the concluding equality can be assumed false in the hypothesis
 (e.g., think of the contrapositive version).  Nothing else happens because the
 hint has been removed and so is not applicable to the child.</p>

 <p>Now consider the following &mdash; and be ready to interrupt it and
 abort!</p>

 @({
  (thm (equal u v)
    :hints (`(:computed-hint-replacement t
              :use (:instance wrapper-axiom (x ,(car clause))))))
 })

 <p>This time the hint is not removed and so is applied to the child.  So from
 @('Goal') we get</p>

 @({
  Goal'
  (IMPLIES (WRAPPER (EQUAL U V))
           (EQUAL U V))
 })

 <p>and then</p>

 @({
  Goal''
  (IMPLIES (AND (WRAPPER (NOT (WRAPPER (EQUAL U V))))
                (WRAPPER (EQUAL U V)))
           (EQUAL U V))
 })

 <p>etc.</p>

 <p>First, note that the hint is repeatedly applied to its children.  That is
 because we wrote @(':computed-hint-replacement t').  But second, note that
 @('Goal'') is not even being simplified before @('Goal''') is produced from
 it.  If it were being simplified, the @('(equal u v)')'s in the hypotheses
 would be replaced by @('nil').  This is a feature.  It means after a computed
 hint has fired, other hints are given a chance at the result, even the hint
 itself unless it is removed from the list of hints.</p>

 <p>As an exercise, let's arrange for the hint to stay around and be applied
 indefinitely but with a simplification between each use of the the hint.  To
 do this we need to pass information from one application of the hint to the
 next, essentially to say ``stay around but don't fire.''</p>

 <p>First, we will define a function to use in the hint.  This is more than a
 mere convenience; it allows the hint to ``reproduce itself'' in the
 replacement.</p>

 @({
  (defun wrapper-challenge (clause parity)
    (if parity
        `(:computed-hint-replacement ((wrapper-challenge clause nil))
          :use (:instance wrapper-axiom (x ,(car clause))))
        `(:computed-hint-replacement ((wrapper-challenge clause t)))))
 })

 <p>Note that this function is not recursive, even though it uses its own name.
 That is because the occurrence of its name is in a quoted constant.</p>

 <p>Now consider the following.  What will it do?</p>

 @({
  (thm (equal u v)
    :hints ((wrapper-challenge clause t)))
 })

 <p>First, observe that this is a legal hint because it is a term that mentions
 only the free variable @('CLAUSE').  When defining hint functions you may
 sometimes think their only arguments are the four variables @('id'),
 @('clause'), @('world'), and @('stable-under-simplificationp').  That is not
 so.  But in your hints you must call those functions so that those are the
 only free variables.  Note also that the occurrence of @('clause') inside the
 @(':computed-hint-replacement') is not an occurrence of the variable clause
 but just a constant.  Just store this note away for a moment.  We'll return to
 it momentarily.</p>

 <p>Second, the basic cleverness of this hint is that every time it fires it
 reproduces itself with the opposite parity.  When the parity is @('t') it
 actually changes the goal by adding a hypothesis.  When the parity is @('nil')
 it doesn't change the goal and so allows simplification to proceed &mdash; but
 it swaps the parity back to @('t').  What you can see with this simple toy is
 that we can use the computed hints to pass information from parent to
 child.</p>

 <p>Ok, so what happens when the event above is executed?  Try it.  You will
 see that ACL2 applied the hint the first time.  It doesn't get around to
 printing the output because an error is caused before it can print.  But here
 is a blow-by-blow description of what happens.  The hint is evaluated on
 @('Goal') with the @('clause') @('((equal u v))').  It produces a hint exactly
 as though we had typed:</p>

 @({
  (\"Goal\" :use (:instance wrapper-axiom (x (equal u v))))
 })

 <p>which is applied to this goal. In addition, it produces the new hints
 argument</p>

 @({
  :hints ((wrapper-challenge clause nil)).
 })

 <p>By applying the @('\"Goal\"') hint we get the new subgoal</p>

 @({
  Goal'
  (implies (wrapper (equal u v))
           (equal u v))
 })

 <p>but this is not printed because, before printing it, the theorem prover
 looks for hints to apply to it and finds</p>

 @({
  (wrapper-challenge clause nil)
 })

 <p>That is evaluated and produces a hint exactly as though we had typed:</p>

 @({
  (\"Goal'\" )
 })

 <p>and the new hints argument:</p>

 @({
  :hints ((wrapper-challenge clause nil)).
 })

 <p>But if you supply the hint @('(\"Goal'\" )'), ACL2 will signal an error
 because it does not allow you to specify an empty hint!</p>

 <p>So the definition of @('wrapper-challenge') above is almost correct but
 fatally flawed.  We need a non-empty ``no-op'' hint.  One such hint is to tell
 the system to expand a term that will always be expanded anyway.  So undo
 @('wrapper-challenge'), redefine it, and try the proof again.  Now remember
 the observation about @('clause') that we asked you to ``store'' above.  The
 new definition of @('wrapper-challenge') illustrates what we meant.  Note that
 the first formal parameter of @('wrapper-challenge'), below, is no longer
 named @('clause') but is called @('cl') instead.  But the ``call'' of
 @('wrapper-challenge') in the replacements is on @('clause').  This may seem
 to violate the rule that a function definition cannot use variables other than
 the formals.  But the occurrences of @('clause') below are not variables but
 constants in an object that will eventually be treated as hint term.</p>

 @({
  :ubt wrapper-challenge

  (defun wrapper-challenge (cl parity)
    (if parity
        `(:computed-hint-replacement ((wrapper-challenge clause nil))
          :use (:instance wrapper-axiom (x ,(car cl))))
        `(:computed-hint-replacement ((wrapper-challenge clause t))
          :expand ((atom zzz)))))

  (thm (equal u v)
    :hints ((wrapper-challenge clause t)))
 })

 <p>This time, things go as you might have expected!  @('Goal'') is produced
 and simplified, to</p>

 @({
  Goal''
  (implies (wrapper nil)
           (equal u v)).
 })

 <p>Simplification gets a chance because when the new hint
 @('(wrapper-challenge clause nil)') is fired it does not change the goal.  But
 it does change the parity in the hints argument so that before @('Goal''') is
 simplified again, the hint fires and adds the hypothesis:</p>

 @({
  Goal'''
  (IMPLIES (AND (WRAPPER (NOT (WRAPPER NIL)))
                (WRAPPER NIL))
           (EQUAL U V)).
 })

 <p>This simplifies, replacing the first @('(NOT (WRAPPER NIL))') by @('NIL'),
 since @('(WRAPPER NIL)') is known to be true here.  Thus the goal simplifies
 to</p>

 @({
  Goal'4'
  (IMPLIES (WRAPPER NIL) (EQUAL U V)).
 })

 <p>The process repeats indefinitely.</p>

 <p>So we succeeded in getting a hint to fire indefinitely but allow a full
 simplification between rounds.</p>")

(defxdoc using-computed-hints-7
  :parents (using-computed-hints)
  :short "Using the @('stable-under-simplificationp') flag"
  :long "<p>A problem with the example in @(see using-computed-hints-6) is that
 exactly one simplification occurs between each (effective) firing of the hint.
 Much more commonly we wish to fire a hint once a subgoal has become stable
 under simplification.</p>

 <p>A classic example of this is when we are dealing with an interpreter for
 some state machine.  We typically do not want the ``step'' function to open up
 on the symbolic representation of a state until that state has been maximally
 simplified.  We will illustrate with a simple state machine.</p>

 <p>Let us start by defining the step function, @('stp'), and the corresponding
 @('run') function that applies it a given number of times.</p>

 @({
  (defun stp (s)
    (+ 1 s))

  (defun run (s n)
    (if (zp n)
        s
        (run (stp s) (- n 1))))
 })

 <p>The step function here is trivial: a state is just a number and the step
 function increments it.  In this example we will not be interested in the
 theorems we prove but in how we prove them.  The formula we will focus on
 is</p>

 @({
  (thm (equal (run s 7) xxx))
 })

 <p>This is not a theorem, of course.  But we want to test our advice on
 non-theorems because we do not want the advice to work only for proofs that
 succeed.  (In the past, we gave advice about using computed hints and that
 advice caused the theorem prover to run forever when given formulas that it
 couldn't prove &mdash; but most of the time the system is presented with
 formulas it cannot prove!)</p>

 <p>Furthermore, without some kind of additional rules, the @('(run s 7)')
 expression in the conjecture above will not expand at all, because ACL2's
 heuristics do not approve.</p>

 <p>In fact, we do not want to take chances that @('run') will be expanded
 &mdash; we want to control its expansion completely.  Therefore, disable
 @('run').</p>

 @({
  (in-theory (disable run))
 })

 <p>Now, what do we want?  (That is always a good question to ask!)  We want
 @('(run s 7)') to expand ``slowly.''  In particular, we want it to expand
 once, to @('(run (stp s) 6)').  Then we want the @('stp') to be expanded and
 fully simplified before the @('run') expression is expanded again.  That is,
 we want to force the expansion of @('run') whenever the goal is stable under
 simplification.  This is sometimes called ``staged simplification.''</p>

 <p>We can achieve staged simplification for any given function symbol by
 defining the functions shown below and then using a simple computed hint:</p>

 @({
  (thm (equal (run s 7) xxx)
       :hints ((stage run)))
 })

 <p>By inspecting how @('stage') is defined you can see how to extend it, but
 we explain as we go.  To experiment, you can just paste the definitions (and
 defmacro) below into your ACL2 shell and then try the @('thm') command.</p>

 <p>First, define this pair of mutually recursive functions.
 @('Find-first-call') finds the first call of the function symbol @('fn') in a
 given term.</p>

 @({
  (mutual-recursion
   (defun find-first-call (fn term)
   ; Find the first call of fn in term.
    (cond ((variablep term) nil)
          ((fquotep term) nil)
          ((equal (ffn-symb term) fn)
           term)
          (t (find-first-call-lst fn (fargs term)))))
   (defun find-first-call-lst (fn lst)
   ; Find the first call of fn in a list of terms.
    (cond ((endp lst) nil)
          (t (or (find-first-call fn (car lst))
                 (find-first-call-lst fn (cdr lst)))))))
 })

 <p>We will arrange for the computed hint to generate an @(':EXPAND') hint for
 the first call of @('fn'), whenever the goal becomes stable under
 simplification.  If no call is found, the hint will do nothing.  To make sure
 the hint will not loop indefinitely (for example, by forcing @('fn') to expand
 only to have the rewriter ``fold'' it back up again), we will provide the hint
 with a bound that stops it after some number of iterations.  Here is the basic
 function that creates the @('expand') hint and replaces itself to count
 down.</p>

 @({
  (defun stage1 (fn max clause flg)
  ; If the clause is stable under simplification and there is a call of
  ; fn in it, expand it.  But don't do it more than max times.
   (let ((temp (and flg
                    (find-first-call-lst fn clause))))
     (if temp
         (if (zp max)
             (cw \"~%~%HINT PROBLEM:  The maximum repetition count of ~
                  your STAGE hint been reached without eliminating ~
                  all of the calls of ~x0.  You could supply a larger ~
                  count with the optional second argument to STAGE ~
                  (which defaults to 100).  But think about what is ~
                  happening! Is each stage permanently eliminating a ~
                  call of ~x0?~%~%\"
                 fn)
           `(:computed-hint-replacement
              ((stage1 ',fn ,(- max 1)
                       clause
                       stable-under-simplificationp))
             :expand (,temp)))
       nil)))
 })

 <p>Suppose that when @('stage1') is called, @('fn') is the function we want to
 expand, @('max') is the maximum number of iterations of this expansion,
 @('clause') is the current goal clause, and @('flg') is the value of the
 @('stable-under-simplificationp') flag.  Then if @('clause') is stable and we
 can find a call of @('fn') in it, we ask whether @('max') is exhausted.  If
 so, we print an ``error message'' to the comment window with @(tsee cw) and
 return @('nil') (the value of @('cw')).  That @('nil') means the hint does
 nothing.  But if @('max') is not yet exhausted, we return a new hint.  As you
 can see above, the hint replaces itself with another @('stage1') hint with the
 same @('fn') and a decremented @('max') to be applied to the new @('clause')
 and the then-current value of @('stable-under-simplificationp').  The hint
 also contains an @(':expand') directive for the call of @('fn') found.</p>

 <p>Thus, if the computed hint was:</p>

 @({
  (stage1 'run 5 clause stable-under-simplificationp)
 })

 <p>and @('(run s 7)') occurs in the clause, then it will generate</p>

 @({
  (:computed-hint-replacement
    ((stage1 'run 4 clause stable-under-simplificationp))
   :expand ((run s 7)))
 })

 <p>which will in turn replace the old @('stage1') hint with the new one and
 will apply @(':expand ((run s 7))') to the current goal.</p>

 <p>We can make this more convenient by defining the macro:</p>

 @({
  (defmacro stage (fn &optional (max '100))
   `(stage1 ',fn ,max clause stable-under-simplificationp))
 })

 <p>Note that the macro allows us to either provide the maximum bound or let it
 default to 100.</p>

 <p>Henceforth, we can type</p>

 @({
  (thm (equal (run s 7) xxx)
       :hints ((stage run)))
 })

 <p>to stage the opening of @('run') up to 100 times, or we can write</p>

 @({
  (thm (equal (run s 7) xxx)
       :hints ((stage run 5)))
 })

 <p>to stage it only 5 times.  In the latter example, the system with print a
 ``error message'' after the fifth expansion.</p>

 <p>Note that if we executed</p>

 @({
  (set-default-hints '((stage run)))
 })

 <p>then we could attack all theorems (involving @('run')) with staged
 simplification (up to bound 100), without typing an explicit hint.</p>

 @({
  (thm (equal (run s 7) xxx))
 })

 <p>Using techniques similar to those above we have implemented ``priority
 phased simplification'' and provided it as a book.  See community book
 @('books/misc/priorities.lisp').  This is an idea suggested by Pete Manolios,
 by which priorities may be assigned to rules and then the simplifier
 simplifies each subgoal maximally under the rules of a given priority before
 enabling the rules of the next priority level.  The book above documents both
 how we implement it with computed hints and how to use it.</p>

 <p>Here is another example of using the @('stable-under-simplificationp') flag
 to delay certain actions.  It defines a default hint, see @(see
 DEFAULT-HINTS), which will enable @(see non-linear-arithmetic) on precisely
 those goals which are stable-under-simplificationp.  It also uses the
 @('HISTORY') and @('PSPV') variables to determine when toggling @(see
 non-linear-arithmetic) is appropriate.  These variables are documented only in
 the source code.  If you start using these variables extensively, please
 contact the developers of ACL2 or Robert Krug (@('rkrug@cs.utexas.edu')) and
 let us know how we can help.</p>

 @({
  (defun nonlinearp-default-hint (stable-under-simplificationp hist pspv)
    (cond (stable-under-simplificationp
           (if (not (access rewrite-constant
                            (access prove-spec-var pspv :rewrite-constant)
                            :nonlinearp))
               '(:computed-hint-replacement t
                 :nonlinearp t)
             nil))
          ((access rewrite-constant
                   (access prove-spec-var pspv :rewrite-constant)
                   :nonlinearp)
           (if (not (equal (caar hist) 'SETTLED-DOWN-CLAUSE))
               '(:computed-hint-replacement t
                 :nonlinearp nil)
             nil))
          (t
           nil)))
 })")

(defxdoc using-computed-hints-8
  :parents (using-computed-hints)
  :short "Some Final Comments"
  :long "<p>None of the examples show the use of the variable @('WORLD'), which
 is allowed in computed hints.  There are some (undocumented) ACL2 utilities
 that might be useful in programming hints, but these utilities need access to
 the ACL2 logical world (see @(see world)).</p>

 <p>A very useful fact to know is that @('(table-alist name world)') returns an
 alist representation of the current value of the @(tsee table) named
 @('name').</p>

 <p>The ACL2 source code is littered with @(':')@(tsee program) mode functions
 for manipulating world.  In our source code, the world is usually bound a
 variable named @('wrld'); so searching our code for that name might be
 helpful.</p>

 <p>Using these utilities to look at the @('WORLD') one can, for example,
 determine whether a symbol is defined recursively or not, get the body and
 formals of a defined function, or fetch the statement of a given lemma.
 Because these utilities are not yet documented, we do not expect users to
 employ @('WORLD') in computed hints.  But experts might and it might lead to
 the formulation of a more convenient language for computed hints.</p>

 <p>None of our examples illustrated the 7 argument form of a computed hint,
 @('(fn ID CLAUSE WORLD STABLE-UNDER-SIMPLIFICATIONP HIST PSPV CTX)').  When
 used, the variables @('HIST'), @('PSPV'), and @('CTX'), are bound to the
 clause history, the package of ``special variables'' governing the clause, and
 the ``error message context.''  These variables are commonly used throughout
 our source code but are, unfortunately, undocumented.  Again, we expect a few
 experts will find them useful in developing computed hints.</p>

 <p>If you start using computed hints extensively, please contact the
 developers of ACL2 and let us know what you are doing with them and how we can
 help.</p>")

(defxdoc using-enabled-rules
  :parents (theories)
  :short "Avoiding @(':use') @(see hints) for @(see enable)d @(':')@(tsee
  rewrite) rules"
  :long "<p>Consider the following (admittedly silly) example.</p>

 @({
  (thm (equal (append (append x y) z) (append x y z))
       :hints ((\"Subgoal *1/1\" :use cdr-cons)))
 })

 <p>ACL2's output includes the following warning.</p>

 @({
  ACL2 Warning [Use] in ( THM ...):  It is unusual to :USE an enabled
  :REWRITE or :DEFINITION rule, so you may want to consider disabling
  (:REWRITE CDR-CONS) in the hint provided for Subgoal *1/1.
 })

 <p>The warning is saying that if you leave the rewrite rule enabled, ACL2 may
 simplify away the hypothesis added by the @(':use') hint.  We now explain this
 danger in more detail and show how disabling the rule can solve this
 problem.</p>

 <p>Recall (see @(see hints)) how @(':use') @(see hints) work.  Such a hint
 specifies a formula, @('F'), which is based on an existing lemma.  Then the
 indicated goal, @('G'), is replaced by the implication @('(implies F G)').
 The intention is that the truth of @('F') will help in the simplification of
 @('G') to @('T') (true).  The ``[Use]'' warning shown above is telling us of
 the danger that @('F') may be rewritten to @('T'), reducing the implication
 above to @('(implies T G)') &mdash; thus, sadly, @('F') has disappeared and is
 not available to help with the simplification of @('G').</p>

 <p>Consider the following tiny example.</p>

 @({
    (defun p (x) (cons x x))
    (defthm car-p
       (equal (car (p x)) x))
    (in-theory (disable p (:type-prescription p)))
    (thm (implies (equal (p x1) (p x2))
                  (equal x1 x2))
         :hints ((\"Goal\"
                  :use ((:instance car-p (x x1))
                        (:instance car-p (x x2))))))
 })

 <p>The proof of the final @(tsee thm) form fails, because the new hypotheses
 are rewritten to @('t') using the @(':')@(tsee rewrite) rule @('CAR-P'), in
 the manner described above.  The following proof log shows the new hypotheses
 and their disappearance via rewriting.</p>

 @({
    We augment the goal with the hypotheses provided by the :USE hint.
    These hypotheses can be derived from CAR-P via instantiation.  We are
    left with the following subgoal.

    Goal'
    (IMPLIES (AND (EQUAL (CAR (P X1)) X1)
                  (EQUAL (CAR (P X2)) X2))
             (IMPLIES (EQUAL (P X1) (P X2))
                      (EQUAL X1 X2))).

    By the simple :rewrite rule CAR-P we reduce the conjecture to

    Goal''
    (IMPLIES (EQUAL (P X1) (P X2))
             (EQUAL X1 X2)).
 })

 <p>When we disable the rule @('CAR-P') as follows, the proof succeeds.</p>

 @({
    (thm (implies (equal (p x1) (p x2))
                  (equal x1 x2))
         :hints ((\"Goal\"
                  :use ((:instance car-p (x x1))
                        (:instance car-p (x x2)))
                  :in-theory (disable car-p))))
 })

 <p>In general, then, a solution is to disable the rewrite rule that you are
 supplying in a @(':use') hint.</p>")

(defxdoc using-tables-efficiently
  :parents (table)
  :short "Notes on how to use tables efficiently"
  :long "<p>
 (Thanks to Jared Davis for contributing this @(see documentation) topic, to
 which we have made only minor modifications.)</p>

 <p>Suppose your book contains @(tsee table) @(see events), or macros that
 expand into @('table') events, of the following form:</p>

 @({
     (table my-table 'my-field <computation>)
 })

 <p>Then @('<computation>') will be evaluated <i>twice</i> during @(tsee
 certify-book) and <i>again</i> every time you include the book with @(tsee
 include-book).  In some cases this overhead can be avoided using @(tsee
 make-event).</p>

 <p>See also @(see defconsts) for an analogous trick involving @(tsee
 defconst).</p>

 <p>As an example, suppose we want to store numbers in a table only if they
 satisfy some computationally expensive predicate.  We'll introduce a new book,
 @('number-table.lisp'), and create a table to store these numbers:</p>

 @({
    (table number-table 'data nil)
 })

 <p>Instead of implementing a ``computationally expensive predicate,'' we'll
 write a function that just prints a message when it is called and accepts even
 numbers:</p>

 @({
  (defun expensive-computation (n)
    (prog2$ (cw \"Expensive computation on ~x0.~%\" n)
            (evenp n)))
 })

 <p>Now we'll implement a macro, @('add-number'), which will add its argument
 to the table only if it satisfies the expensive predicate:</p>

 @({
  (defmacro add-number (n)
    `(table number-table 'data
            (let ((current-data
                   (cdr (assoc-eq 'data (table-alist 'number-table world)))))
              (if (expensive-computation ,n)
                  (cons ,n current-data)
                current-data))))
 })

 <p>Finally, we'll call @('add-number') a few times to finish the book.</p>

 @({
  (add-number 1)
  (add-number 2)
  (add-number 3)
 })

 <p>When we now invoke @('(certify-book \"number-table\")'), we see the
 expensive predicate being called twice for each number: once in Step 2, the
 main pass, then again in Step 3, the admissibility check.  Worse, the
 computation is performed again for each number when we use @(tsee
 include-book) to load @('number-table'), e.g.,</p>

 @({
     ACL2 !>(include-book \"number-table\")
     Expensive computation on 1.
     Expensive computation on 2.
     Expensive computation on 3.
 })

 <p>To avoid these repeated executions, we can pull the test out of the
 @('table') event using @(tsee make-event).  Here's an alternate implementation
 of @('add-number') that won't repeat the computation:</p>

 @({
  (defmacro add-number (n)
    `(make-event
      (if (expensive-computation ,n)
          '(table number-table 'data
                  (cons ,n (cdr (assoc 'data
                                       (table-alist 'number-table world)))))
        '(value-triple :expensive-computation-failed))))
 })

 <p>When we recertify @('number-table.lisp'), we'll see the expensive
 computation is still called once for each number in Step 2, but is no longer
 called during Step 3.  Similarly, the @(tsee include-book) no longer shows any
 calls of the expensive computation.</p>")

(defxdoc |Undocumented Topic|
  :parents (|Pages Written Especially for the Tours|)
  :short "Undocumented Topic"
  :long "<p>This topic has not yet been documented.  Sorry</p>")

(defxdoc |Using the Associativity of App to Prove a Trivial Consequence|
  :parents (|Pages Written Especially for the Tours|)
  :short "Using the Associativity of App to Prove a Trivial Consequence"
  :long "<p><see topic='@(url
 |Overview of the Proof of a Trivial Consequence|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>If we have proved the @('associativity-of-app') rule, then the following
 theorem is trivial:</p>

 @({
  (defthm trivial-consequence
    (equal (app (app (app (app x1 x2) (app x3 x4)) (app x5 x6)) x7)
           (app x1 (app (app x2 x3) (app (app x4 x5) (app x6 x7))))))
 })

 <p>Below we show the proof</p>

 <p><see topic='@(url |Overview of the Proof of a Trivial Consequence|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc value-triple
  :parents (events acl2-built-ins)
  :short "Compute a value, optionally checking that it is not @('nil')"
  :long "@({
  Examples:
  (value-triple (+ 3 4))
  (value-triple (cw \"hi\") :on-skip-proofs t)
  (value-triple (@ ld-pre-eval-print))
  (value-triple (@ ld-pre-eval-print) :check t)

  General Form:
  (value-triple form
                :on-skip-proofs sp ; optional; nil by default
                :check chk         ; optional; nil by default
                :ctx ctx           ; optional; ''value-triple by default
                )
 })

 <p>@('Value-triple') provides a convenient way to evaluate a form in an event
 context, including @(tsee progn) and @(tsee encapsulate) and in @(see books);
 see @(see events).  The form should evaluate to a single, non-@(see stobj)
 value.</p>

 <p>Calls of @('value-triple') are generally skipped when proofs are being
 skipped, in particular when ACL2 is performing the second pass through the
 @(see events) of an @(tsee encapsulate) form or during an @(tsee
 include-book), or indeed any time @(tsee ld-skip-proofsp) is non-@('nil').  If
 you want the call evaluated during those times as well, use a non-@('nil')
 value for @(':on-skip-proofs').  Note that the argument to
 @(':on-skip-proofs') is not evaluated.</p>

 <p>If you expect the form to evaluate to a non-@('nil') value and you want an
 error to occur when that is not the case, you can use @(':check t').  More
 generally, the argument of @(':check') can be a form that evaluates to a
 single, non-@(see stobj) value.  If this value is not @('nil'), then the
 aforementioned test is made (that the given form is not @('nil')).  If an
 error occurs and the value of @(':check') is a string or indeed any
 ``message'' suitable for printing by @(tsee fmt) when supplied as a value for
 tilde-directive @('~@'), then that string or message is printed as an ACL2
 soft error, evaluating the given @(':ctx') argument (default
 @('''value-triple')) as the @('ctx') for @(tsee er).</p>

 <p>Finally, note that @('value-triple') performs evaluation in so-called @(see
 safe-mode), which can slow down evaluation significantly but checks @(see
 guard)s on @(see primitive)s.</p>")

(defxdoc verbose-pstack
  :parents (pstack)
  :short "Seeing what the prover is up to (for system hackers)"
  :long "<p>NOTE: This utility is a low-level debugging utility, which may not
 be useful except to those familiar with ACL2 source code.</p>

 @({
 General Forms:
 (verbose-pstack t)   ; get trace-like information on prover during proofs
 (verbose-pstack '(fn1 fn2 ...))
                      ; as above, but omit calls of the indicated functions
 (verbose-pstack nil) ; turn off trace-like information on prover
 })

 <p>For example, (verbose-pstack '(ev-fncall)) will provide a trace of various
 prover functions during proofs, except for the function @('ev-fncall').</p>

 <p>By evaluating @('(verbose-pstack t)') one can get trace-like information
 during subsequent proofs about prover functions, including time summaries,
 printed to the screen during a proof.  To turn off this feature, evaluate
 @('(verbose-pstack nil)').  Also see @(see pstack).</p>")

(defxdoc verify
  :parents (proof-builder)
  :short "Enter the interactive proof-builder"
  :long "<p>For proof-builder command summaries, see @(see proof-builder).</p>

 @({
  Examples:
  (VERIFY (implies (and (true-listp x) (true-listp y))
                        (equal (append (append x y) z)
                               (append x (append y z)))))
     -- Attempt to prove the given term interactively.

  (VERIFY (p x)
          :event-name p-always-holds
          :rule-classes (:rewrite :generalize)
          :instructions ((rewrite p-always-holds-lemma)
                         change-goal))
     -- Attempt to prove (p x), where the intention is to call the
        resulting DEFTHM event by the name p-always-holds, with
        rule-classes as indicated.  The two indicated instructions
        will be run immediately to start the proof.

  (VERIFY)
     -- Re-enter the interactive proof-builder in the state at which
        it was most recently left.

  General Form:
  (VERIFY &OPTIONAL raw-term
          &KEY
          event-name
          rule-classes
          instructions)
 })

 <p>@('Verify') is the function used for entering the interactive @(see
 proof-builder)'s read-eval-print loop.</p>

 <p>Note that you can use @('verify') to create an event, by using the
 @('exit') command (see @(see acl2-pc::exit)).  For example, after
 evaluating</p>

 @({
 (verify (equal y y) :instructions (s (exit foo nil t)))
 })

 <p>we can see that the expected event was successfully created:</p>

 @({
 ACL2 !>:pe foo
            1:x(VERIFY (EQUAL Y Y) :INSTRUCTIONS ...)
               \
 >              (DEFTHM FOO (EQUAL Y Y)
                        :RULE-CLASSES NIL
                        :INSTRUCTIONS (:S))
 ACL2 !>
 })

 <p>That said, it's probably not a good idea to save @(see events) with
 @(':instructions').  There are at least two general reasons to avoid
 @(':instructions'): (1) to encourage the development of @(see rewrite) rules
 and other ways to help with later proofs, and (2) to make the proofs less
 brittle, that is, more likely to survive when there are small changes to
 earlier events.</p>")

(defxdoc verify-guards
  :parents (events guard)
  :short "Verify the @(see guard)s of a function"
  :long "<p>See @(see guard) for a general discussion of guards.</p>

 <p>Before discussing the @('verify-guards') event, we first discuss guard
 verification, which can take place at definition time or, later, using
 @('verify-guards').  Typically, guard verification takes place at definition
 time if a guard (or type, or @(see stobjs)) has been supplied explicitly
 unless @(':verify-guards nil') has been specified; see @(see defun) and see
 @(see xargs), and see @(see set-verify-guards-eagerness) for how to change
 this default.  The point of guard verification is to ensure that during
 evaluation of an expression without free variables, no guard violation takes
 place.</p>

 <p>Technical note: the first argument of @('verify-guards') must be a function
 symbol or the name of a @(tsee defthm) or @(tsee defaxiom) event, not a
 macro-alias for a function symbol (see @(see macro-aliases-table)).  See @(see
 verify-guards+) for a utility that does not have this restriction.</p>

 <p>Guard verification is intended to guarantee that for any call of a given
 function, if its @(see guard) holds for that call then the @(see guard) will
 hold for every function call in the body of that function.  Moreover, in order
 to avoid guard violations during evaluation of the function's guard itself,
 guard verification also is intended to guarantee that the guards are satisfied
 for all calls in the guard itself.  Consider the following simple example.</p>

 @({
  (defun f (x)
    (declare (xargs :guard (and (consp x)
                                (integerp (car x)))))
    (if (rationalp (cdr x))
        (+ (car x) (cdr x))
      17))
 })

 <p>If you evaluate @('(f t)'), for example, in the top-level loop, you will
 (by default) get a guard error.  The point of guard verification is to
 guarantee the absence of guard errors, and we start by using this example to
 illustrate the proof obligations that guarantee such absence.</p>

 <p>The body of the above definition has the following function calls, where
 the first is the entire body.</p>

 @({
    (if (rationalp (cdr x))
        (< (car x) (cdr x))
      17)
    (rationalp (cdr x)) ; the test of the top-level IF call
    (cdr x)             ; from (rationalp (cdr x))
    (< (car x) (cdr x)) ; the true branch of the top-level IF call
    (car x)             ; from (< (car x) (cdr x))
    (cdr x)             ; from (< (car x) (cdr x))
 })

 <p>We thus see potentially six conditions to prove, one for each call.  The
 guards of the function symbols of those calls are @('t') for @(tsee if) and
 @(tsee rationalp), @('(or (consp x) (equal x nil))') for both @('(car x)') and
 @('(cdr x)'), and finally that both arguments are rationals for @('<').
 Moreover, we can take advantage of ``contextual assumptions'': the
 @('if')-test conditions and the top-level @(':guard').  Thus, for
 @('verify-guards') the proof obligation from the body of @('f') is as
 follows.</p>

 @({
  (implies
   (and (consp x) (integerp (car x))) ; from the :guard
   (and t ; from the top-level IF call
        t ; from (rationalp (cdr x))
        (or (consp x) (equal x nil)) ; from the first (cdr x)
        (implies
         (rationalp (cdr x)) ; IF-test for calls in the true branch
         (and (or (consp x) (equal x nil)) ; from (car x)
              (or (consp x) (equal x nil)) ; from the second (cdr x)
              (and (rationalp (car x)) (rationalp (cdr x))) ; from the < call
              ))))
 })

 <p>But the @(':guard') itself generates a similar sort of proof obligation.
 Note that the guard @('(and (consp x) (integerp (car x)))') is really an
 abbreviation (i.e. via the macro @(tsee AND)) for the term @('(if (consp x)
 (integerp (car x)) nil)').  The guard proof obligation for the guard itself is
 thus as follows.</p>

 @({
  (and t ; from (consp x)
       (implies (consp x)
                (and t         ; from (integerp (car x)) ;
                     (consp x) ; from (car x) ;
                     )))
 })

 <p>All of the above proof obligations are indeed theorems, and guard
 verification succeeds for the above definition of @('f').</p>

 <p>The example above illustrates the general procedure for generating the
 guard proof obligation.  Each function call is considered in the body or guard
 of the function, and it is required that the guard is met for that call, under
 certain ``contextual assumptions'', which are as follows.  In the case of the
 body of the named function, it is assumed that the guard holds for that
 function on its formal parameters.  And in both cases &mdash; the body of the
 named function and also its guard &mdash; the governing tests from superior
 calls of @(tsee IF) are also assumed.</p>

 <p>As mentioned above, if the guard on a function is not @('t'), then guard
 verification requires not only consideration of the body under the assumption
 that the guard is true, but also consideration of the guard itself.  Thus, for
 example, guard verification fails in the following example, even though there
 are no proof obligations arising from the body, because the guard itself can
 cause a guard violation when evaluated for an arbitrary value of @('x'):</p>

 @({
  (defun foo (x)
    (declare (xargs :guard (car x)))
    x)
 })

 <p>We turn now to the @('verify-guards') event as a way of verifying the @(see
 guard)s for a function or theorem.</p>

 @({
  Examples:
  (verify-guards flatten)
  (verify-guards flatten
                 :hints ((\"Goal\" :use (:instance assoc-of-app)))
                 :guard-debug t ; default = nil
                 :otf-flg t)

  General Form:
  (verify-guards name
          :hints        hints
          :guard-debug  t ; typically t, but any value is legal
          :otf-flg      otf-flg)
 })

 <p>In the General Form above, @('name') is the name of a @(':')@(tsee logic)
 function (see @(see defun-mode)) or of a theorem or axiom.  In the most common
 case @('name') is the name of a function that has not yet had its @(see
 guard)s verified, each subroutine of which has had its @(see guard)s verified.
 The values @(tsee hints), @(tsee otf-flg), and @(tsee guard-debug) are as
 described in the corresponding @(see documentation) entries.  The keyword
 arguments above are all optional.  To admit this event, the conjunction of the
 guard proof obligations must be proved.  If that proof is successful,
 @('name') is considered to have had its @(see guard)s verified.</p>

 <p>See @(see guard-formula-utilities) for utilities that let you view the
 formula to be proved by @('verify-guards'), but without creating an event.</p>

 <p>If @('name') is one of several functions in a mutually recursive clique,
 @('verify-guards') will attempt to verify the @(see guard)s of all of the
 functions.</p>

 <p>If @('name') is a theorem or axiom name, @('verify-guards') verifies the
 guards of the associated formula.  When a theorem has had its guards verified
 then you know that the theorem will evaluate to non-@('nil') in all Common
 Lisps, without causing a runtime error (other than possibly a resource error).
 In particular, you know that the theorem's validity does not depend upon
 ACL2's arbitrary completion of the domains of partial Common Lisp
 functions.</p>

 <p>For example, if @('app') is defined as</p>

 @({
  (defun app (x y)
    (declare (xargs :guard (true-listp x)))
    (if (endp x)
        y
        (cons (car x) (app (cdr x) y))))
 })

 <p>then we can verify the guards of @('app') and we can prove the theorem:</p>

 @({
  (defthm assoc-of-app
    (equal (app (app a b) c) (app a (app b c))))
 })

 <p>However, if you go into almost any Common Lisp in which @('app') is defined
 as shown and evaluate</p>

 @({
  (equal (app (app 1 2) 3) (app 1 (app 2 3)))
 })

 <p>we get an error or, perhaps, something worse like @('nil')!  How can this
 happen since the formula is an instance of a theorem?  It is supposed to be
 true!</p>

 <p>It happens because the theorem exploits the fact that ACL2 has completed
 the domains of the partially defined Common Lisp functions like @(tsee car)
 and @(tsee cdr), defining them to be @('nil') on all non-conses.  The formula
 above violates the guards on @('app').  It is therefore ``unreasonable'' to
 expect it to be valid in Common Lisp.</p>

 <p>But the following formula is valid in Common Lisp:</p>

 @({
  (if (and (true-listp a)
           (true-listp b))
      (equal (app (app a b) c) (app a (app b c)))
      t)
 })

 <p>That is, no matter what the values of @('a'), @('b') and @('c') the formula
 above evaluates to @('t') in all Common Lisps (unless the Lisp engine runs out
 of memory or stack computing it).  Furthermore the above formula is a
 theorem:</p>

 @({
  (defthm guarded-assoc-of-app
    (if (and (true-listp a)
             (true-listp b))
        (equal (app (app a b) c) (app a (app b c)))
        t))
 })

 <p>This formula, @('guarded-assoc-of-app'), is very easy to prove from
 @('assoc-of-app').  So why prove it?  The interesting thing about
 @('guarded-assoc-of-app') is that we can verify the guards of the formula.
 That is, @('(verify-guards guarded-assoc-of-app)') succeeds.  Note that it has
 to prove that if @('a') and @('b') are true lists then so is @('(app a b)') to
 establish that the guard on the outermost @('app') on the left is satisfied.
 By verifying the guards of the theorem we know it will evaluate to true in all
 Common Lisps.  Put another way, we know that the validity of the formula does
 not depend on ACL2's completion of the partial functions or that the formula
 is ``well-typed.''</p>

 <p>One last complication: The careful reader might have thought we could state
 @('guarded-assoc-of-app') as</p>

 @({
  (implies (and (true-listp a)
                (true-listp b))
           (equal (app (app a b) c)
                  (app a (app b c))))
 })

 <p>rather than using the @('if') form of the theorem.  We cannot!  The reason
 is technical: @(tsee implies) is defined as a function in ACL2.  When it is
 called, both arguments are evaluated and then the obvious truth table is
 checked.  That is, @('implies') is not ``lazy.''  Hence, when we write the
 guarded theorem in the @('implies') form we have to prove the guards on the
 conclusion without knowing that the hypothesis is true.  It would have been
 better had we defined @('implies') as a macro that expanded to the @('if')
 form, making it lazy.  But we did not and after we introduced guards we did
 not want to make such a basic change.  For a utility that deals with this sort
 of problem automatically, see @(tsee defthmg).</p>

 <p>Recall however that @('verify-guards') is almost always used to verify the
 guards on a function definition rather than a theorem.  We now return to that
 discussion.</p>

 <p>@('Verify-guards') must often be used when the value of a recursive call of
 a defined function is given as an argument to a subroutine that is @(see
 guard)ed.  An example of such a situation is given below.  Suppose @('app')
 (read ``append'') has a @(see guard) requiring its first argument to be a
 @(tsee true-listp).  Consider</p>

 @({
  (defun rev (x)
    (declare (xargs :guard (true-listp x)))
    (cond ((endp x) nil)
          (t (app (rev (cdr x)) (list (car x))))))
 })

 <p>Observe that the value of a recursive call of @('rev') is being passed into
 a @(see guard)ed subroutine, @('app').  In order to verify the @(see guard)s
 of this definition we must show that @('(rev (cdr x))') produces a @(tsee
 true-listp), since that is what the @(see guard) of @('app') requires.  How do
 we know that @('(rev (cdr x))') is a @(tsee true-listp)?  The most elegant
 argument is a two-step one, appealing to the following two lemmas: (1) When
 @('x') is a @(tsee true-listp), @('(cdr x)') is a @(tsee true-listp).  (2)
 When @('z') is a @(tsee true-listp), @('(rev z)') is a @(tsee true-listp).
 But the second lemma is a generalized property of @('rev'), the function we
 are defining.  This property could not be stated before @('rev') is defined
 and so is not known to the theorem prover when @('rev') is defined.</p>

 <p>Therefore, we might break the admission of @('rev') into three steps:
 define @('rev') without addressing its @(see guard) verification, prove some
 general properties about @('rev'), and then verify the @(see guard)s.  This
 can be done as follows:</p>

 @({
  (defun rev (x)
    (declare (xargs :guard (true-listp x)
                    :verify-guards nil))    ; Note this additional xarg.
    (cond ((endp x) nil)
          (t (app (rev (cdr x)) (list (car x))))))

  (defthm true-listp-rev
    (implies (true-listp x2)
             (true-listp (rev x2))))

  (verify-guards rev)
 })

 <p>The ACL2 system can actually admit the original definition of @('rev'),
 verifying the @(see guard)s as part of the @(tsee defun) event.  The reason is
 that, in this particular case, the system's heuristics just happen to hit upon
 the lemma @('true-listp-rev').  But in many more complicated functions it is
 necessary for the user to formulate the inductively provable properties before
 @(see guard) verification is attempted.</p>

 <p><b>Remark on computation of guard conjectures and evaluation</b>.  When
 ACL2 computes the @(see guard) conjecture for the body of a function, it
 evaluates any ground subexpressions (those with no free variables), for calls
 of functions whose @(':')@(tsee executable-counterpart) @(see rune)s are
 @(tsee enable)d.  Note that here, ``enabled'' refers to the current global
 @(see theory), not to any @(':')@(tsee hints) given to the guard verification
 process; after all, the guard conjecture is computed even before its initial
 goal is produced.  Also note that this evaluation is done in an environment as
 though @(':set-guard-checking :all') had been executed, so that we can trust
 that this evaluation takes place without guard violations; see @(see
 set-guard-checking).</p>

 <p>If you want to verify the @(see guard)s on functions that are built into
 ACL2, you will first need to put them into @(':')@(tsee logic) mode.  See
 @(see verify-termination), specifically the ``Remark on system functions'' in
 that @(see documentation).</p>")

(defxdoc verify-guards+
  :parents (events)
  :short "Verify the @(see guard)s of a function"
  :long "<p>We assume familiarity with @(see guard) verification; see @(see
 verify-guards).  Unlike @('verify-guards'), the macro call @('(verify-guards+
 mac ...)') will verify guards for a function, @('fn'), such that the macro
 @('mac') is associated with the function symbol @('fn') in @(tsee
 macro-aliases-table)
 (also see @(see add-macro-alias)).  For example, if you define a macro
 @('app') and list append function @('binary-app'), and you associate macro
 @('app') with function symbol @('binary-app') in @(tsee macro-aliases-table),
 then evaluation of the form @('(verify-guards+ app)') will have the effect of
 evaluating @('(verify-guards fn)').  Note that in this setting, evaluation of
 @('(verify-guards app)') would cause an error, because @('app') is a macro and
 @('verify-guards'), unlike @('verify-guards+'), cannot handle macros.</p>

 <p>The rest of this @(see documentation) topic discusses why we do not simply
 arrange that @('verify-guards') be permitted to take a macro alias.  The
 following example shows a soundness issue in doing so.</p>

 @({
  (encapsulate
   ()
   (defun f1 (x)
     (declare (xargs :guard (consp x)
                     :verify-guards nil))
     (car x))
   (defun f2 (x)
     (declare (xargs :guard t
                     :verify-guards nil))
     (cdr x))
   (defmacro mac (x)
     x)
   (add-macro-alias mac f2) ; silly macro alias ;
   (local (add-macro-alias mac f1)) ; alternate silly macro alias ;
   (verify-guards mac))
 })

 <p>If we were to allow macro aliases in @(tsee verify-guards), this event
 would be admitted, because on the first pass we are verifying guards of
 @('f1').  But after the @(tsee encapsulate) form completes evaluation, it
 would appear that @('f2') is guard-verified.  That could of course cause a raw
 Lisp error.</p>

 <p>The enhanced functionality provided by @('verify-guards+') does not have
 the above problem, because it takes advantage of @(tsee make-event) to avoid
 taking advantage of the contradictory results produced by the two calls of
 @('add-macro-alias').  See @(see make-event).  If the specific example above
 is modified by replacing @('verify-guards') with @('verify-guards+'), then the
 first pass through the @(tsee encapsulate) form will expand the form
 @('(verify-guards+ mac)') to @('(verify-guards f1)').  That same expansion
 will be used for the @('verify-guards+') call during the second pass through
 the @('encapsulate') form, which is evaluated successfully and leaves us in a
 @(see world) where @('f1') is guard-verified and @('f2') is not.</p>")

(defxdoc verify-guards-for-system-functions
  :parents (system-development verify-termination verify-guards)
  :short "Arranging that source functions come up as guard-verified"
  :long "<p>ACL2 is maintained solely by Matt Kaufmann and J Moore.  However,
 we anticipate that a few others will eventually contribute as well.  Here we
 discuss how to put built-in functions into @(':')@(tsee logic) mode.  Since
 ACL2 insists that its built-in @(':logic') mode functions are @(see
 guard)-verified, we actually explain how to arrange that built-in @(':')@(tsee
 program) mode functions become built in guard-verified @(':logic') mode
 functions.</p>

 <p>To put a system function into @(':logic') mode, you might first need or
 want to modify ACL2, for example replacing @('(null lst)') by @('(endp lst)')
 in a function's definition in support of the termination proof.  You might
 wish to see @(see making-system-changes) for information on modifying system
 code.</p>

 <p>After making such changes, build an ACL2 executable image containing your
 modified code.  The next step is typically to create a new file, perhaps named
 after the main function(s) whose guards you want to verify, in directory
 @('books/system').  Community book @('books/system/too-many-ifs.lisp') is a
 good example.  Ultimately, this file should be a certifiable book that
 verifies the desired termination and guards.  Include this book in
 @('books/system/top.lisp').  Of course, you can instead add to some existing
 file in the same directory that is already included in
 @('books/system/top.lisp'), rather than creating a new book and including it
 there.</p>

 <p>The steps above can be done without touching the ACL2 source files.</p>

 <p>Now it is time to modify the constant *system-verify-guards-alist*, which
 associates a distributed book name with a list of functions whose
 guard-verification is proved by including that book.  Follow the steps
 below.</p>

 <ol>

 <li>Build a so-called ``devel'' copy in which the functions in
 @('*system-verify-guards-alist*') remain in @(':program') mode.  For example,
 the following command will create ``devel'' executable @('saved_acl2d').

 @({
 (time nice make ACL2_DEVEL=d) >& make-devel.log
 })</li>

 <li>Check that the build worked (see @(see making-system-changes)).</li>

 <li>Run a ``devel'' regression, for example as follows if starting in the ACL2
 sources directory.

 @({
 make clean-books ACL2=`pwd`/saved_acl2d
 cd books
 (time nice ./build/cert.pl -j 8 \\
            --acl2 `pwd`/../saved_acl2d system/top.cert) \\
   >& make-devel-regression.log&
 })

 The last of these commands should take well under 2 minutes on a decent
 machine.  You can of course check on it as follows.

 @({
 tail make-devel-regression.log
 })</li>

 <li>Check that there are no errors, by checking that the following produces no
 output.

 @({
 fgrep -a '**' make-devel-regression.log
 })</li>

 <li>Run the following check from your ACL2 sources directory.

 @({
 make devel-check ACL2=`pwd`/saved_acl2d
 })

 You should see output like the following.

 @({
 (chk-new-verified-guards 0) ...
 (chk-new-verified-guards 1) ...
 SUCCESS for chk-new-verified-guards
 SUCCESS for check-system-events
 SUCCESS for devel-check
 })</li>

 <li>Ideally, you will finally do a normal build and regression; again, see
 @(see making-system-changes).</li>

 </ol>")

(defxdoc verify-guards-formula
  :parents (guard-formula-utilities)
  :short "View the guard proof obligation, without proving it"
  :long "<p>See @(see verify-guards) and see @(see guard) for a discussion of
 guards.  This utility provides output showing the guard proof obligation as
 printed by @('verify-guards'), but without then carrying out a proof attempt.
 If you simply want the guard proof obligation for a definition
 (without the prover's output), use @(see gthm).  Note that @('gthm') has an
 option to avoid the simplification that is normally performed when generating
 the guard proof obligation.  For more about related utilities, see @(see
 guard-formula-utilities).</p>

 @({
  Example Forms:
  (verify-guards-formula foo)
  (verify-guards-formula foo :guard-debug t)
  (verify-guards-formula foo :rrp t :otf-flg dont-care :xyz whatever)
  (verify-guards-formula (+ (foo x) (bar y)) :guard-debug t)
 })

 <p>@('Verify-guards-formula') allows all keywords, but only pays attention to
 @(':guard-debug'), which has the same effect as in @(tsee verify-guards) (see
 @(see guard-debug)), and to @(':rrp'), described below.  Apply
 @('verify-guards-formula') to a name just as you would use @(tsee
 verify-guards), but when you only want the output that shows the guard proof
 obligation, without attempting a proof or creating an event.  If the first
 argument is not a symbol, then it is treated as the body of a @(tsee defthm)
 event for which you want the guard proof obligation.</p>

 <p>The @(':rrp') argument (``return redundant p'') is @('nil') by default.  If
 its value is not @('nil'), then in the case that the first argument is a
 guard-verified function symbol, the keyword @(':REDUNDANT') is returned
 without any output.</p>")

(defxdoc verify-termination
  :parents (events)
  :short "Convert a function from :program mode to :logic mode"
  :long "@({
  Example:
  (verify-termination fact)

  General Forms:
  (verify-termination fn dcl ... dcl)
  (verify-termination (fn1 dcl ... dcl)
                      (fn2 dcl ... dcl)
                      ...)
 })

 <p>where @('fn') and the @('fni') are function symbols having @(':')@(tsee
 program) mode (see @(see defun-mode)) and all of the @('dcl')s are either
 @(tsee declare) forms or @(see documentation) strings.  The first form above
 is an abbreviation for</p>

 @({
  (verify-termination (fn dcl ... dcl))
 })

 <p>so we limit our discussion to the second form.  Each of the @('fni') must
 be in the same clique of mutually recursively defined functions, but not every
 function in the clique need be among the @('fni').</p>

 <p>@('Verify-termination') attempts to establish the admissibility of the
 @('fni'). @('Verify-termination') retrieves their definitions, creates
 modified definitions using the @('dcl')s supplied above, and resubmits these
 definitions.  You could avoid using @('verify-termination') by typing the new
 definitions yourself.  So in that sense, @('verify-termination') adds no new
 functionality.  But if you have prototyped your system in @(':')@(tsee
 program) mode and tested it, you can use @('verify-termination') to resubmit
 your definitions and change their @(see defun-mode)s to @(':')@(tsee logic),
 adding @(see hints) without having to retype or recopy the code.</p>

 <p>The @(tsee defun) @(see command) executed by @('verify-termination') is
 obtained by retrieving the @(tsee defun) (or @(tsee mutual-recursion)) @(see
 command) that introduced the clique in question and then possibly modifying
 each definition as follows.  Consider a function, @('fn'), in the clique.  If
 @('fn') is not among the @('fni') above, its definition is left unmodified
 other than to add @('(declare (xargs :mode :logic))').  Otherwise, @('fn') is
 some @('fni') and we modify its definition by inserting into it the
 corresponding @('dcl')s listed with @('fni') in the arguments to
 @('verify-termination'), as well as @('(declare (xargs :mode :logic))').  In
 addition, we throw out from the old declarations in @('fn') the @(':mode')
 specification and anything that is specified in the new @('dcl')s.</p>

 <p>For example, suppose that @('fact') was introduced with:</p>

 @({
  (defun fact (n)
    (declare (type integer n)
             (xargs :mode :program))
    (if (zp n) 1 (* n (fact (1- n))))).
 })

 <p>Suppose later we do @('(verify-termination fact)').  Then the following
 definition is submitted.</p>

 @({
  (defun fact (n)
    (declare (type integer n))
    (if (zp n) 1 (* n (fact (1- n))))).
 })

 <p>Observe that this is the same definition as the original one, except the
 old specification of the @(':mode') has been deleted so that the @(see
 defun-mode) now defaults to @(':')@(tsee logic).  Although the termination
 proof succeeds, ACL2 also tries to verify the @(see guard), because we have
 (implicitly) provided a @(see guard), namely @('(integerp n)'), for this
 function.  (See @(see guard) for a general discussion of guards, and see @(see
 type-spec) for a discussion of how type declarations are used in guards.)
 Unfortunately, the @(see guard) verification fails, because the subterm @('(zp
 n)') requires that @('n') be nonnegative, as can be seen by invoking @(':args
 zp').  (For a discussion of termination issues relating to recursion on the
 naturals, see @(see zero-test-idioms).)  So we might be tempted to submit the
 following:</p>

 @({
  (verify-termination
   fact
   (declare (xargs :guard (and (integerp n) (<= 0 n))))).
 })

 <p>However, this is considered a changing of the guard (from @('(integerp
 n)')), which is illegal.  If we instead change the guard in the earlier
 @('defun') after undoing that earlier definition with @(':')@(tsee ubt)@('
 fact'), then @('(verify-termination fact)') will succeed.</p>

 <p><b>Remark on system functions.</b> There may be times when you want to
 apply @('verify-termination') (and also, perhaps, @(tsee verify-guards)) to
 functions that are predefined in ACL2.  It may be necessary in such cases to
 modify the system code first.  See @(see verify-guards-for-system-functions)
 for a discussion of the process for contributing updates to the system code
 and @(see books) with such @('verify-termination') or @(tsee verify-guards)
 @(see events), perhaps resulting in more system functions being built-in as
 @(see guard)-verified.  To see which built-in functions have already received
 such treatment, see community books directory @('books/system/'); or, evaluate
 the constant @('*system-verify-guards-alist*'), each of whose entries
 associates the name of a community book with a list of functions whose
 guard-verification is proved by including that book.  See the above URL for
 more details.</p>

 <p>Note that if @('fn1') is already in @(':')@(tsee logic) mode, then the
 @('verify-termination') call has no effect.  It is generally considered to be
 redundant, in the sense that it returns without error; but if the @('fn1') is
 a constrained function (i.e., introduced in the signature of an @(tsee
 encapsulate), or by @(tsee defchoose)), then an error occurs.  This error is
 intended to highlight unintended uses of @('verify-termination'); but if you
 do not want to see an error in this case, you can write and use your own macro
 in place of @('verify-termination').  The following explanation of the
 implementation of @('verify-termination') may help with such a task.</p>

 <p>We conclude with a discussion of the use of @(tsee make-event) to implement
 @('verify-termination').  This discussion can be skipped; we include it only
 for those who want to create variants of @('verify-termination'), or who are
 interested in seeing an application of @(tsee make-event).</p>

 <p>Consider the following proof of @('nil'), which succeeded up through
 Version_3.4 of ACL2.</p>

 @({
  (encapsulate
   ()
   (defun foo (x y)
     (declare (xargs :mode :program))
     (if (or (zp x) (zp y))
         (list x y)
       (foo (1+ x) (1- y))))
   (local (defun foo (x y)
            (declare (xargs :measure (acl2-count y)))
            (if (or (zp x) (zp y))
                (list x y)
              (foo (1+ x) (1- y)))))
   (verify-termination foo))

  (defthm bad-lemma
    (zp x)
    :hints ((\"Goal\" :induct (foo x 1)))
    :rule-classes nil)
 })

 <p>How did this work?  In the first pass of the @(tsee encapsulate), the
 second @(tsee defun) of @('foo') promoted @('foo') from @(':program') to
 @(':logic') mode, with @('y') as the unique measured variable.  The following
 call to @('verify-termination') was then redundant.  However, on the second
 pass of the @(tsee encapsulate), the second (@(tsee local)) definition of
 @('foo') was skipped, and the @('verify-termination') event then used the
 first definition of @('foo') to guess the measure, based (as with all guesses
 of measures) on a purely syntactic criterion.  ACL2 incorrectly chose
 @('(acl2-count x)') as the measure, installing @('x') as the unique measured
 variable, which in turn led to an unsound induction scheme subsequently used
 to prove @('nil') (lemma @('bad-lemma'), above)</p>

 <p>Now, @('verify-termination') is a macro whose calls expand to @(tsee
 make-event) calls.  So in the first pass above, the @('verify-termination')
 call generated a @('defun') event identical to the @(tsee local) @(tsee defun)
 of @('foo'), which was correctly identified as redundant.  That expansion was
 recorded, and on the second pass of the @(tsee encapsulate), the expansion was
 recalled and used in place of the @('verify-termination') call (that is how
 @(tsee make-event) works).  So instead of a measure being guessed for the
 @('verify-termination') call on the second pass, the same measure was used as
 was used on the first pass, and a sound induction scheme was stored.  The
 attempt to prove @('nil') (lemma @('bad-lemma')) then failed.</p>")

(defxdoc verify-termination-on-raw-program-okp
  :parents (verify-termination)
  :short "Permit @(tsee verify-termination) for functions with raw Lisp code."
  :long "<p>By default, it is not permitted to <see topic='@(url
 verify-termination)'> verify termination</see> for functions with raw Lisp
 code.  (Technical note: With sufficient effort this restriction could perhaps
 be lifted, but that would involve significant modification to the ACL2
 sources, in particular to handle properly code generation for
 executable-counterparts (see @(see evaluation)) in such cases in source
 function @('oneify-cltl-code').)</p>

 <p>However, in some cases it may be harmless to remove this restriction.  That
 can be done as follows.  Note that an active trust tag is required: in
 principle you can render ACL2 unsound with this action!</p>

 @({
 (defttag t)
 (remove-untouchable verify-termination-on-raw-program-okp nil)
 (assign verify-termination-on-raw-program-okp t)
 })")

(defxdoc version
  :parents (about-acl2)
  :short "ACL2 Version Number"
  :long "<p>To determine the version number of your copy of ACL2, evaluate the
 form @('(@ acl2-version)').  The value will be a string.  For example,</p>

 @({
  ACL2 !>(@ acl2-version)
  \"ACL2 Version 3.4\"
 })

 <p>The part of the string after @('\"ACL2 Version \"') is of the form @('x.y')
 or @('x.y.z'), optionally followed by a succession of values in parentheses,
 where @('x'), @('y'), and @('z') are natural numbers.  If @('z') is omitted
 then it is implicitly 0.  We refer to @('X'), @('y'), and @('z') as the
 ``major'', ``minor'', and ``incrl'' fields, respectively.  The incrl field is
 used for incremental releases.  The discussion just below assumes that
 incremental releases are not employed at the user's site, i.e., the incrl
 fields are always 0.  We remove this assumption when we discuss incremental
 releases at the end of this documentation topic.</p>

 <p>@(see Books) are considered certified only in the same version of ACL2 in
 which the certification was done.  The @(see certificate) file records the
 version number of the certifying ACL2 and @(see include-book) considers the
 book uncertified if that does not match the current version number.  Thus,
 each time we release a new version of ACL2, previously certified books should
 be recertified.</p>

 <p>Note that there are over 150 constants in the system, most having to do
 with the fact that ACL2 is coded in ACL2.  Many of these, for example
 @('*common-lisp-specials-and-constants*') and @('*acl2-exports*'), may change
 from version to version, and this can cause unsoundness.  For example, the
 symbol @(''set-difference-eq') was added to @('*acl2-exports*') in
 Version_2.9, so we can certify a book in Version_2.8 containing the following
 theorem, which is false in Version_2.9.</p>

 @({
  (null (member 'set-difference-eq *acl2-exports*))
 })

 <p>Therefore, we need to disallow inclusion of such a book in a Version_2.9
 session, which otherwise would allow us to prove @('nil').  Furthermore, it is
 possible that from one version of the system to another we might change, say,
 the default values on some system function or otherwise make ``intentional''
 changes to the axioms.  It is even possible one version of the system is
 discovered to be unsound and we release a new version to correct our
 error.</p>

 <p>Therefore we adopted the draconian policy that books are certified by a
 given version of ACL2 and ``must'' be recertified to be used in other
 versions.  We put ``must'' in quotes because in fact, ACL2 allows a book that
 was certified in one ACL2 version to be included in a later version, using
 @(tsee include-book).  But ACL2 does not allow @(tsee certify-book) to succeed
 when such an @(tsee include-book) is executed on its behalf.  Also, you may
 experience undesirable behavior if you avoid recertification when moving to a
 different version.  Hence we recommend that you stick to the draconion policy
 of recertifying books when updating to a new ACL2 version.</p>

 <p>Furthermore, all bets are off if you certify a book using ACL2 built on one
 host Lisp implementation and include the book using ACL2 built on a different
 host Lisp implementation.  For example, for most host Lisp implementations,
 the Lisp reader will interpret the token @('2f') as a symbol; however, Common
 Lisp allows for the possibility that @('2f') is read as a number.  In such a
 case, one could use the former ACL2 executable to certify a book containing
 the form</p>

 @({
 (defthm my-thm
   (symbolp '2f)
   :rule-classes nil)
 })

 <p>but then use the latter ACL2 executable to include the book, even though
 for the latter ACL2 executable, @('2f') is a number, not a symbol.  Of course,
 one would expect an error because of a @(see book-hash) mismatch) in such
 case.  But these do not provide guaranteed protection against including
 uncertified books.</p>

 <p><i>Incremental releases.</i></p>

 <p>From time to time, so-called ``incremental releases'' of ACL2 are made
 available.  These releases are thoroughly tested on at least two platforms;
 ``normal'' releases, on the other hand, are thoroughly tested on many more
 platforms (perhaps a dozen or so) and are accompanied by updates to the ACL2
 home page.  We provide incremental releases in order to provide timely updates
 for ACL2 users who want them, without imposing unnecessary burdens on either
 on the ACL2 implementors or on ACL2 users who prefer to update less
 frequently.  The implementors expect users to update their copies of ACL2 when
 normal releases are made available, but not necessarily when incremental
 releases are made available.</p>

 <p>Incremental releases are accompanied by a bump in the incrl field of the
 version field, while normal releases are accompanied by a bump in the minor or
 (much less frequently) major field and zeroing out of the incrl field.  Note
 that incremental releases are full-fledged releases.</p>")

(defxdoc w
  :parents (state)
  :short "The current ACL2 @(see world)"
  :long "<p>The value of the form @('(w state)') is the current ACL2 world.
 See @(see world).</p>")

(defxdoc walkabout
  :parents (debugging)
  :short "Explore an ACL2 cons tree"
  :long "<p>By typing @('(walkabout x state)') for an ACL2 term @('x') whose
 value is a @(tsee cons) tree, you can walk around that tree.  For example,
 ACL2 developers often use this utility to explore the ACL2 logical @(see
 world).</p>

 <p>When you issue a @('walkabout') command, a summary of commands will be
 printed before you enter an interactive loop.</p>

 @({
  Commands:
  0, 1, 2, ..., nx, bk, pp, (pp n), (pp lev len), =, (= symb), and q.
 })

 <p>In the interactive @('walkabout') loop, a positive integer n takes you to
 the nth position, while 0 takes you up a level.  The commands @('nx') and
 @('bk') take you to the next and previous position, respectively, at the same
 level.  The command @('pp') prints the current object in full, while @('(pp
 level length)') hides sub-objects below the indicated level and past the
 indicated length, if non-@('nil'); see @(see evisc-tuple).  The command @('(pp
 n)') abbreviates @('(pp n n)'), so in particular @('(pp nil)') is equivalent
 to @('pp').</p>

 <p>Note that the commands above work in any package: @('nx'), @('bk'),
 @('pp'), @('='), and @('q') are converted to the @('\"ACL2\"') package if the
 current package is not @('\"ACL2\"').</p>

 <p>The following example illustrates the commands described above.</p>

 @({
  ACL2 !>(walkabout (append '(a (b1 b2 b3)) '(c d e f)) state)

  Commands:
  0, 1, 2, ..., nx, bk, pp, (pp n), (pp lev len), =, (= symb), and q.

  (A (B1 B2 B3) C ...)
  :2
  (B1 B2 B3)
  :3
  B3
  :0
  (B1 B2 B3)
  :nx
  C
  :nx
  D
  :0
  (A (B1 B2 B3) C ...)
  :pp
  (A (B1 B2 B3) C D E F)
  :(pp 4)
  (A (B1 B2 B3) C D ...)
  :(pp 1 4)
  (A # C D ...)
  :(pp nil 2)
  (A (B1 B2 ...) ...)
  :q
  ACL2 !>
 })

 <p>Finally we describe the commands @('q'), @('='), and @('(= symb)'), where
 @('symb') is a symbol.  The command @('q') simply causes an exit from the
 @('walkabout') loop.  The command @('=') also exits, but causes the current
 object to be printed in full.  The command @('(= symb)') saves an association
 of @('symb') with the current object, which can be retrieved outside the
 @('walkabout') loop using the macro @('walkabout='), as illustrated below.</p>

 @({
  :2
  (B1 B2 B3)
  :(= my-list)
  (walkabout= MY-LIST) is
  (B1 B2 B3)
  :q
  ACL2 !>(walkabout= MY-LIST)
  (B1 B2 B3)
  ACL2 !>
 })

 <p>Finally, we remark that for trees that are not true-lists, @('walkabout')
 treats the dot as an object that can be ``walked about''.  The following
 example illustrates this point.</p>

 @({
  ACL2 !>(walkabout '(c d e . f) state)

  Commands:
  0, 1, 2, ..., nx, bk, pp, (pp n), (pp lev len), =, (= symb), and q.

  (C D E . F)
  :3
  E
  :nx
  .
  :nx
  F
  :0
  (C D E . F)
  :4
  .
  :0
  (C D E . F)
  :5
  F
  :
 })")

(defxdoc warnings
  :parents (prover-output)
  :short "Warnings emitted by the ACL2 proof process"
  :long "<p>The prover can emit many warnings when processing @(see events).
 See @(see set-inhibit-warnings) and see @(see set-inhibit-output-lst) for how
 to disable and enable them.</p>")

(defxdoc waterfall-parallelism
  :parents (parallel-proof)
  :short "For ACL2(p): configuring the parallel execution of the waterfall"
  :long "<p>See @(see set-waterfall-parallelism).</p>")

(defxdoc waterfall-parallelism-for-book-certification
  :parents (parallelism)
  :short "For ACL2(p): using waterfall parallelism during book certification"
  :long "<p>This @(see documentation) topic relates to the experimental
 extension of ACL2 supporting parallel execution and proof; see @(see
 parallelism).</p>

 <p>There are books whose certification can be sped up significantly by using
 waterfall parallelism.  (See @(see parallelism), including the caveat in its
 \"IMPORTANT NOTE\".)  One such example in the ACL2 community books is
 @('models/jvm/m5/apprentice.lisp'), which is typically excluded from
 regressions because of how long it takes to certify.  In order to use
 waterfall parallelism during certification of a book @('<book-name>.lisp')
 using `make' (see @(see books-certification) and see @(see
 books-certification-classic)), we recommend creating a file
 @('<book-name>.acl2') that includes the following forms.</p>

 @({
  #+acl2-par
  (set-waterfall-parallelism t)

  (certify-book <book-name> ? t) ; other arguments may be preferable
 })

 <p>Note that there are books that will not certify when waterfall-parallelism
 is enabled.  See file @('acl2-customization-files/README') for more
 information, including how to certify essentially all books using waterfall
 parallelism.</p>")

(defxdoc waterfall-printing
  :parents (parallel-proof)
  :short "For ACL2(p): configuring the printing within the parallelized waterfall"
  :long "<p>See @(see set-waterfall-printing).</p>")

(defxdoc well-formedness-guarantee
  :parents (rule-classes)
  :short "Guarantee that a metafunction or clause-processor returns a
 well-formed answer"
  :long "<p>A @(':well-formedness-guarantee') is a keyword attribute available
 in the @(':')@(tsee meta) and @(':')@(tsee clause-processor) @(':')@(tsee
 rule-classes).  By default, when a metafunction or clause processor is
 applied, ACL2 checks that the output is well-formed (and does not contain
 certain ``forbidden'' functions; see @(tsee set-skip-meta-termp-checks)).  By
 providing a @(':well-formedness-guarantee') when you store a @(':meta') or
 @(':clause-processor') rule, you can cause ACL2 to skip these runtime
 checks.</p>

 <p>This is considered an advanced feature that requires that you prove certain
 theorems; this is probably only worthwhile if your metafunctions or clause
 processors produce very large terms.  Henceforth, we assume you are familiar
 with metafunctions and clause processors.</p>

 <p>This topic first exhibits a simple example of a well-formedness guarantee
 for a metafunction.  This example is really an outline; a self-contained,
 runnable example may be found in the @(see community-books) in file
 @('books/demos/meta-wf-guarantee-example.lisp').  Then we describe the
 acceptable values of the @(':well-formedness-guarantee') keyword of both the
 @(':meta') and @(':clause-processor') rule-classes.  Next we show the forms of
 the theorems you must prove to provide such guarantees.  Finally, we discuss
 the runtime effects of providing such guarantees.</p>

 <h4>Example</h4>

 <p>Suppose that @('fn') is a vanilla metafunction that rewrites terms with top
 function symbol @('TARGET'), of @(tsee arity) 1.  The event storing @('fn') as
 a metafunction would normally be something like this:

 @({
 (defthm fn-is-correct
   (implies (and (pseudo-termp x)
                 (alistp a))
            (equal (evl x a)
                   (evl (fn x) a)))
   :rule-classes
   ((:meta :trigger-fns (TARGET))))
 })

 where @('evl') is an evaluator for all the function symbols known to @('fn').
 Suppose that to prove this theorem, @('evl') must be able to interpret the
 symbols @('TARGET'), @('CONS'), and @('IF').  While the metatheorem for
 @('fn') establishes that @('fn') returns something with the same
 ``meaning'' (under @('evl')) as its input, it does not answer the question:
 does @('fn') return a well-formed term, all of whose function symbols are in
 @(':')@(tsee logic) mode?  Given the above @(':rule-class'), whenever the
 simplifier fires the @(':meta') rule @('fn-is-correct') by applying @('fn') to
 a term, it checks that the value, @('val'), is well-formed, by evaluating
 @('(logic-termp val (w state))').  The function @(tsee logic-termp) checks
 that its argument is a @(see term) all of whose function symbols are in
 @(':logic') mode.</p>

 @(def logic-termp)

 <p>The @('logic-termp') check can be avoided if, before you store the rule
 @('fn-is-correct'), you prove:

 @({
 (defthm fn-is-well-formed
   (implies (and (logic-termp x w)
                 (arities-okp '((TARGET . 1)
                                (CONS . 2)
                                (IF . 3))
                              w))
            (logic-termp (fn x) w))
   :rule-classes nil)
 })

 and then you store @('fn-is-correct') this way:

 @({
 (defthm fn-is-correct
   (implies (and (pseudo-termp x)
                 (alistp a))
            (equal (evl x a)
                   (evl (fn x) a)))
   :rule-classes
   ((:meta :trigger-fns (TARGET)
           :well-formedness-guarantee fn-is-well-formed)))
 })
 </p>

 <h4>Acceptable Values</h4>

 <p>Now we describe the values you may provide with the
 @(':well-founded-guarantee') keyword of the @(':meta') and the
 @(':clause-processor') rule-classes.

 @({
 General Forms:
 :well-formedness-guarantee thm-name1
 :well-formedness-guarantee (thm-name1)
 :well-formedness-guarantee (thm-name1 thm-name2)

 })

 where both @('thm-name1') and @('thm-name2') are the names of previously
 proved ``well-formedness theorems'' (see the next section); furthermore,
 @('thm-name1') must be about the metafunction or clause processor being
 introduced, and @('thm-name2') must be about the hypothesis metafunction (if
 any) associated with the metafunction.  For @(':meta') rules, all three forms
 are accepted, but the last form is required if the @(':meta') rule involves a
 hypothesis metafunction.  That is, to provide a
 @(':well-formedness-guarantee') for a metatheorem with a hypothesis
 metafunction, you must supply both @('thm-name1') and @('thm-name2').  For
 @(':clause-processor') rules, you must use the first form.</p>

 <p>Each well-formedness theorem provides an ``arity alist'' that specifies the
 assumed arities of the function symbols known to the metafunction or clause
 processor.  The arities shown for the function symbols listed in that alist
 must be the same as the arities of those functions in the actual ACL2 logical
 @(see world) current at the time the @(':meta') or @(':clause-processor') is
 stored.  Moreover, the function symbols in that alist must all be in
 @(':')@(tsee logic) mode.</p>

 <p>Furthermore, none of the function symbols in the arity alists should be
 ``forbidden'' function symbols as explained in @(tsee
 set-skip-meta-termp-checks).</p>

 <p>When the @(':meta') or @(':clause-processor') rule is stored, notes are
 made that will prevent the function symbols on the arity alists from becoming
 untouchable (and thus forbidden).  See @(tsee push-untouchable).</p>

 <p>The only way a function's arity or forbidden status can change, or that a
 function can transition out of @(':logic') mode, is if the user has engaged in
 redefinition or activated a trust tag to add or remove untouchables.  Thus,
 the restrictions above are unimportant to most users.</p>

 <h4>Well-Formedness Theorems</h4>

 <p>Theorems must be proved to establish that metafunctions and clause
 processors return well-formed results.  These are called ``well-formedness
 theorems.''  Note: To say a theorem is a ``well-formedness theorem'' is a
 remark about the shape of the formula, not its rule-class.  There is no
 @(':well-formedness-theorem') rule-class and a well-formedness theorem may be
 stored with any @(':')@(tsee rule-classes) that accept the syntax of the
 formula or as @(':rule-classes') @('nil').  Indeed, if one of your
 metafunctions uses another function to produce a subterm of the metafunction's
 answer, you might need to prove a well-formedness theorem for the sub-function
 and make it a @(':rewrite') rule.</p>

 <p>Well-formedness theorems for metafunctions and clause processors are
 similar but slightly different.  We deal with metafunctions and their
 corresponding hypothesis metafunctions (if any) first.  The shapes of the
 well-formedness theorems for a metafunction and hypothesis metafunction are
 identical, but remember that you must prove a well-formedness theorem for both
 the metafunction and the associated hypothesis metafunction.  So suppose
 @('fn') is a metafunction or a hypothesis metafunction and let @('(fn x ...)')
 be a legal call on distinct variable symbols.  (Recall that extended
 metafunctions and their hypothesis functions can take three arguments.)  Then
 the general form a well-formedness theorem for @('fn') states that @('fn')
 returns a @(tsee termp) when given one, provided the arities of certain
 function symbols are as expected:

 @({
 General Form of Well-Formedness Theorem for a Metafunction:
 (implies (and (logic-termp x w)
               (arities-okp '<alist> w))
          (logic-termp (fn x ...) w))
 })

 where @('<alist>') is an alist pairing function symbols with their assumed
 arities as illustrated in the opening example.  Note that the first argument
 of @('arities-okp') in the theorem is a quoted constant.  You may omit or
 reorder the hypotheses above and you may use different variable symbols in
 place of @('x') and @('w'), but they must be distinct and different from the
 variables in the ``@('...').''</p>

 <p>An example of @('<alist>') is @('((TARGET . 1) (CONS . 2) (IF . 3))').
 Generally, the @('<alist>') you provide should assign arities to every symbol
 known to @('fn'), i.e., every function symbol known to the evaluator used in
 your correctness theorem.  If you inspect the definition of @(tsee termp) you
 will see that it uses @('w') to obtain arities of the function symbols in
 @('x').  The @(tsee arities-okp) hypothesis restricts @('w') to worlds where
 the function symbols known to @('fn') have the arities you expect and are in
 @(':')@(tsee logic)-mode.  For example, given the @('(arities-okp '<alist>
 w)') hypothesis for the @('<alist>') above, the theorem prover will rewrite
 @('(arity 'IF w)') to 3.  By default @(tsee arity) and @(tsee arities-okp) are
 disabled; and the following rewrite rules, which are part of ACL2's initial
 @(see world), will take care of calls like @('(arity 'IF w)') and @('(logicp
 fn w)').</p>

 @(def arities-okp-implies-arity)

 @(def arities-okp-implies-logicp)

 <p>Now we turn to the well-formedness theorem for a clause processor,
 @('cl-proc').  Let @('(cl-proc x ...)') be a legal call on distinct variable
 symbols.  The theorem establishes that @('cl-proc') returns a list of clauses
 when given a clause, provided certain functions have the expected arities.
 But the recognizer for a clause is the function @(tsee logic-term-listp) and
 the recognizer for a list of clauses is @(tsee logic-term-list-listp):</p>

 @({
 General Forms of Well-Formedness Theorem for a Clause Processor
 (implies (and (logic-term-listp x w)
               (arities-okp '<alist> w))
          (logic-term-list-listp (cl-proc x ...) w))

 (implies (and (logic-term-listp x w)
               (arities-okp '<alist> w))
          (logic-term-list-listp (clauses-result (cl-proc x ...)) w))
  })

 <p>The first form above is for a @('cl-proc') that returns a single value and
 the second form is for a @('cl-proc') that returns multiple values.</p>

 <p>The discussion about metafunctions, above, applies here as well.
 @('<Alist>') is an alist pairing function symbols with their assumed arities.
 You may omit or reorder the hypotheses and you may use different variable
 symbols in place of @('x') and @('w'), but they must be distinct and different
 from the variables in the ``@('...').''</p>

 <h4>Runtime Effects</h4>

 <p>In the absence of a @(':well-formedness-guarantee'), if a metafunction or
 clause processor is applied during a proof and produces @('val'), then certain
 checks are made on @('val') before it is used in the proof attempt.  In the
 case of a metafunction, @('(logic-termp val (w state))') is checked and
 @('val') is scanned to ensure that it contains no forbidden function symbols.
 In the case of a clause processor, @('(logic-term-list-listp val (w state))')
 is checked and @('val') is scanned to ensure that it contains no forbidden
 function symbols.</p>

 <p>If @('val') is large (e.g., because the input is large), these checks can
 take more time than the metafunction or clause processor did to produce
 @('val')!  It is for this reason that we provide for
 @(':well-formedness-guarantee')s.</p>

 <p>When a @(':well-formedness-guarantee') is provided no checks are made on
 @('val').  However, ACL2 will check that the arity alist(s) involved in the
 guarantee still correctly shows the arities of the function symbols listed.
 Because those function symbols were not forbidden when the guarantee was made
 and are prohibited from being forbidden thereafter, no check is necessary to
 ensure that no forbidden symbols are introduced into the proof.</p>")

(defxdoc well-founded-relation

; This topic is appropriately redefined by (define well-founded-relation ...)
; in books/kestrel/utilities/world-queries.lisp.

  :parents (rule-classes)
  :short "Show that a relation is well-founded on a set"
  :long "<p>See @(see well-founded-relation-rule) for discussion of
 well-founded relations in ACL2.  A related utility,
 @('well-founded-relation'), may be found in the @(see community-books), file
 @('kestrel/utilities/world-queries.lisp').</p>")

(defxdoc well-founded-relation-rule
  :parents (rule-classes)
  :short "Show that a relation is well-founded on a set"
  :long "<p>See @(see rule-classes) for a general discussion of rule classes,
 including how they are used to build rules from formulas and a discussion of
 the various keywords in a rule class description.</p>

 @({
  Example:
  (defthm lex2p-is-well-founded-relation
    (and (implies (pairp x) (o-p (ordinate x)))
         (implies (and (pairp x)
                       (pairp y)
                       (lex2p x y))
                  (o< (ordinate x) (ordinate y))))
    :rule-classes :well-founded-relation)
 })

 <p>The example above creates a @(':well-founded-relation') rule, where of
 course the functions @('pairp'), @('lex2p'), and @('ordinate') would have to
 be defined first.  It establishes that @('lex2p') is a well-founded relation
 on @('pairp')s.  We explain and give details below.</p>

 <p>Exactly two general forms are recognized:</p>

 @({
  General Forms
  (AND (IMPLIES (mp x) (O-P (fn x)))              ; Property 1
       (IMPLIES (AND (mp x)                       ; Property 2
                     (mp y)
                     (rel x y))
                (O< (fn x) (fn y)))),
 })

 <p>or</p>

 @({
  (AND (O-P (fn x))                               ; Property 1
       (IMPLIES (rel x y)                         ; Property 2
                (O< (fn x) (fn y))))
 })

 <p>where @('mp'), @('fn'), and @('rel') are function symbols, @('x') and
 @('y') are distinct variable symbols, and no other @(':well-founded-relation')
 theorem about @('fn') has been proved.  When the second general form is used,
 we act as though the first form were used with @('mp') being the function that
 ignores its argument and returns @('t').  The discussion below therefore
 considers only the first general form.</p>

 <p>Note: We are very rigid when checking that the submitted formula is of one
 of these forms.  For example, in the first form, we insist that all the
 conjuncts appear in the order shown above.  Thus, interchanging the two
 properties in the top-level conjunct or rearranging the hypotheses in the
 second conjunct both produce unrecognized forms.  The requirement that each
 @('fn') be proved well-founded at most once ensures that for each well-founded
 relation, @('fn'), there is a unique @('mp') that recognizes the domain on
 which @('rel') is well-founded.  We impose this requirement simply so that
 @('rel') can be used as a short-hand when specifying the well-founded
 relations to be used in definitions; otherwise the specification would have to
 indicate which @('mp') was to be used.</p>

 <p>We also insist that the new ordering be embedded into the ordinals as
 handled by @(tsee o-p) and @(tsee o<) and not some into previously admitted
 user-defined well-founded set and relation.  This restriction should pose no
 hardship.  If @('mp') and @('rel') were previously shown to be well-founded
 via the embedding @('fn'), and you know how to embed some new set and relation
 into @('mp') and @('rel'), then by composing @('fn') with your new embedding
 and using the previously proved well-founded relation lemma you can embed the
 new set and relation into the ordinals.</p>

 <p>@('Mp') is a predicate that recognizes the objects that are supposedly
 ordered in a well-founded way by @('rel').  We call such an object an
 ``@('mp')-measure'' or simply a ``measure'' when @('mp') is understood.
 Property 1 tells us that every measure can be mapped into an ACL2 ordinal.
 (See @(see o-p).)  This mapping is performed by @('fn').  Property 2 tells us
 that if the measure @('x') is smaller than the measure @('y') according to
 @('rel') then the image of @('x') under @('fn') is a smaller than that of
 @('y'), according to the well-founded relation @(tsee o<).  (See @(see o<).)
 Thus, the general form of a @(':well-founded-relation') formula establishes
 that there exists a @('rel')-order preserving embedding (namely via @('fn'))
 of the @('mp')-measures into the ordinals.  We can thus conclude that @('rel')
 is well-founded on @('mp')-measures.</p>

 <p>Such well-founded relations are used in the admissibility test for
 recursive functions, in particular, to show that the recursion terminates.  To
 illustrate how such information may be used, consider a generic function
 definition</p>

 @({
  (defun g (x) (if (test x) (g (step x)) (base x))).
 })

 <p>If @('rel') has been shown to be well-founded on @('mp')-measures, then
 @('g')'s termination can be ensured by finding a measure, @('(m x)'), with the
 property that @('m') produces a measure:</p>

 @({
  (mp (m x)),                                     ; Defun-goal-1
 })

 <p>and that the argument to @('g') gets smaller (when measured by @('m') and
 compared by @('rel')) in the recursion,</p>

 @({
  (implies (test x) (rel (m (step x)) (m x))).    ; Defun-goal-2
 })

 <p>If @('rel') is selected as the @(':well-founded-relation') to be used in
 the definition of @('g'), the definitional principal will generate and attempt
 to prove @('defun-goal-1') and @('defun-goal-2') to justify @('g').  We show
 later why these two goals are sufficient to establish the termination of
 @('g').  Observe that neither the ordinals nor the embedding, @('fn'), of the
 @('mp')-measures into the ordinals is involved in the goals generated by the
 definitional principal.</p>

 <p>Suppose now that a @(':well-founded-relation') theorem has been proved for
 @('mp') and @('rel').  How can @('rel') be ``selected as the
 @(':well-founded-relation')'' by @(tsee defun)?  There are two ways.  First,
 an @(tsee xargs) keyword to the @(tsee defun) event allows the specification
 of a @(':well-founded-relation').  Thus, the definition of @('g') above might
 be written</p>

 @({
  (defun g (x)
   (declare (xargs :well-founded-relation (mp . rel)))
   (if (test x) (g (step x)) (base x)))
 })

 <p>Alternatively, @('rel') may be specified as the
 @(':default-well-founded-relation') in @(tsee acl2-defaults-table) by
 executing the event</p>

 @({
  (set-well-founded-relation rel).
 })

 <p>When a @(tsee defun) event does not explicitly specify the relation in its
 @(tsee xargs) the default relation is used.  When ACL2 is initialized, the
 default relation is @(tsee o<).</p>

 <p>Finally, though it is probably obvious, we now show that @('defun-goal-1')
 and @('defun-goal-2') are sufficient to ensure the termination of @('g')
 provided @('property-1') and @('property-2') of @('mp') and @('rel') have been
 proved.  To this end, assume we have proved @('defun-goal-1') and
 @('defun-goal-2') as well as @('property-1') and @('property-2') and we show
 how to admit @('g') under the primitive ACL2 definitional principal (i.e.,
 using only the ordinals).  In particular, consider the definition event</p>

 @({
  (defun g (x)
   (declare (xargs :well-founded-relation o<
                   :measure (fn (m x))))
   (if (test x) (g (step x)) (base x)))
 })

 <p>Proof that @('g') is admissible: To admit the definition of @('g') above we
 must prove</p>

 @({
  (o-p (fn (m x)))                        ; *1
 })

 <p>and</p>

 @({
  (implies (test x)                               ; *2
           (o< (fn (m (step x))) (fn (m x)))).
 })

 <p>But *1 can be proved by instantiating @('property-1') to get</p>

 @({
  (implies (mp (m x)) (o-p (fn (m x)))),
 })

 <p>and then relieving the hypothesis with @('defun-goal-1'), @('(mp (m
 x))').</p>

 <p>Similarly, *2 can be proved by instantiating @('property-2') to get</p>

 @({
  (implies (and (mp (m (step x)))
                (mp (m x))
                (rel (m (step x)) (m x)))
           (o< (fn (m (step x))) (fn (m x))))
 })

 <p>and relieving the first two hypotheses by appealing to two instances of
 @('defun-goal-1'), thus obtaining</p>

 @({
  (implies (rel (m (step x)) (m x))
           (o< (fn (m (step x))) (fn (m x)))).
 })

 <p>By chaining this together with @('defun-goal-2'),</p>

 @({
  (implies (test x)
           (rel (m (step x)) (m x)))
 })

 <p>we obtain *2.  Q.E.D.</p>")

(defxdoc wet
  :parents (trace)
  :short "Evaluate a form and print subsequent error trace"
  :long "<p>The acronym ``wet'' stands for ``with-error-trace''.  @('Wet')
 provides a convenient way to obtain a backtrace when evaluation causes a guard
 violation or other error.</p>

 <p>The basic idea is that @('(wet form)') evaluates @('form') and, if there is
 an error, shows a backtrace of calls that led to that error.  Note however
 that by default only calls of user-defined (not built-in) functions
 ``supporting'' @('form') in the following sense will show up in the backtrace:
 those that occur in the macroexpansion of @('form') or (recursively) support
 any of those functions.  So for example, since @('(make-event form)')
 macroexpands to @('(make-event-fn (quote form) ...)'), calls of functions
 occurring in @('form') will likely not show up in the backtrace by default.
 The option @(':fns all') overrides this default, with potential loss of speed;
 more on this below.</p>

 <p>The following example explains the use of @('wet').  First, submit the
 following three definitions:</p>

 @({
  (defun foo (x) (declare (xargs :guard (consp x))) (car x))
  (defun bar (x) (foo (cdr x)))
  (defun g (x) (bar (cdr x)))
 })

 <p>Now imagine you have obtained the following guard violation:</p>

 @({
  ACL2 !>(g '(3 4))

  ACL2 Error in TOP-LEVEL:  The guard for the function call (FOO X),
  which is (CONSP X), is violated by the arguments in the call (FOO NIL).
  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.  See
  :DOC set-guard-checking for information about suppressing this check
  with (set-guard-checking :none), as recommended for new users.

  ACL2 !>
 })

 <p>With @('wet'), you can get a backtrace of user-defined functions.  The
 package prefixes shown below, @('ACL2_*1*_'), indicate that the
 executable-counterparts of the corresponding submitted functions are being
 called; see @(see evaluation).  Don't forget to start with @('(include-book
 \"misc/wet\" :dir :system)').</p>

 @({
  ACL2 !>(wet (g '(3 4)))
  ; Fast loading /projects/acl2/devel/books/misc/wet.fasl

  TTAG NOTE: Adding ttag :TRACE! from the top level loop.

  ACL2 Error in WET:  The guard for the function call (FOO X), which
  is (CONSP X), is violated by the arguments in the call (FOO NIL).
  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.  See
  :DOC set-guard-checking for information about suppressing this check
  with (set-guard-checking :none), as recommended for new users.

  Backtrace stack:
  ----------------
  1. (ACL2_*1*_ACL2::FOO NIL)
  2. (ACL2_*1*_ACL2::BAR (4))
  3. (ACL2_*1*_ACL2::G (3 4))

  ACL2 !>
 })

 <p>By default, large structures are hidden during the printing of the
 backtrace stack.  But you can supply a value for keyword argument
 @(':evisc-tuple') to modify the printing: @('nil') to avoid hiding, else a
 suitable evisc-tuple, as shown below (see @(see evisc-tuple)).</p>

 @({
  ACL2 !>(wet (g '(3 4)) :evisc-tuple (evisc-tuple 1 1 nil nil))
  ; Fast loading /projects/acl2/devel/books/misc/wet.fasl

  TTAG NOTE: Adding ttag :TRACE! from the top level loop.

  ACL2 Error in WET:  The guard for the function call (FOO X), which
  is (CONSP X), is violated by the arguments in the call (FOO NIL).
  To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.  See
  :DOC set-guard-checking for information about suppressing this check
  with (set-guard-checking :none), as recommended for new users.

  Backtrace stack:
  ----------------
  1. (ACL2_*1*_ACL2::FOO ...)
  2. (ACL2_*1*_ACL2::BAR ...)
  3. (ACL2_*1*_ACL2::G ...)

  ACL2 !>
 })

 <p>For a backtrace as a data object, evaluate the form @('(@ wet-stack)').
 But note that this object may not be a legal ACL2 value, for example because
 of the ``@('*1*')'' symbols shown above.</p>

 @({
  General Form:
  (wet form           ; an arbitrary form
       :book bk-form  ; optional, not evaluated
       ;;; the rest are optional and evaluated:
       :evisc-tuple e ; an evisc-tuple
       :fns fns       ; :all, or a list of functions to show in a backtrace
       :compile c     ; :same, t, or nil; default :same (nil if :fns supplied)
 })

 <p>@('Form') is evaluated.  If there is an error, a backtrace stack is printed
 to the standard output (@(tsee *standard-co*)), containing (by default) the
 user-defined function calls made before the error.  Such printing is
 controlled by the @(':evisc-tuple') if supplied; otherwise, hiding of large
 structures will occur.  (Technical detail: by default the global
 abbrev-evisc-tuple is used, if bound; see @(see set-evisc-tuple).</p>

 <p>The @(':fns') option.  As mentioned above, by default the @('wet')
 backtrace shows user-defined functions that syntactically ``support'' the form
 being evaluated.  This default can be overridden by supplying an explicit
 list, @('fns'), of functions, using option @(':fns fns'); these will then be
 the functions whose calls are eligible for inclusion in the backtrace.  The
 special value @(':fns :all') will allow all user-defined function calls in the
 backtrace.  This value can be useful when using @(tsee magic-ev-fncall), for
 example, since the function being applied isn't typically included as a
 syntactic supporter of the form being evaluated.</p>

 <p>The @(':compile') option.  @('Wet') uses the @(tsee trace$) utility to
 modify the definitions of affected functions so that they can record
 information for the backtrace.  As described above, these affected functions
 are those that syntactically ``support'' the form unless specified by the
 @(':fns') option.  As is the case for @('trace$') &mdash; see @(see trace$)
 &mdash; the new definitions of these affected functions may or may not be
 compiled.  For @('trace$') and for @('wet'), the default is to compile the new
 definition if and only if the original definition was compiled, except: For
 @('wet'), if option @(':fns :all') is provided, then the default is not to
 compile the affected definitions.  And for @('trace$') and @('wet'), the
 @(':compile') option overrides the default, to specify what will be compiled:
 value @(':same') to compile each affected function if and only if its original
 definition was compiled, value @('t') to compile all affected functions, and
 value @('nil') to skip compilation.</p>

 <p>The @(':book') option.  @('Wet') actually works by temporarily including a
 community book,</p>

 @({
  (include-book \"misc/wet\" :dir :system)
 })

 <p>and then passing its arguments to macro @('wet!'), defined in that book.
 The keyword argument @(':book') allows you to specify a different book that
 defines a macro @('wet!') to which to pass its arguments.  If the value of
 @(':book') is a string, then the book named by that string is temporarily
 included using @(tsee include-book): @('(include-book \"bk\")').  Otherwise
 @(':book') should be a list of arguments, to be provided (unevaluated) to
 @(tsee include-book), for example @('(\"my-wet\" :dir :my-utils)').  Thus you
 can experiment by copying community book @('books/misc/wet.lisp') to your own
 directory and making modifications to the copy.  If you make changes, we
 invite you to share them with the ACL2 community (see @(see books)).  Note
 that you can also supply @(':book nil'), in which case the definition of
 @('wet!') in your current session will be used without including a book.</p>

 <p>Also see @(see trace$) for a general tracing utility.  As mentioned above,
 @('wet') is implemented using @('trace$').  @('Wet') actually first applies
 @(tsee untrace$); upon completion, @('wet') then applies @(tsee trace$) to
 re-trace any functions that it had untraced, using their original trace
 specs.</p>")

(defxdoc why-brr
  :parents (break-rewrite)
  :short "An explanation of why ACL2 has an explicit @(tsee brr) mode"
  :long "<p>Why isn't @(tsee brr) mode automatically disabled when there are no
 monitored runes?  The reason is that the list of monitored runes is kept in a
 wormhole state.</p>

 <p>See @(see wormhole) for more information on wormholes in general.  But the
 fundamental property of the wormhole function is that it is a logical
 @('no-op'), a constant function that does not take state as an argument.  When
 entering a wormhole, arbitrary information can be passed in (including the
 external state).  That information is used to construct a near copy of the
 external state and that ``wormhole state'' is the one with respect to which
 interactions occur during breaks.  But no information is carried by ACL2 out
 of a wormhole &mdash; if that were allowed wormholes would not be logical
 no-ops.  The only information carried out of a wormhole is in the user's
 head.</p>

 <p>@(tsee Break-rewrite) interacts with the user in a wormhole state because
 the signature of the ACL2 rewrite function does not permit it to modify @(tsee
 state).  Hence, only wormhole interaction is possible.  (This has the
 additional desirable property that the correctness of the rewriter does not
 depend on what the user does during interactive breaks within it; indeed, it
 is logically impossible for the user to affect the course of @(tsee
 rewrite).)</p>

 <p>Now consider the list of monitored runes.  Is that kept in the external
 state as a normal state global or is it kept in the wormhole state?  If it is
 in the external state then it can be inspected within the wormhole but not
 changed.  This is unacceptable; it is common to change the @(see monitor)ed
 rules as the proof attempt progresses, installing monitors when certain rules
 are about to be used in certain contexts.  Thus, the list of monitored runes
 must be kept as a wormhole variable.  Hence, its value cannot be determined
 outside the wormhole, where the proof attempt is ongoing.</p>

 <p>This raises another question: If the list of monitored runes is unknown to
 the rewriter operating on the external state, how does the rewriter know when
 to break?  The answer is simple: it breaks every time, for every rune, if
 @(tsee brr) mode is enabled.  The wormhole is entered (silently), computations
 are done within the wormhole state to determine if the user wants to see the
 break, and if so, interactions begin.  For unmonitored runes and runes with
 false break conditions, the silent wormhole entry is followed by a silent
 wormhole exit and the user perceives no break.</p>

 <p>Thus, the penalty for running with @(tsee brr) mode enabled when there are
 no monitored runes is high: a wormhole is entered on every application of
 every rune and the user is simply unaware of it.  The user who has finally
 unmonitored all runes is therefore strongly advised to carry this information
 out of the wormhole and to do @(':')@(tsee brr) @('nil') in the external state
 when the next opportunity arises.</p>")

(defxdoc with-fast-alist
  :parents (fast-alists acl2-built-ins)
  :short "@('(with-fast-alist name form)') causes @('name') to be a fast alist
for the execution of @('form')."
  :long "<p>Logically, @('with-fast-alist') just returns @('form').</p>

 <p>Under the hood, we cause @('alist') to become a fast alist before executing
 @('form').  If doing so caused us to introduce a new hash table, the hash
 table is automatically freed after @('form') completes.</p>

 <p>More accurately, under the hood @('(with-fast-alist name form)')
 essentially expands to something like:</p>

 @({
   (if (already-fast-alist-p name)
       form
     (let ((<temp> (make-fast-alist name)))
       (prog1 form
              (fast-alist-free <temp>))))
 })

 <p>Practically speaking, @('with-fast-alist') is frequently a better choice
 then just using @(tsee make-fast-alist), and is particularly useful for
 writing functions that can take either fast or slow alists as arguments.  That
 is, consider the difference between:</p>

 @({
   (defun bad (alist ...)
     (let* ((fast-alist (make-fast-alist alist))
            (answer     (expensive-computation fast-alist ...)))
      (prog2$ (fast-alist-free fast-alist)
              answer)))

   (defun good (alist ...)
      (with-fast-alist alist
        (expensive-computation alist ...)))
 })

 <p>Either approach is fine if the caller provides a slow @('alist').  But if
 the input @('alist') is already fast, @('bad') will (perhaps unexpectedly)
 free it!  On the other hand, @('good') is able to take advantage of an
 already-fast argument and will not cause it to be inadvertently freed.</p>

 <p>See also the macro @('with-fast-alists') defined in the community book
 @('\"books/centaur/misc/hons-extra.lisp\"'), which allows you to call @(tsee
 with-fast-alist) on several alists simultaneously.</p>

 <p>The community book @('\"books/centaur/misc/hons-extra.lisp\"') extends the
 @(see b*) macro with the @('with-fast') pattern binder.  That is, after
 executing @('(include-book \"centaur/misc/hons-extra.lisp\" :dir :system)')
 you may write something like this:</p>

 @({
   (b* (...
        ((with-fast a b c ...))
        ...)
     ...)
 })

 <p>which causes @('a'), @('b'), and @('c') to become fast alists until the
 completion of the @('b*') form.</p>

 <p>Note that @('with-fast-alist') will cause logically tail-recursive
 functions not to execute tail-recursively if its cleanup phase happens after
 the tail-recursive call returns.</p>")

(defxdoc with-guard-checking
  :parents (guard acl2-built-ins)
  :short "Suppress or enable guard-checking for a form"
  :long "@({
 Example:

 ; Turn off all guard-checking for the indicated calls of append and car:
 (with-guard-checking :none
                      (append 3 4))

 General Form:
 (with-guard-checking val form)
 })

 <p>where @('val') evaluates to a legal @(see guard)-checking value (see @(see
 set-guard-checking), or evaluate @('*guard-checking-values*') to see the list
 of such values), and @('form') is a form that does not mention @(tsee state)
 (unless there is an active trust tag, in which case mention of @('state') can
 be unsound; see below).  See @(see with-guard-checking-error-triple) and @(see
 with-guard-checking-event) for analogous utilities to be used with forms that
 return @(see error-triple)s.  @('Form') is to be evaluated in a scope such
 that, in essence, @('(set-guard-checking val)') is first executed locally in
 that scope.  However, this guard-checking setting is ignored once evaluation
 passes into raw Lisp functions (see @(see guards-and-evaluation)).</p>

 <p>Note that the addition of @('with-guard-checking') does not change the
 proof obligations generated for guard verification.  However, @(tsee ec-call)
 can be used in order to eliminate those proof obligations.  Consider the
 following example.</p>

 @({
 (defun f1 (x)
   (declare (xargs :guard t))
   (with-guard-checking nil (ec-call (nth t x))))
 })

 <p>Then guard verification succeeds, and evaluation of the form @('(f1 '(1 2
 3))') will return @('1'), without causing a guard violation.  However, if
 @('ec-call') is instead removed from this definition, then guard verification
 will fail, and for good reason, as illustrated by the following example.</p>

 @({
 (defun f2 (x)
   (declare (xargs :guard t))
   (with-guard-checking nil (nth t x)))

 (defun f3 (x)
   (declare (xargs :guard t))
   (f2 x))
 })

 <p>Suppose guard verification were to succeed for @('f2').  Then of course it
 would also succeed for @('f3').  But the call @('(f3 nil)') would then cause a
 raw Lisp error (at least in many host Lisps), because it would lead to a
 raw-Lisp call of @('nth') whose first argument is not a number.</p>

 <p>The remainder of this topic provides a remark for advanced users.
 @('With-guard-checking') is implemented using @(tsee return-last), which you
 can in principle call directly; use @(':')@(tsee trans) or @(':')@(tsee
 trans1) to see how a call of @('with-guard-checking') expands to a
 corresponding call of @('return-last').  However, ACL2 enforces a couple of
 checks that can only be circumvented if there is an active trust tag.  The
 following example from Jared Davis shows why those checks are required
 (in particular, it shows how circumventing them with a trust tag can be
 unsound).  We start by defining our own version of the utility, which omits
 the check that the form has no occurrences of @('state').</p>

 @({
 (defmacro my-with-guard-checking (val form)
   `(with-guard-checking1 (chk-with-guard-checking-arg ,val)
                          ,form))
 })

 <p>Submitting the following event results in the error shown just below
 it.</p>

 @({
 (defun foo (state)
   (declare (xargs :stobjs state
                   :guard (f-boundp-global 'guard-checking-on state)))
   (my-with-guard-checking :all (f-get-global 'guard-checking-on state)))

 ACL2 Error in ( DEFUN FOO ...):  The form
 (RETURN-LAST 'WITH-GUARD-CHECKING1-RAW
              (CHK-WITH-GUARD-CHECKING-ARG :ALL)
              (F-GET-GLOBAL 'GUARD-CHECKING-ON STATE))
 is essentially a call of WITH-GUARD-CHECKING, but without certain checks
 performed.  This is illegal unless there is an active trust tag; see
 :DOC defttag.  To avoid this error without use of a trust tag, call
 WITH-GUARD-CHECKING directly.  Note:  this error occurred in the context
 (WITH-GUARD-CHECKING1 (CHK-WITH-GUARD-CHECKING-ARG :ALL)
                       (F-GET-GLOBAL 'GUARD-CHECKING-ON
                                     STATE)).
 })

 <p>But if we first evaluate @('(defttag t)'), then the @(tsee defun) event
 above is admitted, and we can subsequently prove something that is not
 true.</p>

 @({
 (thm (equal (foo state)
             (f-get-global 'guard-checking-on state)))

 (assert-event (not (equal (foo state)
                           (f-get-global 'guard-checking-on state))))
 })")

(defxdoc with-guard-checking-error-triple
  :parents (guard acl2-built-ins)
  :short "Suppress or enable guard-checking for a form"
  :long "<p>See documentation on the closely related utility, @(see
 with-guard-checking), for relevant background.</p>

 @({
 Example:

 ; Turn off all guard-checking for the indicated calls of append and car:
 (with-guard-checking-error-triple :none
                                    (value (append 3 4)))

 General Form:
 (with-guard-checking-error-triple val form)
 })

 <p>where @('val') evaluates to a legal guard-checking value (see @(see
 set-guard-checking), or evaluate @('*guard-checking-values*') to see the list
 of such values), and @('form') is a form that returns an error triple, @('(mv
 erp val state)'); see @(see error-triple).  Thus,
 @('with-guard-checking-error-triple') is much like @(tsee
 with-guard-checking), but the former is to be used if @('form') mentions the
 ACL2 @(see state); indeed, @('with-guard-checking-error-triple') requires
 @('form') to evaluate to an error triple.  As with @('with-guard-checking'),
 @('form') is evaluated in a context where guard-checking has been set to the
 value of @('val'), but this guard-checking setting is ignored once evaluation
 passes into raw Lisp functions (see @(see guards-and-evaluation)).</p>

 <p>Also see @(see with-guard-checking-event) for a similar utility to be used
 for creating @(see events), specifically, @(see embedded-event-form)s.</p>")

(defxdoc with-guard-checking-event
  :parents (guard acl2-built-ins)
  :short "Suppress or enable guard-checking for an event form"
  :long "<p>See documentation on the closely related utility, @(see
 with-guard-checking), for relevant background.</p>

 @({
 General Forms:
 (with-guard-checking-event val form)
 (with-guard-checking-event (quote val) form)
 })

 <p>where @('val') is a legal guard-checking value (see @(see
 set-guard-checking), or evaluate @('*guard-checking-values*') to see the list
 of such values), and @('form') is a form that returns an @(see error-triple),
 @('(mv erp val state)').  This macro is identical to @(tsee
 with-guard-checking-error-triple), except that the first argument of a call of
 @('with-guard-checking-event') must be a constant as described above, and it
 will generate a legal event form @(see embedded-event-form).  For example, the
 following (uninteresting) form may be placed in a book.</p>

 @({
 (with-guard-checking-event
  :none
  (make-event (prog2$ (car 3) '(defun f (x) x))))
 })

 <p>In raw Lisp, @('(with-guard-checking-event x y)') macroexpands to @('y');
 thus, wrapping an event with @('with-guard-checking-event') has effect only
 inside the ACL2 read-eval-print loop.  Because of that behavior, calls of
 @('with-guard-checking-event') must not be used in function definitions; use
 @(tsee with-guard-checking-error-triple) in such cases.</p>")

(defxdoc with-live-state
  :parents (programming-with-state acl2-built-ins)
  :short "Allow a reference to @('state') in raw Lisp"
  :long "<p>The macro @('with-live-state') is an advanced feature that very few
 users will need (basically, only system hackers).  Indeed, it is untouchable;
 see @(see remove-untouchable) for how to enable calling @('with-live-state')
 in the ACL2 loop.</p>

 @({
  Example Form:
  (with-live-state (assign y 3))

  General form:
  (with-live-state form)
 })

 <p>where form is an arbitrary form with a free reference to the variable
 @(tsee state).</p>

 <p>Logically, @('(with-live-state FORM)') macroexpands to @('FORM').  However,
 in raw Lisp it expands to:</p>

 @({
  (let ((state *the-live-state*))
    FORM)
 })

 <p>If a form that mentions the variable @(tsee state) might be executed in raw
 Lisp &mdash; that is, either outside the ACL2 loop or in raw mode (see @(see
 set-raw-mode)) &mdash; then the surrounding the form with @('with-live-state')
 as shown above can avoid potential warnings or (much less likely) errors.
 Note however that if @('state') is lexically bound to a state other than the
 usual ``live'' state, surprising behavior may occur when evaluating a call of
 @('with-live-state') in raw Lisp or raw mode (either directly by evaluation or
 at compile time), because @('with-live-state') will override that lexical
 binding of @(tsee state) by a lexical binding of @('state') to the usual
 ``live'' state.</p>")

(defxdoc with-local-state
  :parents (stobj acl2-built-ins)
  :short "Locally bind state"
  :long "<p>This is an advanced topic, probably of interest only to system
 developers.</p>

 <p>Consider the following example form:</p>

 @({
  (with-local-state
   (mv-let (result state)
           (compute-with-state x state)
           result))
 })

 <p>This is equivalent to the following form.</p>

 @({
  (with-local-stobj
   state
   (mv-let (result state)
           (compute-with-state x state)
           result))
 })

 <p>By default, this form is illegal, because ACL2 does not have a way to
 unwind all changes to the ACL2 @(see state); we say more on this issue below.
 There may however be situations where you are willing to manage or overlook
 this issue.  In that case you may execute the following form to enable the use
 of @('with-local-state'), by enabling the use of @(tsee with-local-stobj) on
 @('state'); but note that it requires an active trust tag (see @(see
 defttag)).</p>

 @({
  (remove-untouchable create-state t)
 })

 <p>Please be aware that no local @(see state) is actually created, however!
 In particular, users of @('with-local-state') need either to ensure that
 channels are closed and state global variables are returned to their original
 values, or else be willing to live with changes made to state that are not
 justified by the code that has been evaluated.  You are welcome to look in the
 the ACL2 source code at the definition of macro @('channel-to-string'), which
 employs @('with-local-state') to create a local @(see state) for the purpose
 of creating a string.</p>

 <p>Here is an example use of @('with-local-state').  Notice the use of @(tsee
 defttag) &mdash; and indeed, please understand that we are just hacking here,
 and in general it takes significant effort to be sure that one is using
 @('with-local-state') correctly!</p>

 @({
  (defttag t)

  (remove-untouchable create-state t)

  (set-state-ok t)

  (defun foo (state)
    (declare (xargs :mode :program))
    (mv-let
     (channel state)
     (open-input-channel \"my-file\" :object state)
     (mv-let (eofp obj state)
             (read-object channel state)
             (declare (ignore eofp))
             (let ((state (close-input-channel channel state)))
               (mv obj state)))))

  (defun bar ()
    (declare (xargs :mode :program))
    (with-local-state (mv-let (result state)
                              (foo state)
                              result)))

  ; Multiple-value return version:

  (defun foo2 (state)
    (declare (xargs :mode :program))
    (mv-let
     (channel state)
     (open-input-channel \"my-file\" :object state)
     (mv-let (eofp obj state)
             (read-object channel state)
             (let ((state (close-input-channel channel state)))
               (mv eofp obj state)))))

  (defun bar2 ()
    (declare (xargs :mode :program))
    (with-local-state (mv-let (eofp result state)
                              (foo2 state)
                              (mv eofp result))))
 })")

(defxdoc with-local-stobj
  :parents (stobj acl2-built-ins)
  :short "Locally bind a single-threaded object"
  :long "<p>See @(see stobj) for an introduction to single-threaded
  objects.</p>

 @({
  Example Form:
  (with-local-stobj
   st
   (mv-let (result st)
           (compute-with-st x st)
           result))
 })

 <p>@('With-local-stobj') can be thought of as a macro, where the example form
 above expands as follows.</p>

 @({
  (mv-let (result st)
          (let ((st (create-st)))
            (compute-with-st x st))
          (declare (ignore st))
          result)
 })

 <p>However, ACL2 expects you to use @('with-local-stobj'), not its expansion.
 More precisely, stobj creator functions are not allowed except (implicitly)
 via @('with-local-stobj') and in logic-only situations (like theorems and
 hints).  Moreover, neither @('with-local-stobj') nor its expansions are legal
 when typed directly at the top-level loop.  See @(see top-level) for a way to
 use @('with-local-stobj') in the top-level loop.</p>

 @({
  General Forms:
  (with-local-stobj stobj-name mv-let-form)
  (with-local-stobj stobj-name mv-let-form creator-name)
 })

 <p>where @('stobj-name') is the name of a @(see stobj), @('mv-let-form') is a
 call of @(tsee mv-let) that binds @('stobj-name') but does not return
 @('stobj-name'), and if @('creator-name') is supplied then it should be the
 name of the creator function for @('stobj-name'); see @(see defstobj).  For
 the example form above, its expansion would use @('creator-name'), if
 supplied, in place of @('create-st').  Note that @('stobj-name') must not be
 @(tsee state) (the ACL2 state), except in special situations probably of
 interest only to system developers; see @(see with-local-state).</p>

 <p>@('With-local-stobj') can be useful when a stobj is used to memoize
 intermediate results during a computation, yet it is desired not to make the
 @('stobj') a formal parameter for the function and its callers.</p>

 <p>ACL2 can reason about these ``local stobjs,'' and in particular about stobj
 creator functions.  For technical reasons, ACL2 will not allow you to enable
 the @(':EXECUTABLE-COUNTERPART') @(see rune) of a stobj creator function.</p>

 <p>Finally, here is a small example concocted in order to illustrate that
 @('with-local-stobj') calls can be nested.</p>

 @({
  (defstobj st fld1)

  (defun foo ()
    (with-local-stobj
     st ; Let us call this the ``outer binding of st''.
     (mv-let (val10 val20 st)
       (let ((st (update-fld1 10 st)))
         ;; At this point the outer binding of st has fld1 = 10.
         (let ((result (with-local-stobj
                        st ; Let us call this the ``inner binding of st''.
                        (mv-let (val st)
                          (let ((st (update-fld1 20 st)))
                            ;; Now fld1 = 20 for the inner binding of st.
                            (mv (fld1 st) st))
                          val))))
           ;; So result has been bound to 20 above, but here we are once again
           ;; looking at the outer binding of st, where fld1 is still 10.
           (mv (fld1 st) result st)))
       (mv val10 val20))))

  (thm (equal (foo) (mv 10 20))) ; succeeds
 })")

(defxdoc with-output
  :parents (prover-output)
  :short "Suppressing or turning on specified output for an event"
  :long "<p>The macro @('with-output') can be used to control ACL2 output.  It
 can be wrapped around an event to create a new event; see @(see
 embedded-event-form).  The macro @('with-output!') is identical except that
 it does not create an event and, unlike @('with-output'), it can be called in
 code.</p>

 @({
  Examples:

  ; Turn off all output during evaluation of the indicated thm form.
  (with-output
   :off :all
   :gag-mode nil
   (thm (equal (app (app x y) z) (app x (app y z)))))

  ; Prove the indicated theorem with the event summary turned off and
  ; using the :goals setting for gag-mode.
  (with-output
     :off summary
     :gag-mode :goals
     (defthm app-assoc (equal (app (app x y) z) (app x (app y z)))))

  ; Same effect as just above:
  (with-output
     :on summary
     :summary nil
     :gag-mode :goals
     (defthm app-assoc (equal (app (app x y) z) (app x (app y z)))))

  ; Turn on only the indicated parts of the summary.
  (with-output
     :on summary
     :summary (time rules)
     :gag-mode :goals  ; use gag-mode, with goal names printed
     (defthm app-assoc (equal (app (app x y) z) (app x (app y z)))))

  ; Same as specifying :off :all, but showing all output types
  ; (i.e., the value of constant *valid-output-names*):
  (with-output
   :off (error warning warning! observation prove proof-builder event history
               summary proof-tree)
   :gag-mode nil
   (thm (equal (app (app x y) z) (app x (app y z)))))

  ; Same as above, but :stack :push says to save the current
  ; inhibit-output-lst, which can be restored in a subsidiary with-output call
  ; that specifies :stack :pop.
  (with-output
   :stack :push
   :off :all
   :gag-mode nil
   (thm (equal (app (app x y) z) (app x (app y z)))))

  ; Abbreviate printing in gag-mode for guard goals and induction schemes, but
  ; defeat abbreviated printing (if any) for terms.
  (with-output
   :evisc (:gag-mode (evisc-tuple 3 4 nil nil)
           :term nil)
   (defun h (x)
     (declare (xargs :guard t))
     (append (cons (make-list 10) x) x)))

  General Form:
  (with-output :key1 val1 ... :keyk valk form)
 })

 <p>where each @(':keyi') is either @(':off'), @(':on'), @(':stack'),
 @(':summary'), @(':gag-mode'), or @(':evisc'); @('form') evaluates to an @(see
 error-triple); and @('vali') is as follows.  If @(':keyi') is @(':off') or
 @(':on'), then @('vali') is either @(':all'), or else a symbol or non-empty
 list of symbols representing output types that can be inhibited; see @(see
 set-inhibit-output-lst).  Note that @('vali') is not evaluated if @(':keyi')
 is @(':off') or @(':on').  If @(':keyi') is @(':summary'), then @('vali') is
 either @(':all') or a true-list of symbols each of which belongs to the list
 @('*summary-types*').  Note that @('vali') is not evaluated if @(':keyi') is
 @(':summary').  If @(':keyi') is @(':gag-mode'), then @('vali') should
 evaluate to one of the legal values for @(':')@(tsee set-gag-mode).  If
 @(':keyi') is @(':evisc'), then @('vali') should be a @(tsee
 keyword-value-listp), where each key is a legal keyword for the @(':sites')
 keyword argument of @(tsee set-evisc-tuple) other than @(':trace') (that is, a
 member of the list @(`(remove1-eq :trace *evisc-tuple-sites*)`)), and each
 value evaluates to a legal @(see evisc-tuple) for that keyword.  Otherwise
 @(':keyi') is @(':stack'), in which case @('vali') is @(':push') or
 @(':pop'); for now assume that @(':stack') is not specified (we'll return to
 it below).  The result of evaluating the General Form above is to evaluate
 @('form'), but in an environment where output occurs as follows.  If
 @(':on :all') is specified, then every output type is turned on except as
 inhibited by @(':off'); else if @(':off :all') is specified, then every output
 type is inhibited except as specified by @(':on'); and otherwise, the
 currently-inhibited output types are reduced as specified by @(':on') and then
 extended as specified by @(':off').  If @(':gag-mode') and/or @(':evisc') are
 specified, then before modifying how output is inhibited, @(tsee gag-mode)
 and/or the appropriate @(see evisc-tuple)s are set for the evaluation of
 @('form') as specified by the values of those keywords; see @(see
 set-gag-mode) and @(see set-evisc-tuple).  If @('summary') is among the output
 types that are turned on
 (not inhibited), then if @(':summary') is specified, the only parts of the
 summary to be printed will be those specified by the value of @(':summary').
 The correspondence should be clear, except perhaps that @('header') refers to
 the line containing only the word @('Summary'), and @('value') refers to the
 value of the form printed during evaluation of sequences of events as for
 @(tsee progn) and @(tsee encapsulate).</p>

 <p>Note that the handling of the @(':stack') argument pays no attention to the
 @(':summary') argument.</p>

 <p>Note: When the scope of @('with-output') is exited, then all modifications
 are undone: that is, the states of each of @(tsee gag-mode), the @(see
 evisc-tuple)s, and output inhibition are all restored to those which were
 present before the @('with-output') call was entered.</p>

 <p>The @(':stack') keyword's effect is illustrated by the following example,
 where ``@('(encapsulate nil)')'' may replaced by ``@('(progn')'' without any
 change to the output that is printed.</p>

 @({
  (with-output
   :stack :push :off :all
   (encapsulate ()
     (defun f1 (x) x)
     (with-output :stack :pop (defun f2 (x) x))
     (defun f3 (x) x)
     (with-output :stack :pop :off warning (in-theory nil))
     (defun f4 (x) x)))
 })

 <p>The outer @('with-output') call saves the current output settings (as may
 have been modified by earlier calls of @(tsee set-inhibit-output-lst)), by
 pushing them onto a stack, and then turns off all output.  Each inner
 @('with-output') call temporarily pops that stack, restoring the starting
 output settings, until it completes and undoes the effects of that pop.
 Unless @('event') output was inhibited at the top level (see @(see
 set-inhibit-output-lst)), the following output is shown:</p>

 @({
  Since F2 is non-recursive, its admission is trivial.  We observe that
  the type of F2 is described by the theorem (EQUAL (F2 X) X).
 })

 <p>And then, if @('summary') output was not inhibited at the top level, we get
 the rest of this output:</p>

 @({
  Summary
  Form:  ( DEFUN F2 ...)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

  Summary
  Form:  ( IN-THEORY NIL)
  Rules: NIL
  Warnings:  None
  Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
 })

 <p>Note that the use of @(':off warning') suppresses a @('\"Theory\"') warning
 for the @('(in-theory nil)') event, and that in no case will output be printed
 for definitions of @('f1'), @('f3'), or @('f4'), or for the @(tsee
 encapsulate) event itself.</p>

 <p>The following more detailed explanation of @(':stack') is intended only for
 advanced users.  After @(':gag-mode') and @(':evisc') are handled (if present)
 but before @(':on') or @(':off') is handled, the value of @(':stack') is
 handled as follows.  If the value is @(':push'), then @(see state) global
 @('inhibit-output-lst-stack') is modified by pushing the value of @(see state)
 global @('inhibit-output-lst') onto the value of @(see state) global
 @('inhibit-output-lst-stack'), which is @('nil') at the top level.  If the
 value is @(':pop'), then @(see state) global @('inhibit-output-lst-stack') is
 modified only if non-@('nil'), in which case its top element is popped and
 becomes the value of of @(see state) global @('inhibit-output-lst').</p>

 <p>Warning: @('With-output') has no effect in raw Lisp (other than to expand
 to the provided @('form') argument), and hence is disallowed in function
 bodies.  However, you can probably get the effect you want as illustrated
 below, where @('<form>') must return an error-triple @('(mv erp val state)');
 see @(see ld) and see @(see error-triple).</p>

 @({
  Examples avoiding with-output, for use in function definitions:

  ; Inhibit all output:
  (state-global-let*
   ((inhibit-output-lst *valid-output-names*))
   <form>)

  ; Inhibit all warning output:
  (state-global-let*
   ((inhibit-output-lst
     (union-eq (f-get-global 'inhibit-output-lst state)
               '(warning warning!))))
   <form>)
 })

 <p>Note that @('with-output') is allowed in books.  See @(see
 embedded-event-form).</p>")

(defxdoc with-output-lock

; The definition of with-output-lock can be found as (deflock <comments>
; *output-lock*) in ACL2 source file axioms.lisp.

  :parents (parallel-programming acl2-built-ins)
  :short "Provides a mutual-exclusion mechanism for performing output in parallel"
  :long "<p>This documentation topic relates to an experimental extension of
 ACL2, ACL2(p), created initially by David L. Rager.  See @(see
 compiling-acl2p) for how to build an executable image that supports parallel
 execution.  Also see community books directory @('books/parallel/') for
 examples.</p>

 <p>One may wish to perform output while executing code in parallel.  If
 threads are allowed to print concurrently, the output will be interleaved and
 often unreadable.  To avoid this, the user can surround forms that perform
 output with the @('with-output-lock') macro.  Warning: @('with-output-lock')
 may not perform as expected when called directly in the loop; see @(see
 parallelism-at-the-top-level).</p>

 <p>Take the following definition of @('pfib') as an example.</p>

 @({
  (defun pfib (x)
    (declare (xargs :guard (natp x)))
    (cond ((mbe :logic (or (zp x) (<= x 0))
                :exec (<= x 0))
           0)
          ((= x 1) 1)
          (t (plet (declare (granularity t))
                   ((a (prog2$ (cw \"Computing pfib ~x0~%\" (- x 1))
                               (pfib (- x 1))))
                    (b (prog2$ (cw \"Computing pfib ~x0~%\" (- x 2))
                               (pfib (- x 2)))))
                   (+ a b)))))
 })

 <p>With @(see parallel-execution) enabled, a call of @('(pfib 5)')results in
 non-deterministically interleaved output, for example as follows.</p>

 @({
  ACL2 !>(pfib 5)
  CComputing pfib 4
  omputing pfib 3
  ComCpuotmipnugt ipnfgi bp fib3
  2
  Computing pCfiobm put2i
  ng pfib 1
  Computing pfib Co1mp
  uting pfib 0
  CCoommppuuttiinngg  ppffiibb  12

  ComCpuotmipnugt ipnfgi bp fib1
  0
  CoCmopmuptuitnign gp fpifbi b 1
  0
  5
  ACL2 !>
 })

 <p>If the user instead surrounds the calls to @(tsee cw) with the macro
 @('with-output-lock'), as in the following session, the output will no longer
 be interleaved.</p>

 @({
  ACL2 !>
  (defun pfib (x)
    (declare (xargs :guard (natp x)))
    (cond ((mbe :logic (or (zp x) (<= x 0))
                :exec (<= x 0))
           0)
          ((= x 1) 1)
          (t (plet (declare (granularity t))
                   ((a (prog2$ (with-output-lock
                                (cw \"Computing pfib ~x0~%\" (- x 1)))
                               (pfib (- x 1))))
                    (b (prog2$ (with-output-lock
                                (cw \"Computing pfib ~x0~%\" (- x 2)))
                               (pfib (- x 2)))))
                   (+ a b)))))

  <snip>

  ACL2 !>(pfib 5)
  Computing pfib 4
  Computing pfib 3
  Computing pfib 3
  Computing pfib 2
  Computing pfib 2
  Computing pfib 1
  Computing pfib 2
  Computing pfib 1
  Computing pfib 1
  Computing pfib 0
  Computing pfib 1
  Computing pfib 0
  Computing pfib 1
  Computing pfib 0
  5
  ACL2 !>
 })")

(defxdoc with-prover-step-limit
  :parents (miscellaneous)
  :short "Limit the number of steps for proofs"
  :long "<p>Logically, @('(with-prover-step-limit expr form)') is equivalent to
 @('form'), except that if the number of ``prover steps'' executed during
 evaluation of @('form') exceeds a bound specified by the value of @('expr'),
 then that proof will abort.  See @(see set-prover-step-limit) for a related
 utility that sets the limit on prover steps globally instead of setting it for
 just one form, and for a discussion of the notion of ``prover steps'', which
 could change in future ACL2 releases.  For a related utility based on time
 instead of prover steps, see @(see with-prover-time-limit); but as discussed
 in the @(see documentation) for @(tsee set-prover-step-limit), there is at
 best a loose connection between the counting of steps and @(tsee
 with-prover-time-limit).</p>

 <p>The arguments of @('(with-prover-step-limit expr form)') are evaluated.
 However, the (optional) argument @('flg') is not evaluated in
 @('(with-prover-step-limit expr flg form)').</p>

 <p>Depending on the machine you are using, you may have less than a half-hour
 of time before the number of prover steps exceeds the maximum limit on prover
 steps that may be imposed, which is one less than the value of
 @('*default-step-limit*').  But there is no limit unless you explicitly call
 @('with-prover-step-limit') or @(tsee set-prover-step-limit).</p>

 <p>For examples of how step-limits work besides those presented below, see the
 community book @('books/misc/misc2/step-limits.lisp').</p>

 <p>For a utility that returns an indicator of the number of prover steps most
 recently taken, see @(see last-prover-steps).</p>

 <p>Note that @('with-prover-step-limit') may not be called inside definitions,
 and that it is simply the identity macro in raw Lisp.  However,
 @('with-prover-step-limit!') may be called in place of
 @('with-prover-step-limit'), with the effect described here even in raw
 Lisp.</p>

 @({
  Examples:

  ; Limit (mini-proveall) to 100,000 prover steps (which happens to suffice)
  (with-prover-step-limit 100000 (mini-proveall))

  ; Same as above for the inner call of with-prover-step-limit; so the
  ; mini-proveall call completes, but then we get an error because the second
  ; argument of the outer with-prover-step-limit call took more than 200
  ; steps.
  (with-prover-step-limit
   200
   (with-prover-step-limit 100000 (mini-proveall)))

  ; Same as preceding form just above, except that this time there is no error,
  ; because the inner call of with-prover-step-limit has an extra argument
  ; of t inserted into the second argument position, which specifies that this
  ; entire inner call is treated as though it uses no prover steps.
  (with-prover-step-limit
   200
   (with-prover-step-limit 100000 t (mini-proveall)))

  ; The inner call limits (mini-proveall) to 200 prover steps, which fails
  ; almost immediately.
  (with-prover-step-limit 100000 (with-prover-step-limit 200 (mini-proveall)))

  ; Do not limit the number of prover steps, regardless of such a limit imposed
  ; globally or by the surrounding context.
  (with-prover-step-limit nil (mini-proveall))

  ; Same as just above (indeed, nil above is converted to
  ; *default-step-limit*):
  (with-prover-step-limit *default-step-limit* (mini-proveall))

  ; Advanced example: Limit the indicated theorem to 100 steps, and when the
  ; proof does not complete, then put down a label instead.
  (mv-let (erp val state)
          (with-prover-step-limit
           100
           (thm (equal (append (append x x) x)
                       (append x x x))))
          (if erp
              (deflabel foo :doc \"Attempt failed.\")
            (value (list :succeeded-with val))))

  ; Use extra argument of t to avoid ``charging'' steps for the indicated
  ; form.
  (with-prover-step-limit
   500
   (encapsulate
    ()
    (with-prover-step-limit
     500
     t ; Don't charge prover steps for this first defthm.
     (defthm test1
       (equal (append x (append y z))
              (append (append x y) z))
       :rule-classes nil))
    (defthm test2
      (equal (append x (append y z))
             (append (append x y) z))
      :rule-classes nil)))

  General Forms:
  (with-prover-step-limit expr form)
  (with-prover-step-limit expr flg form)
 })

 <p>where @('form') is an arbitrary form to evaluate, and @('expr') evaluates
 to one of the following: @('nil'); a natural number not exceeding the value of
 @('*default-step-limit*'); or the special value, @(':START').  The optional
 extra argument in the second position, @('flg'), must be Boolean if
 supplied.</p>

 <p>If the value of @('expr') is a natural number less than the value of
 @('*default-step-limit*'), then that value is the maximum number of prover
 steps permitted during evaluation of @('form') before an error occurs.  If
 however the value of @('expr') is @('nil') or is the value of
 @('*default-step-limit*'), then no limit is placed on the number of prover
 steps during processing of @('form').  Otherwise, the value of @('expr')
 should be the keyword @(':START'), which is intended for use by the ACL2
 implementation and may have semantics that change with new ACL2 versions.</p>

 <p>Finally we describe the optional extra Boolean argument, @('flg').  If
 @('flg') is @('nil') or omitted, then a running count of prover steps is
 maintained after @('form') is evaluated; otherwise, that count is not affected
 by evaluation of @('form').  To see how this works when @('flg') is nil or
 omitted, consider an event of shape @('(progn form1 form2)'), where we are
 tracking prover steps (say, because of a superior call of
 @('with-prover-step-limit')).  If @('n') is the number of prover steps
 available when the @(tsee progn) form is entered, and if @('s') prover steps
 are executed while evaluating @('form1'), then @('n-s') steps are available
 for evaluation of @('form2') provided @('s') does not exceed @('n');
 otherwise, an error occurs.  In particular, this is the case if @('form1') is
 an event <tt>(with-prover-step-limit k form1')</tt>.  However, if @('form1')
 is an event <tt>(with-prover-step-limit k t form1')</tt>, then because of the
 extra argument of @('t'), no steps are ``charged'' to @('form'); that is, all
 @('n') steps, rather than @('n-s') steps, are available for evaluation of
 @('form2').</p>")

(defxdoc with-prover-time-limit
  :parents (miscellaneous)
  :short "Limit the time for proofs"
  :long "@({
  Examples:

  ; Limit (mini-proveall) to about 1/4 second:
  (with-prover-time-limit 1/4 (mini-proveall))

  ; Limit (mini-proveall) to about 1/4 second, even if surrounding call of
  ; with-prover-time-limit provides for a more restrictive bound:
  (with-prover-time-limit '(1/4) (mini-proveall))

  ; Limit the indicated theorem to about 1/50 second, and if the proof does not
  ; complete or it fails, then put down a label instead.
  (mv-let (erp val state)
          (with-prover-time-limit
           1/50
           (thm (equal (append (append x x) x)
                       (append x x x))))
          (if erp
              (deflabel foo :doc \"Attempt failed.\")
            (value (list :succeeded-with val))))

  General Form:
  (with-prover-time-limit time form)
 })

 <p>where @('time') evaluates to a positive rational number or to a list
 containing such, and @('form') is arbitrary.  Logically,
 @('(with-prover-time-limit time form)') is equivalent to @('form').  However,
 if the time for evaluation of @('form') exceeds the value specified by
 @('time'), and if ACL2 notices this fact during a proof, then that proof will
 abort, for example like this:</p>

 @({
  ACL2 Error in ( DEFTHM PERM-REFLEXIVE ...):  Out of time in the rewriter.
 })

 <p>If there is already a surrounding call of @('with-prover-time-limit') that
 has set up an expiration time, the inner @('with-prover-time-limit') call is
 not allowed to push that time further into the future unless the inner time is
 specified as a list containing a rational, rather than as a rational.</p>

 <p>Note that by default, the time used is runtime (cpu time); to switch to
 realtime (elapsed time), see @(see get-internal-time).</p>

 <p>For a related utility based on prover steps instead of time, see @(see
 with-prover-step-limit); also see @(see set-prover-step-limit).  Those
 utilities have the advantage of having platform-independent behavior, unlike
 time limits, which of course are generally less restrictive for faster
 processors.  But note that the prover steps counted need not correspond
 closely to prover time.  For other utilities that limit time, see @(see
 with-timeout) and @(see oracle-timelimit).</p>

 <p>Although @('with-prover-time-limit') behaves like an ACL2 function in the
 sense that it evaluates both its arguments, it is however actually a macro
 that behaves as follows.  (1) The value of its first (time limit) argument
 affects the evaluation of its second argument (by causing an error during that
 evaluation if the time for completion is insufficient).  (2) The second
 argument can return multiple values (see @(see mv)), which are then returned
 by the call of @('with-prover-time-limit').  (3) Thus, there is not a fixed
 number of values returned by @('with-prover-time-limit').</p>

 <p>If you find that the time limit appears to be implemented too loosely, it
 may be because the prover only checks the time elapsed at certain points
 during the proof process, for example at entry to the rewriter.  For example,
 if you write your own @(tsee clause-processor) that does an expensive
 computation, the time is unlikely to be checked during its execution.  If
 however you find the time limit seems to be ignored even during ordinary
 prover operation, you are encouraged to email an example to the ACL2
 implementors with instructions on how to observe the undesirable behavior.
 This information can perhaps be used to improve ACL2 by the insertion of more
 checks for expiration of the time limit.</p>

 <p>The rest of this documentation topic explains the rather subtle logical
 story, and is not necessary for understanding how to use
 @('with-prover-time-limit').  The ACL2 @(tsee state) object logically contains
 a field called the @('acl2-oracle'), which is an arbitrary true list of
 objects; see @(tsee read-acl2-oracle).  Our claim is that every ACL2 session
 makes sense for <b>some</b> value of @('acl2-oracle') in the initial
 @('state') for that session.  Logically, @('with-prover-time-limit') is a
 no-op, just returning its second value.  But under the hood, it provides a
 ``hint'' for the @('acl2-oracle'), so that (logically speaking) when its first
 element (@(tsee car)) is consulted by ACL2's prover to see if the time limit
 has expired, it gets the ``right'' answer (specifically, either nil if all is
 well or else a message to print if the time limit has expired).  Logically,
 the @('acl2-oracle') is then @(tsee cdr)'ed &mdash; that is, its first element
 is popped off &mdash; so that future results from @('read-acl2-oracle') are
 independent of the one just obtained.</p>")

(defxdoc with-serialize-character
  :parents (serialize acl2-built-ins)
  :short "Control output mode for @('print-object$')"
  :long "<p>See @(see serialize) for a discussion of ``serialization''
 routines, contributed by Jared Davis for saving ACL2 objects in files for
 later loading.</p>

 <p>NOTE: To control the use of the serialize writer by the system, rather than
 by the user (as discussed below), see @(see
 set-serialize-character-system).</p>

 <p>The expression @('(with-serialize-character char form)') evaluates to the
 value of @('form'), but with the serialize-character of the @(tsee state)
 assigned to @('char'), which should be one of @('nil'), @('#\\Y'), or
 @('#\\Z').  We describe the effect of that assignment below.  But note that if
 you are doing this because of one or more specific calls of
 @('print-object$'), such as @('(print-object$ x channel state)'), then you may
 wish instead to evaluate @('(print-object$-ser x serialize-character channel
 state)'), in which case you will not need to use
 @('with-serialize-character').</p>

 @({
  General forms:
  (with-serialize-character nil form)
  (with-serialize-character #Y form)
  (with-serialize-character #Z form)
 })

 <p>where @('form') should evaluate to an @(see error-triple).</p>

 <p>Note that if you prefer to obtain the same behavior (as described below)
 globally, rather than only within the scope of @('with-serialize-character'),
 then use @('set-serialize-character') in a corresponding manner:</p>

 @({
  (set-serialize-character nil state)
  (set-serialize-character #\\Y state)
  (set-serialize-character #\\Z state)
 })

 <p>In each case above, calls of @('print-object$') (see @(see io)) in
 @('form') will produce a readable object.  In the first case, that object is
 printed as one might expect at the terminal, as an ordinary Lisp s-expression.
 But in the other cases, the object is printed by first laying down either
 @('#Y') or @('#Z') (respectively) and then calling @(tsee serialize-write) (or
 more precisely, the underlying function called by @('serialize-write') that
 prints to a stream).</p>

 <p>Consider what happens when the ACL2 reader encounters an object produced as
 described above (in the @('#Y') or @('#Z') case).  When the object was
 written, information was recorded on whether that object was a @(see hons).
 In the case of @('#Z'), the object will be read as a hons if and only if it
 was originally written as a hons.  But in the case of @('#Y'), it will never
 be read as a hons.  Thus, @('#Y') and @('#Z') will behave the same if the
 original written object was not a hons, creating an object that is not a hons.
 For an equivalent explanation and a bit more discussion, see @(see
 serialize-read), in particular the discussion of the hons-mode.  The value
 @(':smart') described there corresponds to @('#Z'), while @(':never')
 corresponds to @('#Y').</p>")

(defxdoc with-stolen-alist
  :parents (fast-alists acl2-built-ins)
  :short "@('(with-stolen-alist name form)') ensures that @('name') is a fast
alist at the start of the execution of @('form').  At the end of execution, it
ensures that @('name') is a fast alist if and only if it was originally.  That
is, if @('name') was not a fast alist originally, its hash table link is freed,
and if it was a fast alist originally but its table was modified during the
execution of @('form'), that table is restored.  Note that any extended table
created from the original fast alist during @('form') must be manually freed."
  :long "<p>Logically, @('with-stolen-alist') just returns @('form').</p>

 <p>Under the hood, we cause @('alist') to become a fast alist before executing
 @('form'), and we check the various conditions outlined above before returning
 the final value.</p>

 <p>Note that @('with-stolen-alist') will cause logically tail-recursive
 functions not to execute tail-recursively if its cleanup phase happens after
 the tail-recursive call returns.</p>")

(defxdoc without-evisc
  :parents (io acl2-built-ins)
  :short "Print output in full"
  :long "@({
  General Form:
  (without-evisc form)
 })

 <p>where @('form') is any expression to evaluate.  The effect is to evaluate
 @('form') as though the @('without-evisc') wrapper were absent, except that
 expressions are printed in full for the ensuing output, regardless of the
 current evisc-tuples (see @(see set-evisc-tuple)).  See @(see set-iprint) for
 an example.</p>

 <p>More precisely, @('without-evisc') binds each of the term-evisc-tuple,
 ld-evisc-tuple, abbrev-evisc-tuple and gag-mode-evisc-tuple to @('nil') (see
 @(see set-evisc-tuple)).  It does not modify the trace evisc-tuple, so trace
 output is not modified by @('without-evisc').  Also note that calls of
 printing functions such as @(tsee fmt) that include explicit evisc-tuples will
 not have those evisc-tuples overridden.  The following example illustrates
 this point.</p>

 @({
  ACL2 !>(without-evisc
          (fms \"~x0~%\"
               (list (cons #0 '((a b ((c d)) e f g) u v w x y)))
               *standard-co*
               state
               (evisc-tuple 2 3 nil nil)))

  ((A B # ...) U V ...)
  <state>
  ACL2 !>
 })

 <p>We conclude with two remarks.  (1) A call of @('without-evisc') on
 expression @('exp') actually invokes a specialized call of @(tsee ld) on a
 one-element list containing @('exp'), which prints the value returned by
 evaluation of @('exp') but actually returns the useless value @('(mv nil
 :invisible state)').  So do not use @('without-evisc') in programs; just use
 it at the top level of the ACL2 read-eval-print loop, or at least the top
 level of @('ld').  (2) Even when using without-evisc, if the ACL2 logical
 @(see world) is part of the value returned, it will be printed in abbreviated
 form because the ACL2 read-eval-print loop always arranges for this to be the
 case, regardless of the ld-evisc-tuple.  For example:</p>

 @({
  ACL2 !>(without-evisc (w state))
  <world>
  ACL2 !>
 })

 <p>An alternative to the use of @('without-evisc') is to explore large objects
 using the ACL2 function @('(walkabout object state)').  Some brief
 documentation is printed when you enter an interactive loop upon evaluating a
 call of @('walkabout').  We may add documentation for @('walkabout') if that
 is requested.</p>")

(defxdoc wof
  :parents (prover-output io)
  :short "Direct standard output and proofs output to a file"
  :long "@({
  Example Form:
  (wof \"tmp\" (pso)) ; same as (psof \"tmp\")

  General Form:
  (wof filename form)
 })

 <p>where @('filename') is a writable filename and @('form') is any form that
 evaluates to an error triple (see @(see programming-with-state)), that is, a
 multiple value of the form @('(mv erp val state)').  All output to channels
 @(tsee standard-co) and @(tsee proofs-co) will be directed to the indicated
 file.  It is acceptable to replace @('filename') with @('(quote
 filename)').</p>

 <p>For a general discussion about redirection of output to a file, see @(see
 output-to-file).</p>

 <p>Note that so-called comment-window output (see @(see cw) and see @(see
 observation-cw)) is not redirected by @('wof') to a file, nor is printing from
 a @(see wormhole).</p>")

(defxdoc world
  :parents (state)
  :short "ACL2 property lists and the ACL2 logical database"
  :long "<p>The ACL2 logical world is a data structure that includes all
 logical content resulting from the @(see command)s evaluated, back through and
 including initialization, but not including commands that have been
 undone (see @(see ubt)).  Thus in particular, the world includes a
 representation of the current logical theory, as well as some extra-logical
 information such as the values of ACL2 @(see table)s.  The rest of this topic
 focuses on the structure of the the ACL2 world and, more generally, the
 ``world'' data structure.</p>

 <p>A ``world'' is a list of triples, each of the form @('(sym prop . val)'),
 implementing the ACL2 notion of property lists.  ACL2 permits the simultaneous
 existence of many property list worlds.  ``The world'' is often used as a
 shorthand for ``the ACL2 logical world'' which is the particular property list
 world used within the ACL2 system to maintain a database that contains rules,
 @(see table)s, and so on.</p>

 <p>Common Lisp provides the notion of ``property lists'' by which one can
 attach ``properties'' and their corresponding ``values'' to symbols.  For
 example, one can arrange for the @(''color') property of the symbol
 @(''box-14') to be @(''purple') and the @(''color') property of the symbol
 @(''triangle-7') to be @(''yellow').  Access to property lists is given via
 the Common Lisp function @('get').  Thus, @('(get 'box-14 'color)') might
 return @(''purple').  Property lists can be changed via the special form
 @('setf').  Thus, @('(setf (get 'box-14 'color) 'blue)') changes the Common
 Lisp property list configuration so that @('(get 'box-14 'color)') returns
 @(''blue').  It should be obvious that ACL2 cannot provide this facility,
 because Common Lisp's @('get') ``function'' is not a function of its argument,
 but instead a function of some implicit state object representing the property
 list settings for all symbols.</p>

 <p>ACL2 provides the functions @('getprop') and @('putprop') which allow one
 to mimic the Common Lisp property list facility.  However, ACL2's @('getprop')
 takes as one of its arguments a list that is a direct encoding of what was
 above called the ``state object representing the property list settings for
 all symbols.''  Because ACL2 already has a notion of ``@(see state)'' that is
 quite distinct from that used here, we call this property list object a
 ``world.''  A world is just a true list of triples.  Each triple is of the
 form @('(sym prop . val)').  This world can be thought of as a slightly
 elaborated form of association list and @('getprop') is a slightly elaborated
 form of @(tsee assoc) that takes two keys.  When @('getprop') is called on a
 symbol, @('s'), property @('p'), and world, @('w'), it scans @('w') for the
 first triple whose @('sym') is @('s') and @('prop') is @('p') and returns the
 corresponding @('val'). @('Getprop') has two additional arguments: one
 controls what it returns if no such @('sym') and @('prop') exist in @('w'),
 and the other allows an extremely efficient implementation.  To set some
 property's value for some symbol, ACL2 provides @('putprop').  @('(putprop sym
 prop val w)') merely returns a new world, @('w''), in which @('(sym prop
 . val)') has been @(tsee cons)ed onto the front of @('w'), thus
 ``overwriting'' the @('prop') value of @('sym') in @('w') to @('val') and
 leaving all other properties in @('w') unchanged.</p>

 <p>One aspect of ACL2's property list arrangement is that it is possible to
 have many different property list worlds.  For example, @(''box-14') can have
 @(''color') @(''purple') in one world and can have @(''color') @(''yes') in
 another, and these two worlds can exist simultaneously because @('getprop') is
 explicitly provided the world from which the property value is to be
 extracted.</p>

 <p>The efficiency alluded to above stems from the fact that Common Lisp
 provides property lists.  Using Common Lisp's provisions behind the scenes,
 ACL2 can ``install'' the properties of a given world into the Common Lisp
 property list state so as to make retrieval via @('getprop') very fast in the
 special case that the world provided to @('getprop') has been installed.  To
 permit more than one installed world, each of which is permitted to be changed
 via @('putprop'), ACL2 requires that worlds be named and these names are used
 to distinguish installed versions of the various worlds.  See @(see
 extend-world) and @(see retract-world) for how to install a world.</p>

 <p>However, the ACL2 system uses a property list world, named
 @(''current-acl2-world'), in which to store the succession of user @(see
 command)s and their effects on the logic.  This world is often referred to in
 our @(see documentation) as ``the world'' though it should be stressed that
 the user is permitted to have worlds and ACL2's is in no way distinguished
 except that the user is not permitted to modify it except via event @(see
 command)s.  The ACL2 world is part of the ACL2 @(see state) and may be
 obtained via @('(w state)').</p>

 <p><b>Warning</b>: The ACL2 world is very large.  Its length as of this
 writing (Version 2.5) is over @('40,000') and it grows with each release.
 Furthermore, some of the values stored in it are pointers to old versions of
 itself.  Printing @('(w state)') is something you should avoid because you
 likely will not have the patience to await its completion.  For these
 practical reasons, the only thing you should do with @('(w state)') is provide
 it to @('getprop'), as in the form</p>

 @({
    (getprop sym prop default 'current-acl2-world (w state))
 })

 <p>or its convenient abbreviation</p>

 @({
    (getpropc sym prop default)
 })

 <p>to inspect properties within it, or to pass it to ACL2 primitives, such as
 theory functions, where it is expected.</p>

 <p>Some ACL2 @(see command) forms, such as theory expressions (see @(see
 theories)) and the values to be stored in tables (see @(see table)), are
 permitted to use the variable symbol @('world') freely with the understanding
 that when these forms are evaluated that variable is bound to @('(w state)').
 Theoretically, this gives those forms complete knowledge of the current
 logical configuration of ACL2.  However, at the moment, few world scanning
 functions have been documented for the ACL2 user.  Instead, supposedly
 convenient macro forms have been created and documented.  For example,
 @('(current-theory :here)'), which is the theory expression which returns the
 currently @(see enable)d theory, actually macroexpands to
 @('(current-theory-fn :here world)').  When evaluated with @('world') bound to
 @('(w state)'), @('current-theory-fn') scans the current ACL2 world and
 computes the set of @(see rune)s currently @(see enable)d in it.</p>")

(defxdoc wormhole
  :parents (state ld)
  :short "@(tsee ld) without @(tsee state) &mdash; a short-cut to a parallel universe"
  :long "<code>
 Example Form:
 ; The following form enters a recursive read-eval-print loop on a
 ; copy of the current state, allowing you to interact with that loop.
 ; Note that the form does not mention the ACL2 state variable!
 ; Evaluate the form below. Inside the resulting loop, define some function,
 ; e.g., with @('(defun foo (x) x)').  Then exit with @(':q') and observe,
 ; e.g., with @(':pe foo'), that the external state did not change.

 (wormhole 'foo
           '(lambda (whs) (set-wormhole-entry-code whs :ENTER))
           nil
           '(list 'hello 'there))
 </code>

 @({
  General Form:
  (wormhole name entry-lambda input form
    :current-package    ...  ; known package name
    :ld-skip-proofsp    ...  ; nil, t or 'include-book
    :ld-redefinition-action  ; nil or '(:a . :b)
    :ld-prompt          ...  ; nil, t, or some prompt printer fn
    :ld-missing-input-ok ... ; nil, t, :warn, or warning message
    :ld-pre-eval-filter ...  ; :all, :query, or some new name
    :ld-pre-eval-print  ...  ; nil, t, or :never
    :ld-post-eval-print ...  ; nil, t, or :command-conventions
    :ld-evisc-tuple     ...  ; nil or '(alist level length hiding-cars)
    :ld-error-triples   ...  ; nil or t
    :ld-error-action    ...  ; :return!, :return, :continue, :error,
                             ;   or (:exit N)
    :ld-query-control-alist  ; alist supplying default responses
    :ld-verbose         ...) ; nil or t
 })

 <p>The keyword arguments above are exactly those of @(tsee ld) (see @(see ld))
 except that three of @(tsee ld)'s keyword arguments are missing: the three
 that specify the channels @(tsee standard-oi), @(tsee standard-co) and @(tsee
 proofs-co), which default in @('wormhole') to ACL2's comment window.</p>

 <p>There are two ways to create and enter a wormhole: @('wormhole') as
 described here and the simpler @(tsee wormhole-eval).  We recommend you read
 this full account of wormholes before using @('wormhole-eval').</p>

 <p>Ignoring the use of @('entry-lambda'), @('wormhole') manufactures a named
 ``wormhole @(see state)'' and calls the general-purpose ACL2 read-eval-print
 loop @(tsee ld) on it.  However, when @('ld') exits, the wormhole evaporates
 and the function @('wormhole') returns @('nil').  The manufactured state is
 like the ``current'' ACL2 @(see state) except for two things.  First, some
 information from the last wormhole state of this name is transferred into the
 new state; this allows a wormhole to maintain some state from one call to the
 next.  Second, some information from the wormhole call itself is transferred
 into the new state; this allows the wormhole to be sensitive to context.
 These two changes to the current state are reflected in the settings @('(@
 wormhole-status)') and @('(@ wormhole-input)') discussed in detail below.</p>

 <p>Note that @('wormhole') may be called from environments in which @(tsee
 state) is not bound.  It is still applicative because it always returns
 @('nil').</p>

 <p>There are some restrictions about what can be done inside a wormhole.  As
 you may imagine, we really do not ``copy the current state'' but rather just
 keep track of how we modified it and undo those modifications upon exit.  In
 particular, when exiting a wormhole, values of state globals (see @(see
 programming-with-state)) are restored to their values at the time the wormhole
 was entered.  Note that information about traced functions is stored in state
 globals (see @(see trace$)); accordingly, all tracing and untracing done
 inside a wormhole is undone upon exit from the wormhole.</p>

 <p>An error is signaled if you try to modify state in an unsupported way.
 For this same reason, wormholes do not allow updating of any user-defined
 single-threaded objects.  See @(see stobj).</p>

 <p>One example wormhole is the implementation of the ACL2 @(tsee
 accumulated-persistence) facility for tracking the frequency with which rules
 are tried.  To implement this feature directly the theorem prover would have
 to take the tracking data as an argument and pass it around so that updates
 could be accumulated.  This would greatly clutter the code.  Instead, the
 tracking data is maintained in a wormhole.  The theorem prover enters the
 wormhole to update the data as rules are tried.  When you request a display of
 the data, @(tsee show-accumulated-persistence) enters the wormhole and prints
 the data.  But the data is never available outside that wormhole.  The ACL2
 system uses a second wormhole to implement the @(tsee brr) facility, allowing
 the user to interact with the rewriter as rules are applied.</p>

 <p>We now specify the arguments and behavior of @('wormhole').</p>

 <p>The @('name') argument must be a quoted constant and is typically a symbol.
 It will be the ``name'' of the wormhole.  A wormhole of that name will be
 created the first time either @('wormhole') or @(tsee wormhole-eval) is
 called.</p>

 <p>Every wormhole name has a ``status.''  The status of a wormhole is stored
 outside of ACL2; it is inaccessible to the ACL2 user except when in the named
 wormhole.  But the status of a wormhole may be set by the user from within the
 wormhole.</p>

 <p>Upon the first call of @('wormhole') or @('wormhole-eval') on a name, the
 status of that name is @('nil').  But in general you should arrange for the
 status to be a cons.  The status is set by the quoted @('lambda') every time
 @('wormhole') is called; but it may also be set in the @('form') argument (the
 first form evaluated in the interactive loop) by assigning to the state global
 variable @('wormhole-status'), as with</p>

 @({
  (assign wormhole-status ...)
 })

 <p>or even by the user interacting with the loop if you do not exit the loop
 with the first form.  The @('car') of the cons should be either @(':ENTER') or
 @(':SKIP') and is called the wormhole's ``entry code.''  The entry code of
 @('nil') or an unexpectedly shaped status is @(':ENTER').  The @('cdr') of the
 cons is arbitrary data maintained by you.</p>

 <p>When @('wormhole') is invoked, the status of the specified name is
 incorporated into the manufactured wormhole state.  In particular, inside the
 wormhole, the status is the value of the state global variable
 @('wormhole-status').  That is, inside the wormhole, the status may be
 accessed by @('(@ wormhole-status)') and set by @('(assign wormhole-status
 ...)'), @('f-get-global') and @('f-put-global').  When @('ld') exits &mdash;
 typically because the form @(':q') was read by @('ld') &mdash; the
 then-current value of wormhole-status is hidden away so that it can be
 restored when this wormhole is entered again.  The rest of the wormhole state
 is lost.</p>

 <p>This allows a sequence of entries and exits to a wormhole to maintain some
 history in the status and this information can be manipulated by ACL2
 functions executing inside the wormhole.</p>

 <p>The second argument to @('wormhole') must be a quoted lambda expression.
 We explain it later.</p>

 <p>The third argument, @('input'), may be any term.  The value of the term is
 passed into the manufactured wormhole state, allowing you to pass in
 information about the calling context.  Inside the wormhole, the @('input') is
 available via @('(@ wormhole-input)').  It could be reassigned via @('(assign
 wormhole-input ...)'), but there is no reason to do that.</p>

 <p>The fourth argument, @('form'), may be any term; when @(tsee ld) is called
 on the manufactured wormhole state, the first form evaluated by @('ld') will
 be the value of @('form').  Note that @('form') will be translated by @('ld').
 Errors, including guard violations, in the translation or execution of that
 first form will leave you in the interactive loop of the wormhole state.</p>

 <p>When used properly, the first form allows you to greet your user before
 reading the first interactive command or simply to do whatever computation you
 want to do inside the wormhole and exit silently.  We give examples below.</p>

 <p>Manufacturing a wormhole state is relatively expensive; in addition, the
 forms executed by @('ld') must be read, translated, and interpreted as with
 any user type-in.  The @('entry-lambda') offers a way to avoid this or, at
 least, to decide whether to incur that expense.</p>

 <p>Before the wormhole state is manufactured and entered, the
 @('entry-lambda') is applied to the current wormhole status with @(tsee
 wormhole-eval).  That @('lambda') application must produce a new wormhole
 status, which is stored as the wormhole's status.  The entry code for the new
 status determines whether @('wormhole') actually manufactures a wormhole state
 and calls @('ld').</p>

 <p>If the entry code for that new status is @(':ENTER') the wormhole state is
 manufactured and entered; otherwise, the new status is simply saved as the
 most recent status but the wormhole state is not manufactured or entered.
 Note therefore that the @('entry-lambda') may be used to perform two
 functions: (a) to determine if it is really necessary to manufacture a state
 and (b) to update the data in the wormhole status as a function of the old
 status without invoking @('ld').</p>

 <p>The @('entry-lambda') must be a quoted lambda expression of at most one
 argument.  Thus, the argument must be either</p>

 @({
  '(lambda (whs) <body>)
 })

 <p>or</p>

 @({
  '(lambda () <body>)
 })

 <p>Note the quote.  If a formal, e.g., @('whs'), is provided, it must be used
 as a variable in the @('lambda') body.  The @('lambda')-expression may contain
 free variables, that is, the body may mention variables other than the
 @('lambda') formal.  These free variables are understood in the caller's
 environment.  These conventions allow us to compile the @('entry-lambda')
 application very efficiently when the guard has been verified.</p>

 <p>The guard on a call of @('wormhole') is the conjunction of the guards on
 the arguments conjoined with the guard on the body of the @('entry-lambda').
 See @(see wormhole-eval) for a discussion of the guard on the
 @('lambda')-expression.</p>

 <p>The functions @(tsee wormhole-statusp), @(tsee wormhole-entry-code), @(tsee
 wormhole-data), @(tsee set-wormhole-entry-code), @(tsee set-wormhole-data),
 and @(tsee make-wormhole-status) may be useful in manipulating entry codes and
 data in the @('entry-lambda').</p>

 <p>Note that you access and manipulate the wormhole's status in two different
 ways depending on whether you're ``outside'' of the wormhole applying the
 quoted @('lambda') or ``inside'' the read-eval-print loop of the wormhole.</p>

 <p>OUTSIDE (@('wormhole-eval')): access via the value of the @('lambda')
 formal and set by returning the new status as the value of the @('lambda')
 body.</p>

 <p>INSIDE (@('ld') phase of @('wormhole')): access via @('(@
 wormhole-status)'), and set via @('(assign wormhole-status ...)').</p>

 <p>Pragmatic Advice on Designing a Wormhole: Suppose you are using wormholes
 to implement some extra-logical utility.  You must contemplate how you will
 use your wormhole's status to store hidden information.  You might be tempted
 to exploit the entry code as part of the status.  For example, you may think
 of @(':ENTER') as indicating that your utility is ``turned on'' and @(':SKIP')
 as indicating that your utility is ``turned off.''  We advise against such a
 design.  We recommend you base your decisions on the wormhole data.  We
 recommend that you set but not read the wormhole entry code to signal whether
 you wish to enter a full-fledged wormhole.  To use the entry code as a flag
 overloads it and invites confusion when your facility is ``turned off'' but
 you have to enter the wormhole for some reason.</p>

 <p>For a behind-the-scenes description of how wormholes work, See @(see
 wormhole-implementation).</p>

 <p>Here are some sample situations handled by @('wormhole-eval') and
 @('wormhole').  Let the wormhole in question be named @('DEMO').  Initially
 its status is @('NIL').  The functions below all maintain the convention that
 the status is either @('nil') or of the form @('(:key . lst)'), where
 @(':key') is either @(':SKIP') or @(':ENTER') and @('lst') is a true-list of
 arbitrary objects.  But since there is no way to prevent the user from
 entering the @('DEMO') wormhole interactively and doing something to the
 status, this convention cannot be enforced.  Thus, the functions below do what
 we say they do, e.g., remember all the values of @('x') ever seen, only if
 they're the only functions messing with the @('DEMO') status.  On the other
 hand, the guards of all the functions below can be verified.  We have
 explicitly declared that the guards on the functions below are to be verified,
 to confirm that they can be.  Guard verification is optional but wormholes
 (and @('wormhole-eval') in particular) are more efficient when guards have
 been verified.  All of the functions defined below return @('nil').</p>

 <p>The examples below build on each other.  If you really want to understand
 wormholes we recommend that you evaluate each of the forms below, in the order
 they are discussed.</p>

 <p><b>Q.</b> How do I create a wormhole that prints its status to the comment
 window?</p>

 @({
  (defun demo-status ()
    (declare (xargs :verify-guards t))
    (wormhole-eval 'demo
                   '(lambda (whs)
                      (prog2$ (cw \"DEMO status:~%~x0~%\" whs)
                              whs))
                   nil))
 })

 <p>Note above that after printing the status to the comment window we return
 the new (unchanged) status @('whs').  Had we just written the call of @('cw'),
 which returns @('nil'), the function would print the status and then set it to
 @('nil')!</p>

 <p><b>Q.</b> How do I use a wormhole to collect every symbol, @('x'), passed
 to the function?</p>

 @({
  (defun demo-collect (x)
    (declare (xargs :verify-guards t))
    (wormhole-eval 'demo
                   '(lambda (whs)
                      (make-wormhole-status whs
                                            (wormhole-entry-code whs)
                                            (if (symbolp x)
                                                (cons x (wormhole-data whs))
                                                (wormhole-data whs))))
                   nil))
 })

 <p>We could have also defined this function this way:</p>

 @({
  (defun demo-collect (x)
    (declare (xargs :verify-guards t))
    (if (symbolp x)
        (wormhole-eval 'demo
                       '(lambda (whs)
                          (set-wormhole-data whs
                                             (cons x (wormhole-data whs))))
                       nil)
        nil))
 })

 <p>Both versions always return @('nil') and both versions collect into the
 wormhole data field just the symbols @('x') upon which @('demo-collect') is
 called.</p>

 <p><b>Q.</b> How do I use @('demo-collect')?  Below is a function that maps
 over a list and computes its length.  But it has been annotated with a call to
 @('demo-collect') on every element.</p>

 @({
   (defun my-len (lst)
     (if (endp lst)
         0
         (+ 1
            (prog2$ (demo-collect (car lst))
                    (my-len (cdr lst))))))
 })

 <p>Thus, for example:</p>

 @({
  ACL2 !>(my-len '(4 temp car \"Hi\" rfix))
  5
  ACL2 !>(demo-status)
  DEMO status:
  (:ENTER RFIX CAR TEMP)
  NIL
  ACL2 !>
 })

 <p><b>Q.</b> How do I set the entry code to @(':ENTER') or @(':SKIP')
 according to whether @('name') is a @('member-equal') of the list of things
 seen so far?  Note that we cannot check this condition outside the wormhole,
 because it depends on the list of things collected so far.  We make the
 decision inside the @('lambda')-expression.  Note that we explicitly check
 that the guard of @('member-equal') is satisfied by the current wormhole
 status, since we cannot rely on the invariant that no other function
 interferes with the status of the @('DEMO') wormhole.  In the case that the
 status is ``unexpected'' we act like the status is @('nil') and set it to
 @('(:SKIP . NIL)').</p>

 @({
  (defun demo-set-entry-code (name)
    (declare (xargs :verify-guards t))
    (wormhole-eval 'demo
                   '(lambda (whs)
                      (if (true-listp (wormhole-data whs))
                          (set-wormhole-entry-code
                           whs
                           (if (member-equal name (wormhole-data whs))
                               :ENTER
                               :SKIP))
                          '(:SKIP . NIL)))
                   nil))
 })

 <p>Thus</p>

 @({
  ACL2 !>(demo-set-entry-code 'monday)
  NIL
  ACL2 !>(demo-status)
  DEMO status:
  (:SKIP RFIX CAR TEMP)
  NIL
  ACL2 !>(demo-set-entry-code 'rfix)
  NIL
  ACL2 !>(demo-status)
  DEMO status:
  (:ENTER RFIX CAR TEMP)
  NIL
  ACL2 !>
 })

 <p><b>Q.</b> Suppose I want to collect every symbol and then, if the symbol
 has an @('ABSOLUTE-EVENT-NUMBER') property in the ACL2 logical world, print
 the defining event with @(':pe') and then enter an interactive loop; but if
 the symbol does not have an @('ABSOLUTE-EVENT-NUMBER'), don't print anything
 and don't enter an interactive loop.</p>

 <p>Here it is not important to know what @('ABSOLUTE-EVENT-NUMBER') is; this
 example just shows that we can use a wormhole to access the ACL2 logical
 world, even in a function that does not take the state as an argument.</p>

 <p>In the code below, we use @('wormhole') instead of @('wormhole-eval'),
 because we might have to access the logical world and enter an interactive
 loop.  But for efficiency we do as much as we can inside the entry
 @('lambda'), where we can check whether @('x') is symbol and collect it into
 the data field of the wormhole status.  Note that if we collect @('x'), we
 also set the entry code to @(':ENTER').  If we don't collect @('x'), we set
 the entry code to @(':SKIP').</p>

 <code>
 (defun collect-symbols-and-print-events (x)
   (declare (xargs :guard t))
   (wormhole 'demo
             '(lambda (whs)
                (if (symbolp x)
                    (make-wormhole-status whs
                                          :ENTER
                                          (cons x (wormhole-data whs)))
                    (set-wormhole-entry-code whs :SKIP)))

 ; The wormhole will not get past here is unless the entry code is
 ; :ENTER.  If we get past here, we manufacture a state, put
 ; x into @('(@ wormhole-input)') and call ld in such a way that the
 ; first form executed is the quoted if-expression below.

             x
             '(if (getpropc (@@ wormhole-input) 'absolute-event-number)
                  (er-progn
                   (mv-let (col state)
                           (fmt \"~%Entering a wormhole on the event name ~x0~%\"
                                (list (cons #\\0 (@@ wormhole-input)))
                                *standard-co* state nil)
                           (declare (ignore col))
                           (value nil))
                   (pe (@@ wormhole-input))
                   (set-ld-prompt 'wormhole-prompt state)
                   (value :invisible))
                  (value :q))
             :ld-verbose nil
             :ld-prompt nil))
 </code>

 <p>The ``first form'' (the @('if')) asks whether the @('wormhole-input')
 (i.e., @('x')) has an @('ABSOLUTE-EVENT-NUMBER') property.  If so, it enters
 an @(tsee er-progn) to perform a sequence of commands, each of which returns
 an ACL2 error triple (see @(see programming-with-state)).  The first form uses
 @(tsee fmt) to print a greeting.  Since @('fmt') returns @('(mv col state)')
 and we must return an error triple, we embed the @('fmt') term in an
 @('(mv-let (col state) ... (value nil))').  The macro @('value') takes an
 object and returns a ``normal return'' error triple.  The second form in the
 @('er-progn') uses the ACL2 history macro @('pe') (see @(see pe)) to print the
 defining event for a name.  The third form sets the prompt of this
 read-eval-print loop to the standard function for printing the wormhole
 prompt.  We silenced the printing of the prompt when we called @('ld'), thanks
 to the @(':ld-prompt nil') keyword option.  More on this below.  The fourth
 form returns the error triple value @(':invisible') as the value of the first
 form.  This prevents @('ld') from printing the value of the first form.  Since
 we have not exited @('ld'), that function just continues by reading the next
 form from the comment window.  The user perceives this as entering a
 read-eval-print loop.  We continue in the loop until the user types
 @(':q').</p>

 <p>On the other branch of the @('if'), if the symbol has no
 @('ABSOLUTE-EVENT-NUMBER') property, we execute the form @('(value :q)'),
 which is the programming equivalent of typing @(':q').  That causes the
 @('ld') to exit.</p>

 <p>The @('ld') special variables set in the call to @('wormhole') and further
 manipulated inside the first form to @('ld') may require explanation.  By
 setting @(':')@(tsee ld-verbose) to @('nil'), we prevent @('ld') from printing
 the familiar ACL2 banner when @('ld') is called.  If @(':ld-verbose nil') is
 deleted, then you would see something like</p>

 @({
  ACL2 Version  4.0.  Level 2.
  ...
  Type (good-bye) to quit completely out of ACL2.
 })

 <p>before the first form is read and evaluated.</p>

 <p>By setting @(':')@(tsee ld-prompt) to @('nil') we prevent @('ld') from
 printing the prompt before reading and evaluating the first form.</p>

 <p>As this example shows, to use full-blown wormholes you must understand the
 protocol for using wormhole status to control whether a wormhole state is
 manufactured for @('ld') and you must also understand programming with @(tsee
 state) and the effects of the various @(tsee ld) ``special variables.''</p>

 <p>From the discussion above we see that wormholes can be used to create
 formatted output without passing in the ACL2 @(tsee state).  For examples see
 @(see cw), in particular the discussion at the end of that documentation
 topic.</p>")

(defxdoc wormhole-data
  :parents (wormhole)
  :short "Determines the wormhole data object from a wormhole status object"
  :long "@({
  General Form:  (wormhole-data whs)
 })

 <p>See @(see wormhole).  Returns the wormhole data from a well-formed wormhole
 status @('whs').  If @('whs') is @('nil') or not well-formed, the data is
 @('nil').</p>")

(defxdoc wormhole-entry-code
  :parents (wormhole)
  :short "Determines the wormhole entry code from a wormhole status object"
  :long "@({
  General Form:  (wormhole-entry-code whs)
 })

 <p>See @(see wormhole).  Returns @(':ENTER') or @(':SKIP') given a well-formed
 wormhole status @('whs').  If @('whs') is @('nil') or not well-formed, the
 entry code is @(':ENTER').</p>")

(defxdoc wormhole-eval
  :parents (wormhole)
  :short "State-saving without state &mdash; a short-cut to a parallel universe"
  :long "@({
  Example Form:
  (wormhole-eval 'demo
     '(lambda (whs)
        (set-wormhole-data whs
                           (cons (cons name info)
                                 (wormhole-data whs))))
     (prog2$ info name))

  General Form:
  (wormhole-eval name lambda varterm)
 })

 <p>where @('name') must be a quoted wormhole name and @('lambda') must be a
 quoted @('lambda')-expression.  The @('lambda')-expression must have at most
 one formal parameter but the body of the @('lambda')-expression may contain
 other variables.  Note that in the example form given above, the @('lambda')
 has one formal, @('whs'), and uses @('name') and @('info') freely.  Note that
 the @('lambda') is quoted.  The third argument of @('wormhole-eval'),
 @('varterm'), is an arbitrary term that should mention all of the free
 variables in the @('lambda')-expression.  That term establishes your ``right''
 to refer to those free variables in the environment in which the
 @('wormhole-eval') expression occurs.  The value of @('varterm') is irrelevant
 and if you provide @('nil') ACL2 will automatically provide a suitable term,
 namely a @('prog2$') form like the one shown in the example above.</p>

 <p>Aside: Exception for ACL2(p) (see @(see parallelism)) to the irrelevance of
 @('varterm').  By default, calls of @('wormhole-eval') employ a lock,
 @('*wormhole-lock*').  To avoid such a lock, include the symbol
 @(':NO-WORMHOLE-LOCK') in @('varterm'); for example, you might replace a last
 argument of @('nil') in @('wormhole-eval') by @(':NO-WORMHOLE-LOCK').  End of
 Aside.</p>

 <p>See @(see wormhole) for a full explanation of wormholes.  Most relevant
 here is that every wormhole has a name and a status.  The status is generally
 a cons pair whose @('car') is the keyword @(':ENTER') or the keyword
 @(':SKIP') and whose @('cdr') is an arbitrary object used to store information
 from one wormhole call to the next.</p>

 <p>Here is a succinct summary of @('wormhole-eval').  If the
 @('lambda')-expression has a local variable, @('wormhole-eval') applies the
 @('lambda')-expression to the wormhole status of the named wormhole and
 remembers the value as the new wormhole status.  If the @('lambda') has no
 formal parameter, the @('lambda') is applied to no arguments and the value is
 the new status.  @('Wormhole-eval') returns @('nil').  Thus, the formal
 parameter of the @('lambda')-expression, if provided, denotes the wormhole's
 hidden status information; the value of the @('lambda') is the new status and
 is hidden away.</p>

 <p>The guard of a @('wormhole-eval') call is the guard of the body of the
 @('lambda')-expression, with a fresh variable symbol used in place of the
 formal so that no assumptions are possible about the hidden wormhole status.
 If the guard of a @('wormhole-eval') is verified, the call is macroexpanded
 inline to the evaluation of the body in a suitable environment.  Thus, it can
 be a very fast way to access and change hidden state information, but the
 results must remain hidden.  To do arbitrary computations on the hidden state
 (i.e., to access the ACL2 @(tsee state) or logical @(see world) or to interact
 with the user) see @(see wormhole).</p>

 <p>Functions that are probably useful in the body of the @(tsee lambda) or the
 guard of a function using @('wormhole-eval') include the following: @(tsee
 wormhole-statusp), @(tsee wormhole-entry-code), @(tsee wormhole-data), @(tsee
 set-wormhole-entry-code), @(tsee set-wormhole-data), and @(tsee
 make-wormhole-status).</p>

 <p>See @(see wormhole) for a series of example uses of @('wormhole-eval') and
 @('wormhole').</p>

 <p>For a behind-the-scenes description of how wormholes work, See @(see
 wormhole-implementation).</p>")

(defxdoc wormhole-implementation
  :parents (wormhole)
  :short "Notes on how wormholes are implemented"
  :long "<p>What happens when you call @(tsee wormhole)?  Recall that a typical
 call of the function looks like this:</p>

 @({
  (wormhole 'name
            '(lambda (whs) ...)
            input
            form
            :ld-verbose ...
            ...)
 })

 <p>A brief recap of the advertised semantics for @('wormhole') establishes our
 terminology: When the above @('wormhole') is evaluated, the
 @('lambda')-expression is applied to the wormhole's status and the result is
 stored as the new status.  Then, if the entry-code of the new status is
 @(':ENTER'), @(tsee ld) is invoked on a copy of the ``current state'' with the
 specified @('ld-') ``special variables;'' output is directed to the comment
 window.  In that copy of the state, the state-global variable
 @('wormhole-input') is set to the value of @('input') and the state-global
 variable @('wormhole-status') is set to the (new) status computed by the
 @('lambda')-expression.  Thus, inside the wormhole, @('(@ wormhole-input)')
 returns the list of inputs, @('(@ wormhole-status)') returns the current
 status, and @('(assign wormhole-status ...)') sets the wormhole's status.  The
 first form executed by the @('ld') is the value of @('form') and unless that
 form returns @('(value :q)'), causing the @('ld') to quit, the @('ld')
 proceeds to take subsequent input from the comment window.  Upon exiting from
 @('ld'), the wormhole state ``evaporates.''  The wormhole's status upon exit
 is remembered and restored the next time the wormhole is entered.</p>

 <p>Here is what really happens.</p>

 <p>Each wormhole's status is recorded in an alist stored in a Common Lisp
 global variable named @('*wormhole-status-alist*').  This variable is not part
 of the ACL2 state.  If you exit the ACL2 loop with @(':q') you can inspect the
 value of @('*wormhole-status-alist*').  When the @('lambda')-expression is
 evaluated it is applied to the value associated with @('name') in the alist
 and the result is stored back into that alist.  This step is performed by
 @(tsee wormhole-eval).  To make things more efficient, @('wormhole-eval') is
 just a macro that expands into a @('let') that binds the @('lambda') formal to
 the current status and whose body is the @('lambda') body.  Guard clauses are
 generated from the body, with one exception: the @('lambda') formal is
 replaced by a new variable so that no prior assumptions are available about
 the value of the the wormhole status.</p>

 <p>If the newly computed status has an entry code of @(':ENTER') @(tsee ld)
 will be invoked.  But we don't really copy state, of course.  Instead we will
 invoke @('ld') on the live state, which is always available in the von Neumann
 world in which ACL2 is implemented.  To give the illusion of copying state, we
 will undo changes to the state upon exiting.  To support this, we do two
 things just before invoking @('ld'): we bind a Common Lisp special variable is
 to @('t') to record that ACL2 is in a wormhole, and we initialize an
 accumulator that will be used to record state changes made while in the
 wormhole.</p>

 <p>Then @('ld') is invoked, with first argument, @('standard-oi'), being set
 to @('(cons form *standard-oi*)').  According to the standard semantics of
 @('ld'), this reads and evaluates @('form') and then the forms in the
 specified channel.  The standard channels are directed to and from the
 terminal, which is the physical realization of the comment window.</p>

 <p>All state modifying functions of ACL2 are sensitive to the special variable
 that indicates that evaluation is in a wormhole.  Some ACL2 state-modifying
 functions (e.g., those that modify the file system like @(tsee write-byte$))
 are made to cause an error if invoked inside a wormhole on a file other than
 the terminal.  Others, like @('f-put-global') (the function behind such
 features as @('assign') and maintenance of the ACL2 logical world by such
 events as @(tsee defun) and @(tsee defthm)) are made to record the old value
 of the state component being changed; these records are kept in the
 accumulator initialized above.</p>

 <p>Upon exit from @('ld') for any reason, the final value of @('(@
 wormhole-status)') is stored in @('*wormhole-status-alist*') and then the
 accumulator is used to ``undo'' all the state changes.</p>

 <p>@('Wormhole') always returns @('nil').</p>")

(defxdoc wormhole-p
  :parents (wormhole)
  :short "Predicate to determine if you are inside a @(tsee wormhole)"
  :long "<p>See @(see wormhole) for a discussion of wormholes.  @('(Wormhole-p
 state)') returns @('(mv nil t state)') when evaluated inside a wormhole, else
 @('(mv nil nil state)').</p>")

(defxdoc wormhole-statusp
  :parents (wormhole)
  :short "Predicate recognizing well-formed wormhole status object"
  :long "@({
  General Form:  (wormhole-statusp whs)
 })

 <p>See @(see wormhole).  This predicate is useful in guards for wormholes.  It
 checks whether @('whs') is either @('nil') or a cons whose car is @(':ENTER')
 or @(':SKIP').</p>")

(defxdoc |What Is ACL2(Q)|
  :parents (|Pages Written Especially for the Tours|)
  :short "What Is ACL2?"
  :long "<p><see topic='@(url |What is a Mathematical Logic(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>ACL2 is a <b>mathematical logic</b> together with a <b>mechanical theorem
 prover</b> to help you reason in the logic.</p>

 <p>The logic is just a subset of applicative <see topic='@(url
 |Common Lisp|)'>Common Lisp</see>.  (This link takes you off the main route of
 the tour.  You'll see some Common Lisp on the tour, so visit this later!)</p>

 <p>The theorem prover is an ``industrial strength'' version of the Boyer-Moore
 theorem prover, Nqthm.</p>

 <p><b>Models</b> of all kinds of computing systems can be built in ACL2, just
 as in Nqthm, even though the formal logic is Lisp.</p>

 <p>Once you've built an ACL2 model of a system, you can run it.</p>

 <p>You can also use ACL2 to prove theorems about the model.</p>

 <p><see topic='@(url |What is a Mathematical Logic(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |What is Required of the User(Q)|
  :parents (|Pages Written Especially for the Tours|)
  :short "What is Required of the User?"
  :long "<p><see topic='@(url
 |How Long Does It Take to Become an Effective User(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>It is not easy to build ACL2 models of complex systems.  To do so, the user
 must <b>understand</b></p>

 @({
    * the system being modeled, and

    * ACL2, at least as a programming language.
 })

 <p>It is not easy to get ACL2 to prove hard theorems.  To do so, the user must
 <b>understand</b></p>

 @({
    * the model,

    * ACL2 as a mathematical logic, and

    * be able to construct a proof (in interaction with ACL2).
 })

 <p>ACL2 will help construct the proof but its primary role is to prevent
 logical mistakes.  The creative burden &mdash; the mathematical insight into
 <b>why the model has the desired property</b> &mdash; is the user's
 responsibility.</p>

 <p><see topic='@(url
 |How Long Does It Take to Become an Effective User(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |What is a Mathematical Logic(Q)|
  :parents (|Pages Written Especially for the Tours|)
  :short "What is a Mathematical Logic?"
  :long "<p><see topic='@(url |What is a Mechanical Theorem Prover(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p><img src='res/tours/proof.gif'></img></p>

 <p>A mathematical logic is a formal system of formulas (<b>axioms</b>) and
 <b>rules</b> for deriving other formulas, called <b>theorems</b>.</p>

 <p>A <b>proof</b> is a derivation of a theorem.  To see a concrete proof tree,
 click <see topic='@(url |A Trivial Proof|)'>here</see>.</p>

 <p>Why should you care?  The neat thing about Theorems is that they are
 ``true.''  More precisely, if all the axioms are valid and the rules are
 validity preserving, then anything derived from the axioms via the rules is
 valid.</p>

 <p>So, if you want to determine if some formula is true, <b>prove it</b>.</p>

 <p><see topic='@(url |What is a Mechanical Theorem Prover(Q)|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |What is a Mechanical Theorem Prover(Q)|
  :parents (|Pages Written Especially for the Tours|)
  :short "What is a Mechanical Theorem Prover?"
  :long "<p><see topic='@(url
 |What is a Mechanical Theorem Prover(Q) (cont)|)'><img
 src='res/tours/flying.gif'></img></see></p>

 <p>A <b>mechanical theorem prover</b> is a computer program that finds proofs
 of theorems.</p>

 <p><img src='res/tours/automatic-theorem-prover.gif'></img></p>

 <p>The ideal mechanical theorem prover is <b>automatic</b>: you give it a
 formula and it gives you a proof of that formula or tells you there is no
 proof.</p>

 <p>Unfortunately, automatic theorem provers can be built only for very simple
 logics (e.g., <b>propositional calculus</b>) and even then practical
 considerations (e.g., how many centuries you are willing to wait) limit the
 problems they can solve.</p>

 <p><see topic='@(url |What is a Mechanical Theorem Prover(Q) (cont)|)'><img
 src='res/tours/flying.gif'></img></see></p>")

(defxdoc |What is a Mechanical Theorem Prover(Q) (cont)|
  :parents (|Pages Written Especially for the Tours|)
  :short "What is a Mechanical Theorem Prover? (cont)"
  :long "<p><see topic='@(url |About Models|)'><img
 src='res/tours/flying.gif'></img></see> To get around this, mechanical theorem provers
 often require help from the <b>user</b>.</p>

 <p><img src='res/tours/interactive-theorem-prover-a.gif'></img></p>

 <p>Click <see topic='@(url
 |ACL2 as an Interactive Theorem Prover|)'>here</see> to continue downward.</p>

 <p><see topic='@(url |About Models|)'><img src='res/tours/flying.gif'></img></see></p>")

(defxdoc xargs
  :parents (defun declare)
  :short "Extra arguments, for example to give @(see hints) to @(tsee defun)"
  :long "<p>Common Lisp's @(tsee defun) function does not easily allow one to
 pass extra arguments such as ``@(see hints)''.  ACL2 therefore supports a
 peculiar new declaration (see @(see declare)) designed explicitly for passing
 additional arguments to @(tsee defun) via a keyword-like syntax.  This
 declaration can also be used with @(tsee defmacro), but only for @('xargs')
 keyword @(':guard'); so we restrict attention below to use of @('xargs') in
 @(tsee defun) @(see events).</p>

 <p>The following declaration is nonsensical but does illustrate all of the
 @('xargs') keywords for @(tsee defun) (which are the members of the list
 @('*xargs-keywords*')).</p>

 @({
  (declare (xargs :guard (symbolp x)
                  :guard-debug t
                  :guard-hints ((\"Goal\" :in-theory (theory batch1)))
                  :hints ((\"Goal\" :in-theory (theory batch1)))
                  :measure (- i j)
                  :measure-debug t
                  :mode :logic
                  :non-executable t
                  :normalize nil
                  :otf-flg t
                  :ruler-extenders :basic
                  :split-types t
                  :stobjs ($s)
                  :verify-guards t
                  :well-founded-relation my-wfr))

  General Form:
  (xargs :key1 val1 ... :keyn valn)
 })

 <p>where the keywords and their respective values are as shown below.  Note
 that once ``inside'' the xargs form, the ``extra arguments'' to @(tsee defun)
 are passed exactly as though they were keyword arguments.</p>

 <p>@(':guard')<br></br>

 @('Value') is a term involving only the formals of the function being defined.
 The actual @(see guard) used for the definition is the conjunction of all the
 @(see guard)s and types declared, in the order lexically given, preceded by
 conjuncts corresponding to the @(':')@(tsee stobj) declarations (if any, and
 including @('(state-p state)') if @('state') is a formal).  Also see @(see
 declare).<br/>Note that if no @(':guard') is specified explicitly, then a
 guard of @('t') is assumed, as though one had declared @('(xargs :guard
 t)').  (Note that @('t') is indeed a term involving only the formals; it
 specifies that the guard requirement is always met.)  However, by default, a
 @(':')@(tsee logic) mode function definition will not attempt to verify guards
 unless an explicit @('xargs') @(':guard') declaration is provided.  For
 details on this point, as well as how to change that default behavior, see
 @(see set-verify-guards-eagerness).</p>

 <p>@(':guard-debug')<br></br>

 @('Value'): @('nil') by default, else directs ACL2 to decorate each guard
 proof obligation with hypotheses indicating its sources.  See @(see
 guard-debug).</p>

 <p>@(':guard-hints')<br></br>

 @('Value'): hints (see @(see hints)), to be used during the @(see guard)
 verification proofs as opposed to the termination proofs of the @(tsee
 defun).</p>

 <p>@(':')@(tsee hints)<br></br>

 Value: hints (see @(see hints)), to be used during the termination proofs as
 opposed to the @(see guard) verification proofs of the @(tsee defun).</p>

 <p>@(':measure')<br></br>

 @('Value') is a term involving only the formals of the function being defined.
 This term indicates what is getting smaller in the recursion.  The
 well-founded relation with which successive measures are compared is @(tsee
 o<) by default, but can be changed using the @(':well-founded-relation')
 keyword or with the @(see set-well-founded-relation) event.  Also allowed is a
 special case, @('(:? v1 ... vk)'), where @('(v1 ... vk)') enumerates a subset
 of the formal parameters such that some valid measure involves only those
 formal parameters.  However, this special case is only allowed for definitions
 that are redundant (see @(see redundant-events)) or are executed when skipping
 proofs (see @(see skip-proofs)).  Another special case is @(':measure nil'),
 which is treated the same as if @(':measure') is omitted.  Note that a
 @(':measure') is not allowed for a non-recursive definition (other than the
 ``measure'' @('nil')) unless the definition is part of a @(see mutual-recursion);
 moreover, if a @(':measure') is supplied, then it must be a legal term. Apart
 from these restrictions, the @(':measure') is ignored in @(':')@(tsee program) mode; see
 @(see defun-mode).</p>

 <p>@(':measure-debug')<br></br>

 @('Value'): @('nil') by default, else directs ACL2 to decorate each
 termination proof obligation with hypotheses indicating its sources.  See
 @(see measure-debug).</p>

 <p>@(':mode')<br></br>

 @('Value') is @(':')@(tsee program) or @(':')@(tsee logic), indicating the
 @(tsee defun) mode of the function introduced.  See @(see defun-mode).  If
 unspecified, the @(tsee defun) mode defaults to the default @(tsee defun) mode
 of the current @(see world).  To convert a function from @(':')@(tsee program)
 mode to @(':')@(tsee logic) mode, see @(see verify-termination).</p>

 <p>@(':non-executable')<br></br>

 @('Value') is normally @('t') or @('nil') (the default).  Rather than stating
 @(':non-executable t') directly, which requires @(':')@(tsee logic) mode and
 that the definitional body has a certain form, we suggest using the macro
 @('defun-nx') or @('defund-nx'); see @(see defun-nx).  A third value of
 @(':non-executable') for advanced users is @(':program'), which is generated
 by expansion of @('defproxy') forms; see @(see defproxy).  For another way to
 deal with non-executability, see @(see non-exec).</p>

 <p>@(':normalize')<br></br>

 Value is a flag telling @(tsee defun) whether to perform certain
 simplification before storing the body of the function; see @(see normalize).
 Since the default is to do such @(see normalization), the value supplied is
 only of interest when it is @('nil').  (See @(see defun)).</p>

 <p>@(':')@(tsee otf-flg)<br></br>

 Value is a flag indicating ``onward through the fog''
 (see @(see otf-flg)).  It applies to the @(see guard) verification, as it is
 effectively @('t') during the termination proof.</p>

 <p>@(':ruler-extenders')<br></br>

 For recursive definitions (possibly mutually recursive), @('value') controls
 termination analysis and the resulting stored induction scheme.  See @(see
 rulers) for a discussion of legal values and their effects.</p>

 <p>@(':')@('split-types')<br></br>

 @('Value') is @('t') or @('nil'), indicating whether or not @(see type)s are
 to be proved from the @(see guard)s.  The default is @('nil'), indicating that
 type declarations (see @(see declare)) contribute to the @(see guard)s.  If
 the value is @('t'), then instead, the expressions corresponding to the type
 declarations (see @(see type-spec)) are conjoined into a ``split-type
 expression,'' and guard verification insists that this term is implied by the
 specified @(':guard').  Suppose for example that a definition has the
 following @(tsee declare) form.</p>

 @({
    (declare (xargs :guard (p x y) :split-types t)
             (type integer x)
             (type (satisfies good-bar-p) y))
 })

 <p>Then for guard verification, @('(p x y)') is assumed, and in addition to
 the usual proof obligations derived from the body of the definition, guard
 verification requires a proof that @('(p x y)') implies both @('(integerp x)')
 and @('(good-bar-p y)').  See community book
 @('demos/split-types-examples.lisp') for small examples.</p>

 <p>@(':stobjs')<br></br>

 @('Value') is either a single @(tsee stobj) name or a true list of stobj names
 (see @(see stobj) and see @(see defstobj), and perhaps see @(see
 defabsstobj)).  Every stobj name among the formals of the function must be
 listed, if the corresponding actual is to be treated as a stobj.  That is, if
 a function uses a stobj name as a formal parameter but the name is not
 declared among the @(':stobjs') then the corresponding argument is treated as
 ordinary.  The only exception to this rule is @(tsee state): whether you
 include it or not, @('state') is always treated as a single-threaded object.
 This declaration has two effects.  One is to enforce the syntactic
 restrictions on single-threaded objects.  The other is to strengthen the
 @(tsee guard) of the function being defined so that it includes conjuncts
 specifying that each declared single-threaded object argument satisfies the
 recognizer for the corresponding single-threaded object.</p>

 <p>@(':')@(tsee verify-guards)<br></br>

 @('Value') is @('t') or @('nil'), indicating whether or not @(see guard)s are
 to be verified upon completion of the termination proof.  This flag should
 only be @('t') if the @(':mode') is unspecified but the default @(tsee defun)
 mode is @(':')@(tsee logic), or else the @(':mode') is @(':')@(tsee
 logic).</p>

 <p>@(':')@(tsee well-founded-relation)<br></br>

 @('Value') is a function symbol that is known to be a well-founded relation in
 the sense that a rule of class @(':well-founded-relation') has been proved
 about it.  The effect is to replace the default well-founded relation, which
 is typically @(tsee o<), by the specified value.  See @(see
 well-founded-relation-rule) and see @(see set-well-founded-relation) for
 further discussion, including how to change the default
 well-founded-relation.</p>")

(defxdoc xor
  :parents (basics acl2-built-ins)
  :short "Logical ``exclusive or''"
  :long "<p>@('Xor') is the ACL2 exclusive-or function.  @('(xor P Q)') means
 that either @('P') or @('Q'), but not both, is false (i.e., @('nil')).</p>

 @(def xor)")

(defxdoc |You Must Think about the Use of a Formula as a Rule|
  :parents (|Pages Written Especially for the Tours|)
  :short "You Must Think about the Use of a Formula as a Rule"
  :long "<p><see topic='@(url
 |Using the Associativity of App to Prove a Trivial Consequence|)'><img
 src='res/tours/walking.gif'></img></see></p>

 <p>This is <b>good</b> and <b>bad</b>.</p>

 <p>The good news is that you can <b>program</b> ACL2's simplifier.</p>

 <p>The bad news is that when you command ACL2 to prove a theorem you must give
 some thought to <b>how that theorem is to be used as a rule</b>!</p>

 <p>For example, if after proving @('associativity-of-app') as previously
 shown, you engaged in the mathematically trivial act of proving it again but
 with the equality reversed, you would have programmed ACL2's rewriter to loop
 forever.</p>

 <p>You can avoid adding any rule by using the command:</p>

 <code>
 (defthm associativity-of-app
   (equal (app (app a b) c)
          (app a (app b c)))
   <b>:rule-classes nil</b>)
 </code>

 <p><see topic='@(url
 |Using the Associativity of App to Prove a Trivial Consequence|)'><img
 src='res/tours/walking.gif'></img></see></p>")

(defxdoc zero-test-idioms
  :parents (numbers)
  :short "How to test for 0"
  :long "<p>Below are six commonly used idioms for testing whether @('x') is
 @('0').  @(tsee Zip) and @(tsee zp) are the preferred termination tests for
 recursions down the integers and naturals, respectively.</p>

 @({
  idiom       logical              guard                 primary
              meaning                                 compiled code*

  (equal x 0) (equal x 0)          t                   (equal x 0)

  (eql x 0)   (equal x 0)          t                   (eql x 0)

  (zerop x)   (equal x 0)          x is a number       (= x 0)

  (= x 0)     (equal x 0)          x is a number       (= x 0)

  (zip x)     (equal (ifix x) 0)   x is an integer     (= x 0)

  (zp x)      (equal (nfix x) 0)   x is a natural      (int= x 0)

  (zpf x)     (equal (nfix x) 0)   x is a fixnum >= 0  (eql (the-fixnum x) 0)
 })

 <p>*See @(see guards-and-evaluation), especially the subsection titled
 ``Guards and evaluation V: efficiency issues''.  Primary code is relevant only
 if @(see guard)s are verified.  The ``compiled code'' shown is only
 suggestive.</p>

 <p>The first four idioms all have the same logical meaning and differ only
 with respect to their executability and efficiency.  In the absence of
 compiler optimizing, @('(= x 0)') is probably the most efficient, @('(equal x
 0)') is probably the least efficient, and @('(eql x 0)') is in between.
 However, an optimizing compiler could always choose to compile @('(equal x
 0)') as @('(eql x 0)') and, in situations where @('x') is known at
 compile-time to be numeric, @('(eql x 0)') as @('(= x 0)').  So efficiency
 considerations must, of course, be made in the context of the host
 compiler.</p>

 <p>Note also that @('(zerop x)') and @('(= x 0)') are indistinguishable.  They
 have the same meaning and the same @(see guard), and can reasonably be
 expected to generate equally efficient code.</p>

 <p>Note that @('(zip x)') and @('(zp x)') do not have the same logical
 meanings as the others or each other.  They are not simple tests for equality
 to @('0').  They each coerce @('x') into a restricted domain, @(tsee zip) to
 the integers and @(tsee zp) to the natural numbers, choosing @('0') for @('x')
 when @('x') is outside the domain.  Thus, @('1/2'), @('#c(1 3)'), and
 @(''abc'), for example, are all ``recognized'' as zero by both @(tsee zip) and
 @(tsee zp).  But @(tsee zip) reports that @('-1') is different from @('0')
 while @(tsee zp) reports that @('-1') ``is'' @('0').  More precisely, @('(zip
 -1)') is @('nil') while @('(zp -1)') is @('t').</p>

 <p>Note that the last five idioms all have @(see guard)s that restrict their
 Common Lisp executability.  If these last five are used in situations in which
 @(see guard)s are to be verified, then proof obligations are incurred as the
 price of using them.  If guard verification is not involved in your project,
 then the first five can be thought of as synonymous.</p>

 <p>@(tsee Zip) and @(tsee zp) are not provided by Common Lisp but are
 ACL2-specific functions.  Why does ACL2 provide these functions?  The answer
 has to do with the admission of recursively defined functions and efficiency.
 @(tsee Zp) is provided as the zero-test in situations where the controlling
 formal parameter is understood to be a natural number.  @(tsee Zip) is
 analogously provided for the integer case.  We illustrate below.</p>

 <p>Here is an admissible definition of factorial</p>

 @({
  (defun fact (n) (if (zp n) 1 (* n (fact (1- n)))))
 })

 <p>Observe the classic recursion scheme: a test against @('0') and recursion
 by @(tsee 1-).  Note however that the test against @('0') is expressed with
 the @(tsee zp) idiom.  Note also the absence of a @(see guard) making explicit
 our intention that @('n') is a natural number.</p>

 <p>This definition of factorial is readily admitted because when @('(zp
 n)')</p>

 <p>is false (i.e., @('nil')) then @('n') is a natural number other than @('0')
 and so @('(1- n)') is less than @('n').  The base case, where @('(zp n)') is
 true, handles all the ``unexpected'' inputs, such as arise with @('(fact -1)')
 and @('(fact 'abc)').  When calls of @('fact') are evaluated, @('(zp n)')
 checks @('(integerp n)') and @('(> n 0)').  @(see Guard) verification is
 unsuccessful for this definition of @('fact') because @(tsee zp) requires its
 argument to be a natural number and there is no @(see guard) on @('fact'),
 above.  Thus the primary raw lisp for @('fact') is inaccessible and only the
 @(':')@(tsee logic) definition (which does runtime ``type'' checking) is used
 in computation.  In summary, this definition of factorial is easily admitted
 and easily manipulated by the prover but is not executed as efficiently as it
 could be.</p>

 <p>Runtime efficiency can be improved by adding a @(see guard) to the
 definition.</p>

 @({
  (defun fact (n)
    (declare (xargs :guard (and (integerp n) (>= n 0))))
    (if (zp n) 1 (* n (fact (1- n)))))
 })

 <p>This @(see guard)ed definition has the same termination conditions as
 before &mdash; termination is not sensitive to the @(see guard).  But the
 @(see guard)s can be verified.  This makes the primary raw lisp definition
 accessible during execution.  In that definition, the @('(zp n)') above is
 compiled as @('(= n 0)'), because @('n') will always be a natural number when
 the primary code is executed.  Thus, by adding a @(see guard) and verifying
 it, the elegant and easily used definition of factorial is also efficiently
 executed on natural numbers.</p>

 <p>Now let us consider an alternative definition of factorial in which @('(= n
 0)') is used in place of @('(zp n)').</p>

 @({
  (defun fact (n) (if (= n 0) 1 (* n (fact (1- n)))))
 })

 <p>This definition does not terminate.  For example @('(fact -1)') gives rise
 to a call of @('(fact -2)'), etc.  Hence, this alternative is inadmissible.  A
 plausible response is the addition of a @(see guard) restricting @('n') to the
 naturals:</p>

 @({
  (defun fact (n)
   (declare (xargs :guard (and (integerp n) (>= n 0))))
   (if (= n 0) 1 (* n (fact (1- n)))))
 })

 <p>But because the termination argument is not sensitive to the @(see guard),
 it is still impossible to admit this definition.  To influence the termination
 argument one must change the conditions tested.  Adding a runtime test that
 @('n') is a natural number would suffice and allow both admission and @(see
 guard) verification.  But such a test would slow down the execution of the
 compiled function.</p>

 <p>The use of @('(zp n)') as the test avoids this dilemma.  @(tsee Zp)
 provides the logical equivalent of a runtime test that @('n') is a natural
 number but the execution efficiency of a direct @(tsee =) comparison with
 @('0'), at the expense of a @(see guard) conjecture to prove.  In addition, if
 @(see guard) verification and most-efficient execution are not needed, then
 the use of @('(zp n)') allows the admission of the function without a @(see
 guard) or other extraneous verbiage.</p>

 <p>While general rules are made to be broken, it is probably a good idea to
 get into the habit of using @('(zp n)') as your terminating ``@('0') test''
 idiom when recursing down the natural numbers.  It provides the logical power
 of testing that @('n') is a non-@('0') natural number and allows efficient
 execution.</p>

 <p>We now turn to the analogous function, @(tsee zip).  @(tsee Zip) is the
 preferred @('0')-test idiom when recursing through the integers toward @('0').
 @(tsee Zip) considers any non-integer to be @('0') and otherwise just
 recognizes @('0').  A typical use of @(tsee zip) is in the definition of
 @(tsee integer-length), shown below.  (ACL2 can actually accept this
 definition, but only after appropriate lemmas have been proved.)</p>

 @({
  (defun integer-length (i)
    (declare (xargs :guard (integerp i)))
    (if (zip i)
        0
      (if (= i -1)
        0
        (+ 1 (integer-length (floor i 2))))))
 })

 <p>Observe that the function recurs by @('(floor i 2)').  Hence, calling the
 function on @('25') causes calls on @('12'), @('6'), @('3'), @('1'), and
 @('0'), while calling it on @('-25') generates calls on @('-13'), @('-7'),
 @('-4'), @('-2'), and @('-1').  By making @('(zip i)') the first test, we
 terminate the recursion immediately on non-integers.  The @(see guard), if
 present, can be verified and allows the primary raw lisp definition to check
 @('(= i 0)') as the first terminating condition (because the primary code is
 executed only on integers).</p>")

(defxdoc zerop
  :parents (numbers acl2-built-ins)
  :short "Test an acl2-number against 0"
  :long "<p>@('(zerop x)') is @('t') if @('x') is @('0') and is @('nil')
 otherwise.  Thus, it is logically equivalent to @('(equal x 0)').</p>

 <p>@('(Zerop x)') has a @(see guard) requiring @('x') to be numeric and can be
 expected to execute more efficiently than @('(equal x 0)') in properly @(see
 guard)ed compiled code.</p>

 <p>In recursions down the natural numbers, @('(zp x)') is preferred over
 @('(zerop x)') because the former coerces @('x') to a natural and allows the
 termination proof.  In recursions through the integers, @('(zip x)') is
 preferred.  See @(see zero-test-idioms).</p>

 <p>@('Zerop') is a Common Lisp function.  See any Common Lisp documentation
 for more information.</p>

 @(def zerop)")

(defxdoc zip
  :parents (numbers acl2-built-ins)
  :short "Testing an ``integer'' against 0"
  :long "<p>@('(Zip i)') is logically equivalent to @('(equal (ifix i) 0)') and
 is the preferred termination test for recursion through the integers.  @('(Zip
 i)') returns @('t') if @('i') is @('0') or not an integer; it returns @('nil')
 otherwise.  Thus,</p>

 @({
     i         (zip i)
     3         nil
     0         t
     -2        nil
     5/2       t
     #c(1 3)   t
     'abc      t
 })

 <p>@('(Zip i)') has a @(see guard) requiring @('i') to be an integer.</p>

 <p>For a discussion of the various idioms for testing against @('0'), see
 @(see zero-test-idioms).</p>

 <p>@('Zip') is typically used as the termination test in recursions through
 the integers.  It has the advantage of ``coercing'' its argument to an integer
 and hence allows the definition to be admitted without an explicit type check
 in the body.  @(see Guard) verification allows @('zip') to be compiled as a
 direct @(tsee =)-comparison with @('0').</p>

 @(def zip)")

(defxdoc zp
  :parents (numbers acl2-built-ins)
  :short "Testing a ``natural'' against 0"
  :long "<p>@('(Zp n)') is logically equivalent to @('(equal (nfix n) 0)') and
 is the preferred termination test for recursion down the natural
 numbers. @('(Zp n)') returns @('t') if @('n') is @('0') or not a natural
 number; it returns @('nil') otherwise.  Thus, in the ACL2 logic
 (ignoring the issue of @(see guard)s):</p>

 @({
      n       (zp n)
     3         nil
     0         t
     -1        t
     5/2       t
     #c(1 3)   t
     'abc      t
 })

 <p>@('(Zp n)') has a @(see guard) requiring @('n') to be a natural number.</p>

 <p>For a discussion of the various idioms for testing against @('0'), see
 @(see zero-test-idioms).</p>

 <p>@('Zp') is typically used as the termination test in recursions down the
 natural numbers.  It has the advantage of ``coercing'' its argument to a
 natural and hence allows the definition to be admitted without an explicit
 type check in the body.  @(see Guard) verification allows @('zp') to be
 compiled as a direct @(tsee =)-comparison with @('0').</p>

 @(def zp)")

(defxdoc zpf
  :parents (numbers acl2-built-ins)
  :short "Testing a nonnegative fixnum against 0"
  :long "<p>@('Zpf') is exactly the same as @(tsee zp), except that @('zpf') is
 intended for, and faster for, fixnum arguments.  Its guard is specified with a
 type declaration, @('(type (unsigned-byte 29) x)').  (See @(see declare) and
 see @(see type-spec).)  Also see @(see zp).</p>

 @(def zpf)")

(defxdoc acl2-pc::=
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
attempt an equality (or equivalence) substitution"
  :long "@({
  Examples:
  =     -- replace the current subterm by a term equated to it in
           one of the hypotheses (if such a term exists)
  (= x) -- replace the current subterm by x, assuming that the prover
           can show that they are equal
  (= (+ x y) z)
        -- replace the term (+ x y) by the term z inside the current
           subterm, assuming that the prover can prove
           (equal (+ x y) z) from the current top-level hypotheses
           or that this term or (equal z (+ x y)) is among the
           current top-level hypotheses or the current governors
  (= & z)
        -- exactly the same as above, if (+ x y) is the current
           subterm
  (= (+ x y) z :hints :none)
        -- same as (= (+ x y) z), except that a new subgoal is
           created with the current goal's hypotheses and governors
           as its top-level hypotheses and (equal (+ x y) z) as its
           conclusion
  (= (+ x y) z 0)
        -- exactly the same as immediately above
  (= (p x)
     (p y)
     :equiv iff
     :otf-flg t
     :hints ((\"Subgoal 2\" :BY FOO) (\"Subgoal 1\" :use bar)))
        -- same as (= (+ x y) z), except that the prover uses
           the indicated values for otf-flg and hints, and only
           propositional (iff) equivalence is used (however, it
           must be that only propositional equivalence matters at
           the current subterm)

  General Form:
  (= &optional x y &rest keyword-args)
 })

 <p>If terms @('x') and @('y') are supplied, then replace @('x') by @('y')
 inside the current subterm if they are ``known'' to be ``equal''.  Here
 ``known'' means the following: the prover is called as in the @('prove')
 command (using @('keyword-args')) to prove @('(equal x y)'), except that a
 keyword argument @(':equiv') is allowed, in which case @('(equiv x y)') is
 proved instead, where @('equiv') is that argument.  (See below for how
 governors are handled.)</p>

 <p>Actually, @('keyword-args') is either a single non-keyword or is a list of
 the form @('((kw-1 x-1) ... (kw-n x-n))'), where each @('kw-i') is one of the
 keywords @(':equiv'), @(':otf-flg'), @(':hints').  Here @(':equiv') defaults
 to @('equal') if the argument is not supplied or is @('nil'), and otherwise
 should be the name of an ACL2 equivalence relation.  @(':Otf-flg') and
 @(':hints') give directives to the prover, as explained above; also see @(see
 acl2-pc::prove).  However, no prover call is made if @(':hints') is a
 non-@('nil') atom or if @('keyword-args') is a single non-keyword (more on
 this below).</p>

 <p><i>Remarks on defaults</i></p>

 <p>(1) If there is only one argument, say @('a'), then @('x') defaults to the
 current subterm, in the sense that @('x') is taken to be the current subterm
 and @('y') is taken to be @('a').</p>

 <p>(2) If there are at least two arguments, then @('x') may be the symbol
 @('&'), which then represents the current subterm.  Thus, @('(= a)') is
 equivalent to @('(= & a)').  (Obscure point: actually, @('&') can be in any
 package, except the keyword package.)</p>

 <p>(3) If there are no arguments, then we look for a top-level hypothesis or a
 governor of the form @('(equal c u)') or @('(equal u c)'), where @('c') is the
 current subterm.  In that case we replace the current subterm by @('u').</p>

 <p>As with the @('prove') command, we allow goals to be given ``bye''s in the
 proof, which may be generated by a @(':hints') keyword argument in
 @('keyword-args').  These result in the creation of new subgoals.</p>

 <p>A proof is attempted unless the @(':hints') argument is a non-@('nil') atom
 other than :@('none'), or unless there is one element of @('keyword-args') and
 it is not a keyword.  In that case, if there are any hypotheses in the current
 goal, then what is attempted is a proof of the implication whose antecedent is
 the conjunction of the current hypotheses and governors and whose conclusion
 is the appropriate @('equal') term.</p>

 <p><b>Remarks:</b> (1) It is allowed to use abbreviations in the hints.  (2)
 The keyword :@('none') has the special role as a value of :@('hints') that is
 shown clearly in an example above.  (3) If there are governors, then the new
 subgoal has as additional hypotheses the current governors.</p>")

(defxdoc acl2-pc::acl2-wrap
  :parents (proof-builder-commands)
  :short "(macro) same as @('(lisp x)')"
  :long "@({
  Example:
  (acl2-wrap (pe :here))

  General Form:
  (acl2-wrap form)
 })

 <p>Same as @('(lisp form)').  This is provided for interface tools that want
 to be able to execute the same form in raw Lisp, in the proof-builder, or in
 the ACL2 top-level loop @('(lp)').</p>")

(defxdoc acl2-pc::add-abbreviation
  :parents (proof-builder-commands)
  :short "(primitive)
add an abbreviation"
  :long "<p>Example: @('(add-abbreviation v (* x y))') causes future
 occurrences of @('(* x y)') to be printed as @('(? v)'), until (unless) a
 corresponding invocation of @('remove-abbreviations') occurs.  In this case we
 say that @('v') ``abbreviates'' @('(* x y)').</p>

 @({
  General Form:
  (add-abbreviation var &optional raw-term)
 })

 <p>Let @('var') be an abbreviation for @('raw-term'), if @('raw-term') is
 supplied, else for the current subterm.  Note that @('var') must be a variable
 that does not already abbreviate some term.</p>

 <p>A way to think of abbreviations is as follows.  Imagine that whenever an
 abbreviation is added, say @('v') abbreviates @('expr'), an entry associating
 @('v') to @('expr') is made in an association list, which we will call
 ``@('*abbreviations-alist*')''.  Then simply imagine that @('?') is a function
 defined by something like:</p>

 @({
  (defun ? (v)
    (let ((pair (assoc v *abbreviations-alist*)))
      (if pair (cdr pair)
        (error ...))))
 })

 <p>Of course the implementation isn't exactly like that, since the
 ``constant'' @('*abbreviations-alist*') actually changes each time an
 @('add-abbreviation') instruction is successfully invoked.  Nevertheless, if
 one imagines an appropriate redefinition of the ``constant''
 @('*abbreviations-alist*') each time an @('add-abbreviation') is invoked, then
 one will have a clear model of the meaning of such an instruction.</p>

 <p>The effect of abbreviations on output is that before printing a term, each
 subterm that is abbreviated by a variable @('v') is first replaced by @('(?
 v)').</p>

 <p>The effect of abbreviations on input is that every built-in proof-builder
 command accepts abbreviations wherever a term is expected as an argument,
 i.e., accepts the syntax @('(? v)') whenever @('v') abbreviates a term.  For
 example, the second argument of @('add-abbreviation') may itself use
 abbreviations that have been defined by previous @('add-abbreviation')
 instructions.</p>

 <p>See also @(see acl2-pc::remove-abbreviations) and see @(see
 acl2-pc::show-abbreviations).</p>")

(defxdoc acl2-pc::al
  :parents (proof-builder-commands)
  :short "(macro)
same as apply-linear"
  :long "@({
  Example:
  (al 3)
 })

 <p>See @(see acl2-pc::apply-linear), as @('al') and @('apply-linear') are
 identical.</p>")

(defxdoc acl2-pc::apply-linear
  :parents (proof-builder-commands)
  :short "(primitive)
apply a linear rule"
  :long "@({
  Examples:
  (apply-linear foo)
     -- apply the linear rule `foo'
  (apply-linear (:linear foo))
     -- same as above
  (apply-linear 2)
     -- apply the second linear rule, as displayed by show-linears
  rewrite
     -- apply the first rewrite rule, as displayed by show-rewrites
  (apply-linear foo ((y 7)))
     -- apply the linear rule foo with the substitution
        that associates 7 to the ``free variable'' y
  (apply-linear foo ((x 2) (y 3)) t)
     -- apply the linear rule foo by substituting 2 and 3 for free
        variables x and y, respectively, and also binding all other
        free variables possible by using the current context
        (hypotheses and governors)

  General Form:
  (apply-linear &optional rule-id substitution instantiate-free)
 })

 <p>Add a new top-level hypothesis by applying a @(see linear) rule to the
 current subterm.  The new hypothesis will be created according to the
 information provided by the @('show-linears') (@('sls')) command.</p>

 <p>A short name for this command is @('al').</p>

 <p>We assume familiarity with the interactive @(see proof-builder)'s
 @('rewrite') (@('r')) command (see @(see acl2-pc::rewrite)).  In brief, the
 @('apply-linear') command is an analogue of the @('rewrite') command, but for
 @(see linear) rules in place of @(see rewrite) rules.  There is a significant
 difference: for the @('apply-linear') command, instead of rewriting the
 current subterm as is done by the @('rewrite') command, the conclusion of the
 applicable linear rule, suitably instantiated, is added as a new (and last)
 top-level hypothesis of the goal.  There is another significant difference:
 the automatic application of @(see linear) rules in the theorem prover is
 somewhat more complex than the automatic application of @(see rewrite) rules,
 so the @('apply-linear') command may not correspond as closely to the prover's
 automatic use of a linear rule as the @('rewrite') command corresponds to the
 prover's automatic use of a rewrite rule.</p>

 <p>Below, we refer freely to the @(see documentation) for the interactive
 proof-builder's @('rewrite') command (see @(see acl2-pc::rewrite)).</p>

 <p>The @('rule-id') is treated just as it is by the @('rewrite') command.  If
 @('rule-id') is a positive integer @('n'), then the @('n')th rule as displayed
 by @('show-linears') is the one that is applied.  If @('rule-id') is @('nil')
 or is not supplied, then it is treated as the number 1.  Otherwise,
 @('rule-id') should be either a symbol or else a @(':linear') @(see rune).  If
 a symbol is supplied, then any @(see linear) rule of that name may be
 used.</p>

 <p>Consider the following example.  Suppose that the current subterm is @('(<
 (g (h y)) y)') and that @('foo') is the name of the following linear rule.</p>

 @({
  (implies (true-listp x)
           (< (g x) 15))
 })

 <p>Then the instruction @('(apply-linear foo)') applies @('foo') by adding a
 new hypothesis @('(< (g (h y)) 15)').  In addition, a new goal with conclusion
 @('(true-listp y)') is created unless the current context (top-level
 hypotheses and governors) implies @('(true-listp y)') using only ``trivial
 reasoning'', just as for the @('rewrite') command.</p>

 <p>If the @('rule-id') argument is a number or is not supplied, then the
 system will store an instruction of the form @('(apply-linear name ...)'),
 where @('name') is the name of a @(see linear) rule; this is in order to make
 it easier to replay instructions when there have been changes to the history.
 Except: instead of the name (whether the name is supplied or calculated), the
 system stores the @(see rune) if there is any chance of ambiguity.  (Formally,
 ``ambiguity'' here means that the rune being applied is of the form
 @('(:rewrite name . index)'), where index is not @('nil').)</p>

 <p>Speaking in general, then, an @('apply-linear') instruction works as
 follows.</p>

 <p>First, a @(see linear) rule is selected according to the arguments of the
 instruction.  The selection is made as explained under ``General Form''
 above.</p>

 <p>Next, a trigger term of the rule (see @(see linear)) is matched with the
 current subterm, i.e., a substitution @('unify-subst') is found such that if
 one instantiates that trigger term of the rule with @('unify-subst'), then one
 obtains the current subterm.  If this match fails, then the instruction
 fails.</p>

 <p>Next, an attempt is made to relieve (discharge) the hypotheses, possibly
 handling free variables (see @(see free-variables)), exactly as is done with
 hypotheses when applying the interactive @(see proof-builder) command,
 @('rewrite') (@('r')).</p>

 <p>Finally, the instruction is applied exactly as the @('rewrite') instruction
 is applied, except instead of replacing the current subterm, the rule's
 instantiated conclusion is added to the end of the list of top-level
 hypotheses of the goal.</p>

 <p>Note that as for the @('rewrite') command, the substitution argument should
 be a list whose elements have the form @('(variable term)'), where @('term')
 may contain abbreviations.</p>")

(defxdoc acl2-pc::bash
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
call the ACL2 theorem prover's simplifier"
  :long "@({
  Examples:
  bash -- attempt to prove the current goal by simplification alone
  (bash (\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar))
       -- attempt to prove the current goal by simplification alone,
          with the indicated hints

  General Form:
  (bash &rest hints)
 })

 <p>Call the theorem prover's simplifier, creating a subgoal for each resulting
 goal.</p>

 <p>Notice that unlike @('prove'), the arguments to @('bash') are spread out,
 and are all hints.</p>

 <p>@('Bash') is similar to @('reduce') in that neither of these allows
 induction.  But @('bash') only allows simplification, while @('reduce') allows
 processes @('eliminate-destructors'), @('fertilize'), @('generalize'), and
 @('eliminate-irrelevance').</p>

 <p><b>Remark:</b> All forcing rounds will be skipped (unless there are more
 than 15 subgoals generated in the first forcing round, an injustice that
 should be rectified, but might remain unless there is pressure to fix
 it).</p>")

(defxdoc acl2-pc::bdd
  :parents (proof-builder-commands)
  :short "(atomic macro)
prove the current goal using bdds"
  :long "@({
  Examples:
  bdd
  (bdd :vars nil :bdd-constructors (cons) :prove t :literal :all)
 })

 <p>The general form is as shown in the latter example above, but with any
 keyword-value pairs omitted and with values as described for the @(':')@(tsee
 bdd) hint; see @(see hints).</p>

 <p>This command simply calls the theorem prover with the indicated bdd hint
 for the top-level goal.  Note that if @(':prove') is @('t') (the default),
 then the proof will succeed entirely using bdds or else it will fail
 immediately.  See @(see bdd).</p>")

(defxdoc acl2-pc::bk
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
move backward one argument in the enclosing term"
  :long "@({
  Example and General Form:
  bk
 })

 <p>For example, if the conclusion is @('(= x (* (- y) z))') and the current
 subterm is @('(* (- y) z)'), then after executing @('bk'), the current subterm
 will be @('x').</p>

 <p>Move to the previous argument of the enclosing term.</p>

 <p>This is the same as @('up') followed by @('(dive n-1)'), where @('n') is
 the position of the current subterm in its parent term in the conclusion.
 Thus in particular, the @('nx') command fails if one is already at the top of
 the conclusion.</p>

 <p>Also see @(see acl2-pc::up), @(see acl2-pc::dive), @(see acl2-pc::top), and
 @(see acl2-pc::nx).</p>")

(defxdoc acl2-pc::bookmark
  :parents (proof-builder-commands)
  :short "(macro)
insert matching ``bookends'' comments"
  :long "@({
  Example:
  (bookmark final-goal)

  General Form:
  (bookmark name &rest instruction-list)
 })

 <p>Run the instructions in @('instruction-list') (as though this were a call
 of @('do-all'); see @(see acl2-pc::do-all)), but first insert a begin bookend
 with the given name and then, when the instructions have been completed,
 insert an end bookend with that same name.  See @(see acl2-pc::comm) for an
 explanation of bookends and how they can affect the display of
 instructions.</p>")

(defxdoc acl2-pc::casesplit
  :parents (proof-builder-commands)
  :short "(primitive)
split into two cases"
  :long "@({
  Example:
  (casesplit (< x y)) -- assuming that we are at the top of the
                         conclusion, add (< x y) as a new top-level
                         hypothesis in the current goal, and create a
                         subgoal identical to the current goal except
                         that it has (not (< x y)) as a new top-level
                         hypothesis

  General Form:
  (casesplit expr &optional use-hyps-flag do-not-flatten-flag)
 })

 <p>When the current subterm is the entire conclusion, this instruction adds
 @('expr') as a new top-level hypothesis, and create a subgoal identical to the
 existing current goal except that it has the negation of @('expr') as a new
 top-level hypothesis.  Also see @(see acl2-pc::claim).  The optional arguments
 control the use of governors and the ``flattening'' of new hypotheses, as we
 now explain.</p>

 <p>The argument @('use-hyps-flag') is only of interest when there are
 governors.  (To read about governors, see @(see acl2-pc::hyps)).  In that
 case, if @('use-hyps-flag') is not supplied or is @('nil'), then the
 description above is correct; but otherwise, it is not @('expr') but rather it
 is @('(implies govs expr)') that is added as a new top-level hypothesis (and
 whose negation is added as a top-level hypothesis for the new goal), where
 @('govs') is the conjunction of the governors.</p>

 <p>If @('do-not-flatten-flag') is supplied and not @('nil'), then that is all
 there is to this command.  Otherwise (thus this is the default), when the
 claimed term (first argument) is a conjunction (@('and')) of terms and the
 @('claim') instruction succeeds, then each (nested) conjunct of the claimed
 term is added as a separate new top-level hypothesis.  Consider the following
 example, assuming there are no governors.</p>

 @({
  (casesplit (and (and (< x y) (integerp a)) (equal r s)) t)
 })

 <p>Three new top-level hypotheses are added to the current goal, namely @('(<
 x y)'), @('(integerp a)'), and @('(equal r s)').  In that case, only one
 hypothesis is added to create the new goal, namely the negation of @('(and (<
 x y) (integerp a) (equal r s))').  If the negation of this term had been
 @('claim')ed, then it would be the other way around: the current goal would
 get a single new hypothesis while the new goal would be created by adding
 three hypotheses.</p>

 <p><b>Remark:</b> It is allowed to use abbreviations in the hints.</p>")

(defxdoc acl2-pc::cg
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
change to another goal."
  :long "@({
  Examples:
  (cg (main . 1)) -- change to the goal (main . 1)
  cg              -- change to the next-to-top goal

  General Form:
  (CG &OPTIONAL goal-name)
 })

 <p>Same as @('(change-goal goal-name t)'), i.e. change to the indicated and
 move the current goal to the end of the goal stack.</p>")

(defxdoc acl2-pc::change-goal
  :parents (proof-builder-commands)
  :short "(primitive)
change to another goal."
  :long "@({
  Examples:
  (change-goal (main . 1)) -- change to the goal (main . 1)
  change-goal              -- change to the next-to-top goal

  General Form:
  (change-goal &optional goal-name end-flg)
 })

 <p>Change to the goal with the name @('goal-name'), i.e. make it the current
 goal.  However, if @('goal-name') is @('nil') or is not supplied, then it
 defaults to the next-to-top goal, i.e., the second goal in the stack of goals.
 If @('end-flg') is supplied and not @('nil'), then move the current goal to
 the end of the goal stack; else merely swap it with the next-to-top goal.
 Also see @(see acl2-pc::cg).</p>")

(defxdoc acl2-pc::cl-proc
  :parents (proof-builder-commands)
  :short "(macro) same as @('clause-processor')"
  :long "<p>This is simply an abbreviation for @(see
  acl2-pc::clause-processor).</p>")

(defxdoc acl2-pc::claim
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
add a new hypothesis"
  :long "@({
  Examples:
  (claim (< x y))   -- attempt to prove (< x y) from the current
                       top-level hypotheses and if successful, then
                       add (< x y) as a new top-level hypothesis in
                       the current goal
  (claim (< x y)
         :otf-flg t
         :hints ((\"Goal\" :induct t)))
                    -- as above, but call the prover using the
                       indicated values for the otf-flg and hints
  (claim (< x y) 0) -- as above, except instead of attempting to
                       prove (< x y), create a new subgoal with the
                       same top-level hypotheses as the current goal
                       that has (< x y) as its conclusion
  (claim (< x y) :hints :none)
                    -- same as immediately above

  General Form:
  (claim expr &rest rest-args)
 })

 <p>This command creates a new subgoal with the same top-level hypotheses as
 the current goal but with a conclusion of @('expr').  If @('rest-args') is a
 non-empty list headed by a non-keyword, then there will be no proof attempted
 for the new subgoal.  With that possible exception, @('rest-args') should
 consist of keyword arguments.  The keyword argument @(':do-not-flatten')
 controls the ``flattening'' of new hypotheses, just as with the @('casesplit')
 command (see @(see acl2-pc::casesplit)).  The remaining @('rest-args') are
 used with a call the @('prove') command on the new subgoal, except that if
 @(':hints') is a non-@('nil') atom, then the prover is not called &mdash;
 rather, this is the same as the situation described above, where
 @('rest-args') is a non-empty list headed by a non-keyword.</p>

 <p><b>Remarks:</b> (1) Unlike the @('casesplit') command, the @('claim')
 command is completely insensitive to governors. (2) It is allowed to use
 abbreviations in the hints.  (3) The keyword :@('none') has the special role
 as a value of :@('hints') that is shown clearly in an example above.</p>")

(defxdoc acl2-pc::clause-processor
  :parents (proof-builder-commands)
  :short "(atomic macro)
use a clause-processor"
  :long "<code>
 Example:
 (cl-proc :function
          note-fact-clause-processor
         :hint '(equal a a)) -- Invoke the indicated clause processor function
         with the indicated hint argument (see the beginning of community book
         @('books/clause-processors/basic-examples.lisp').

 General Form:
 (cl-proc &amp;rest cl-proc-args)
 </code>

 <p>Invoke a clause-processor as indicated by cl-proc-args, which is a list of
 arguments that can serve as the value of a @(':')@(tsee clause-processor)
 hint; see @(see hints).</p>

 <p>This command calls the @('prove') command, and hence should only be used at
 the top of the conclusion.</p>")

(defxdoc acl2-pc::comm
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
display instructions from the current interactive session"
  :long "@({
  Examples:
  comm
  (comm 10)

  General Form:
  (comm &optional n)
 })

 <p>Prints out instructions in reverse order.  This is actually the same as
 @('(commands n t)') &mdash; or, @('(commands nil t)') if @('n') is not
 supplied.  As for @('commands') (see @(see acl2-pc::commands)), the final
 argument of @('t') causes suppression of instructions occurring between
 so-called ``matching bookends,'' which we now explain.</p>

 <p>A ``begin bookend'' is an instruction of the form</p>

 @({
  (COMMENT :BEGIN x . y).
 })

 <p>Similarly, an ``end bookend'' is an instruction of the form</p>

 @({
  (COMMENT :END x' . y').
 })

 <p>The ``name'' of the first bookend is @('x') and the ``name'' of the second
 bookend is @('x'').  When such a pair of instructions occurs in the current
 state-stack, we call them ``matching bookends'' provided that they have the
 same name (i.e. @('x') equals @('x'')) and if no other begin or end bookend
 with name @('x') occurs between them.  The idea now is that @('comm') hides
 matching bookends together with the instructions they enclose.  Here is a more
 precise explanation of this ``hiding''; probably there is no value in reading
 on!</p>

 <p>A @('comm') instruction hides bookends in the following manner.  (So does a
 @('comment') instruction when its second optional argument is supplied and
 non-@('nil').)  First, if the first argument @('n') is supplied and not
 @('nil'), then we consider only the last @('n') instructions from the
 state-stack; otherwise, we consider them all.  Now the resulting list of
 instructions is replaced by the result of applying the following process to
 each pair of matching bookends: the pair is removed, together with everything
 in between the begin and end bookend of the pair, and all this is replaced by
 the ``instruction''</p>

 @({
  (\"***HIDING***\" :COMMENT :BEGIN name ...)
 })

 <p>where @('(comment begin name ...)') is the begin bookend of the pair.
 Finally, after applying this process to each pair of matching bookends, each
 begin bookend of the form @('(comment begin name ...)')  that remains is
 replaced by</p>

 @({
  (\"***UNFINISHED***\" :COMMENT :BEGIN name ...) .
 })")

(defxdoc acl2-pc::commands
  :parents (proof-builder-commands)
  :short "(macro)
display instructions from the current interactive session"
  :long "@({
  Examples:
  commands
  (commands 10 t)

  General Forms:

  commands or (commands nil)
  Print out all the instructions (in the current state-stack) in
  reverse order, i.e. from the most recent instruction to the starting
  instruction.

  (commands n) [n a positive integer]
  Print out the most recent n instructions (in the current
  state-stack), in reverse order.

  (commands x abbreviate-flag)
  Same as above, but if abbreviate-flag is non-NIL, then do not
  display commands between ``matching bookends''.  See documentation
  for comm for an explanation of matching bookends.
 })

 <p><b>Remark</b>: If there are more than @('n') instructions in the
 state-stack, then @('(commands n)') is the same as @('commands') (and also,
 @('(commands n abb)') is the same as @('(commands nil abb)')).</p>")

(defxdoc acl2-pc::comment
  :parents (proof-builder-commands)
  :short "(primitive)
insert a comment"
  :long "@({
  Example:
  (comment now begin difficult final goal)

  General Form:
  (comment &rest x)
 })

 <p>This instruction makes no change in the state except to insert the
 @('comment') instruction.</p>

 <p>Some comments can be used to improve the display of commands; see @(see
 acl2-pc::comm).</p>")

(defxdoc acl2-pc::contradict
  :parents (proof-builder-commands)
  :short "(macro) same as @('contrapose')"
  :long "<p>See @(see acl2-pc::contrapose).</p>")

(defxdoc acl2-pc::contrapose
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(primitive)
switch a hypothesis with the conclusion, negating both"
  :long "@({
  Example:
  (contrapose 3)

  General Form:
  (contrapose &optional n)
 })

 <p>The (optional) argument @('n') should be a positive integer that does not
 exceed the number of hypotheses.  Negate the current conclusion and make it
 the @('n')th hypothesis, while negating the current @('n')th hypothesis and
 making it the current conclusion.  If no argument is supplied then the effect
 is the same as for @('(contrapose 1)').</p>

 <p><b>Remark:</b> By ``negate'' we mean an operation that replaces @('nil') by
 @('t'), @('x') by @('nil') for any other explicit value @('x'), @('(not x)')
 by @('x'), and any other @('x') by @('(not x)').</p>")

(defxdoc acl2-pc::demote
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(primitive)
move top-level hypotheses to the conclusion"
  :long "@({
  Examples:
  demote        -- demote all top-level hypotheses
  (demote 3 5)  -- demote hypotheses 3 and 5
 })

 <p>For example, if the top-level hypotheses are @('x') and @('y') and the
 conclusion is @('z'), then after execution of @('demote'), the conclusion will
 be @('(implies (and x y) z)') and there will be no (top-level) hypotheses.</p>

 @({
  General Form:
  (demote &rest hyps-indices)
 })

 <p>Eliminate the indicated (top-level) hypotheses, but replace the conclusion
 @('conc') with @('(implies hyps conc)') where @('hyps') is the conjunction of
 the hypotheses that were eliminated.  If no arguments are supplied, then all
 hypotheses are demoted, i.e. @('demote') is the same as @('(demote 1 2
 ... n)') where @('n') is the number of top-level hypotheses.</p>

 <p><b>Remark</b>: You must be at the top of the conclusion in order to use
 this command.  Otherwise, first invoke @('top').  Also, @('demote') fails if
 there are no top-level hypotheses or if indices are supplied that are out of
 range.</p>")

(defxdoc acl2-pc::dive
  :parents (proof-builder-commands)
  :short "(primitive)
move to the indicated subterm"
  :long "@({
  Examples:
  (DIVE 1)    -- assign the new current subterm to be the first
                 argument of the existing current subterm
  (DIVE 1 2)  -- assign the new current subterm to be the result of
                 first taking the 1st argument of the existing
                 current subterm, and then the 2nd argument of that
 })

 <p>For example, if the current subterm is</p>

 @({
  (* (+ a b) c),
 })

 <p>then after @('(dive 1)') it is</p>

 @({
  (+ a b).
 })

 <p>If after that, then @('(dive 2)') is invoked, the new current subterm will
 be</p>

 @({
  b.
 })

 <p>Instead of @('(dive 1)') followed by @('(dive 2)'), the same current
 subterm could be obtained by instead submitting the single instruction
 @('(dive 1 2)').</p>

 @({
  General Form:
  (dive &rest naturals-list)
 })

 <p>If @('naturals-list') is a non-empty list @('(n_1 ... n_k)') of natural
 numbers, let the new current subterm be the result of selecting the
 @('n_1')-st argument of the current subterm, and then the @('n_2')-th subterm
 of that, ..., finally the @('n_k')-th subterm.</p>

 <p><b>Remark:</b> @('Dive') is related to the command @('pp'), in that the
 diving is done according to raw (translated, internal form) syntax.  Use the
 command @('dv') if you want to dive according to the syntax displayed by the
 command @('p').  Note that @('(dv n)') can be abbreviated by simply
 @('n').</p>

 <p><b>Remark:</b> Emacs users who load (into Emacs) the file
 @('emacs/acl2-doc.el') will have defined a command, @('Control-t Control-d'),
 that avoids the need to type @('dive') commands.  After you print the current
 term using the @('pp') command, you may position the cursor on a subterm and
 type @('Control-t Control-d').  Emacs will respond by pasting the appropriate
 @('dive') command immediately after the interactive proof-builder's prompt.
 You can then simply type @('<RETURN>') in order to dive to the desired
 subterm.</p>")

(defxdoc acl2-pc::do-all
  :parents (proof-builder-commands)
  :short "(macro)
run the given instructions"
  :long "@({
  Example:
  (do-all induct p prove)

  General Form:
  (do-all &rest instruction-list)
 })

 <p>Run the indicated instructions until there is a hard ``failure''.  The
 instruction ``succeeds'' if and only if each instruction in
 @('instruction-list') does.  (See @(see acl2-pc::sequence) for an explanation
 of ``success'' and ``failure.'')  As each instruction is executed, the system
 will print the usual prompt followed by that instruction, unless the global
 state variable @('pc-print-prompt-and-instr-flg') is @('nil').</p>

 <p><b>Remark:</b> If @('do-all') ``fails'', then the failure is hard if and
 only if the last instruction it runs has a hard ``failure''.</p>

 <p>Obscure point: For the record, @('(do-all ins_1 ins_2 ... ins_k)') is the
 same as @('(sequence (ins_1 ins_2 ... ins_k))').</p>")

(defxdoc acl2-pc::do-all-no-prompt
  :parents (proof-builder-commands)
  :short "(macro)
run the given instructions, halting once there is a ``failure''"
  :long "@({
  Example:
  (do-all-no-prompt induct p prove)

  General Form:
  (do-all-no-prompt &rest instruction-list)
 })

 <p>@('Do-all-no-prompt') is the same as @('do-all'), except that the prompt
 and instruction are not printed each time, regardless of the value of
 @('pc-print-prompt-and-instr-flg').  Also, restoring is disabled.  See @(see
 acl2-pc::do-all).</p>")

(defxdoc acl2-pc::do-strict
  :parents (proof-builder-commands)
  :short "(macro)
run the given instructions, halting once there is a ``failure''"
  :long "@({
  Example:
  (do-strict induct p prove)

  General Form:
  (do-strict &rest instruction-list)
 })

 <p>Run the indicated instructions until there is a (hard or soft) ``failure''.
 In fact @('do-strict') is identical in effect to @('do-all'), except that
 @('do-all') only halts once there is a hard ``failure''.  See @(see
 acl2-pc::do-all).</p>")

(defxdoc acl2-pc::doc
  :parents (proof-builder-commands)
  :short "(macro) access documentation inside the interactive proof-builder"
  :long "@({
  Examples:

  (doc rewrite)          -- documentation on rewriting in ACL2
  (doc acl2-pc::rewrite) -- documentation on the proof-builder rewrite command
  (doc)                  -- same as (help doc) or (doc acl2-pc::doc)
  doc                    -- same as above

  General Forms:
  (doc) ; or, just: help
  (doc topic-name)
 })

 <p>For any @(see documentation) topic, @('A'), @('(doc A)') prints
 documentation on @('A') to the terminal.  You can read that documentation
 online or in the Emacs @(see ACL2-Doc) browser; see @(see documentation).
 This @(see proof-builder) command provides a direct interface to the ACL2
 @(':')@(tsee doc) command at the terminal.</p>

 <p>Also see @(see acl2-pc::help), which provides help for proof-builder
 commands.  For example, submitting @('(help rewrite)') to the proof-builder is
 equivalent to submitting @('(doc acl2-pc::rewrite)') to the proof-builder,
 which corresponds to submitting @(':doc acl2-pc::rewrite') directly to the
 ACL2 loop.</p>")

(defxdoc acl2-pc::drop
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(primitive)
drop top-level hypotheses"
  :long "@({
  Examples:
  (drop 2 3) -- drop the second and third hypotheses
  drop       -- drop all top-level hypotheses

  General Forms:
  (drop n1 n2 ...) -- Drop the hypotheses with the indicated indices.

  drop             -- Drop all the top-level hypotheses.
 })

 <p><b>Remark:</b> If there are no top-level hypotheses, then the instruction
 @('drop') will fail.  If any of the indices is out of range, i.e. is not an
 integer between one and the number of top-level hypotheses @('(inclusive)'),
 then @('(drop n1 n2 ...)') will fail.</p>")

(defxdoc acl2-pc::dv
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
move to the indicated subterm"
  :long "@({
  Examples:
  (dv 1)    -- assign the new current subterm to be the first argument
               of the existing current subterm
  (dv 1 2)  -- assign the new current subterm to be the result of
               first taking the 1st argument of the existing
               current subterm, and then the 2nd argument of that
 })

 <p>For example, if the current subterm is</p>

 @({
  (* (+ a b) c),
 })

 <p>then after @('(dv 1)') it is</p>

 @({
  (+ a b).
 })

 <p>If after that, then @('(dv 2)') is invoked, the new current subterm will
 be</p>

 @({
  b.
 })

 <p>Instead of @('(dv 1)') followed by @('(dv 2)'), the same current subterm
 could be obtained by instead submitting the single instruction @('(dv 1
 2)').</p>

 @({
  General Form:
  (dv &rest naturals-list)
 })

 <p>If @('naturals-list') is a non-empty list @('(n_1 ... n_k)') of natural
 numbers, let the new current subterm be the result of selecting the
 @('n_1')-st argument of the current subterm, and then the @('n_2')-th subterm
 of that, ..., finally the @('n_k')-th subterm.</p>

 <p><b>Remark:</b> @('(dv n)') may be abbreviated by simply @('n'), so we could
 have typed @('1') instead of @('(dv 1)') in the first example above.</p>

 <p><b>Remark:</b> Emacs users who load (into Emacs) the file
 @('emacs/acl2-doc.el') will have defined a command, @('Control-t d'), that
 avoids the need to type @('dv') commands.  After you print the current term
 using the @('p') or @('th') command, you may position the cursor on a subterm
 and type @('Control-t d').  Emacs will respond by pasting the appropriate
 @('dv') command immediately after the interactive proof-builder's prompt.  You
 can then simply type @('<RETURN>') in order to dive to the desired
 subterm.</p>

 <p><b>Remark:</b> A similar command is @('dive'), which is related to the
 command @('pp'), in that the diving is done according to raw (translated,
 internal form) syntax.  (See @(see acl2-pc::dive).)  Use the command @('dv')
 if you want to dive according to the syntax displayed by the command @('p').
 Thus, the command ``@('up')'' is the inverse of @('dive'), not of @('dv').
 The following example illustrates this point.</p>

 @({
  ACL2 !>(verify (equal (* a b c) x))
  ->: p ; print user-level term
  (EQUAL (* A B C) X)
  ->: pp ; print internal-form (translated) term
  (EQUAL (BINARY-* A (BINARY-* B C)) X)
  ->: exit
  Exiting....
   NIL
  ACL2 !>(verify (equal (* a b c) x))
  ->: p
  (EQUAL (* A B C) X)
  ->: 1 ; same as (dv 1)
  ->: p ; print user-level term
  (* A B C)
  ->: pp ; print internal-form (translated) term
  (BINARY-* A (BINARY-* B C))
  ->: 3 ; dive to third argument of (* A B C)
  ->: p
  C
  ->: up ; go up one level in (BINARY-* A (BINARY-* B C))
  ->: p
  (* B C)
  ->: pp
  (BINARY-* B C)
  ->:
 })")

(defxdoc acl2-pc::elim
  :parents (proof-builder-commands)
  :short "(atomic macro)
call the ACL2 theorem prover's elimination process"
  :long "@({
  Example and General Form:
  elim
 })

 <p>Upon running the @('elim') command, the system will create a subgoal will
 be created for each goal that would have been pushed for proof by induction in
 an ordinary proof, where <b>only</b> elimination is used; not even
 simplification is used!</p>")

(defxdoc acl2-pc::equiv
  :parents (proof-builder-commands)
  :short "(primitive)
attempt an equality (or congruence-based) substitution"
  :long "@({
  Examples:
  (equiv (* x y) 3) -- replace (* x y) by 3 everywhere inside the
                       current subterm, if their equality is among the
                       top-level hypotheses or the governors
  (equiv x t iff)   -- replace x by t everywhere inside the current
                       subterm, where only propositional equivalence
                       needs to be maintained at each occurrence of x

  General form:
  (equiv old new &optional relation)
 })

 <p>Substitute new for old everywhere inside the current subterm, provided that
 either (relation old new) or (relation new old) is among the top-level
 hypotheses or the governors (possibly by way of backchaining and/or
 refinement; see below).  If relation is @('nil') or is not supplied, then it
 defaults to @('equal').  Also see @('acl2-pc::=') for a much more flexible
 command.  Note that the @('equiv') command fails if no substitution is actually
 made.</p>

 <p><b>Remark:</b> No substitution takes place inside explicit values.  So for
 example, the instruction @('(equiv 3 x)') will cause @('3') to be replaced by
 @('x') if the current subterm is, say, @('(* 3 y)'), but not if the current
 subterm is @('(* 4 y)') even though @('4 = (1+ 3)').</p>

 <p>The following remarks are quite technical and mostly describe a certain
 weak form of ``backchaining'' that has been implemented for @('equiv') in
 order to support the @('=') command.  In fact neither the term @('(relation
 old new)') nor the term @('(relation new old)') needs to be <b>explicitly</b>
 among the current ``assumptions'', i.e., the top-level hypothesis or the
 governors.  Rather, there need only be such an assumption that ``tells us''
 @('(r old new)') or @('(r new old)'), for <b>some</b> equivalence relation
 @('r') that <b>refines</b> @('relation').  Here, ``tells us'' means that
 either one of the indicated terms is among those assumptions, or else there is
 an assumption that is an implication whose conclusion is one of the indicated
 terms and whose hypotheses (gathered up by appropriately flattening the first
 argument of the @('implies') term) are all among the current
 assumptions.</p>")

(defxdoc acl2-pc::ex
  :parents (proof-builder-commands)
  :short "(macro)
exit after possibly saving the state"
  :long "@({
  Example and General Form:
  ex
 })

 <p>Same as @('exit'), except that first the instruction @('save') is
 executed.</p>

 <p>If @('save') queries the user and is answered negatively, then the exit is
 aborted.</p>")

(defxdoc acl2-pc::exit
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(meta) exit the interactive proof-builder"
  :long "@({
  Examples:
  exit                        -- exit the interactive proof-builder
  (exit t)                    -- exit after printing a bogus defthm event
  (exit append-associativity) -- exit and create a defthm
                                 event named append-associativity

  General Forms:

  exit --  Exit without storing an event.

  (exit t) -- Exit after printing a bogus defthm event, showing :INSTRUCTIONS.

  (exit event-name &optional rule-classes do-it-flg) --
  Exit, and perhaps store an event
 })

 <p>The command @('exit') returns you to the ACL2 loop.  At a later time,
 @('(acl2::verify)') may be executed to get back into the same interactive
 proof-builder state, as long as there hasn't been an intervening use of the
 proof-builder (otherwise see @(see acl2-pc::save)).</p>

 <p>When given one or more arguments as shown above, @('exit') still returns
 you to the ACL2 loop, but first, if the interactive proof is complete, then it
 attempts create a @('defthm') event with the specified @('event-name') and
 @('rule-classes') (which defaults to @('(:rewrite)') if not supplied).  The
 event will be printed to the terminal, and then normally the user will be
 queried whether an event should really be created.  However, if the final
 optional argument @('do-it-flg') is supplied and not @('nil'), then an event
 will be made without a query.</p>

 <p>For example, the form</p>

 @({
  (exit top-pop-elim (:elim :rewrite) t)
 })

 <p>causes a @('defthm') event named @('top-pop-elim') to be created with
 rule-classes @('(:elim :rewrite)'), without a query to the user (because of
 the argument @('t')).</p>

 <p><b>Remark:</b> it is permitted for @('event-name') to be @('nil').  In that
 case, the name of the event will be the name supplied during the original call
 of @('verify').  (See @(see acl2::verify) and @(see acl2-pc::commands).)
 Also in that case, if @('rule-classes') is not supplied then it defaults to
 the rule-classes supplied in the original call of @('verify').</p>

 <p>@('Comments') on ``success'' and ``failure''.  An @('exit') instruction
 will always ``fail'', so for example, if it appears as an argument of a
 @('do-strict') instruction then none of the later (instruction) arguments will
 be executed.  Moreover, the ``failure'' will be ``hard'' if an event is
 successfully created or if the instruction is simply @('exit'); otherwise it
 will be ``soft''.  See @(see acl2-pc::sequence) for an explanation of hard and
 soft ``failures''.  An obscure but potentially important fact is that if the
 ``failure'' is hard, then the error signal is a special signal that the
 top-level interactive loop can interpret as a request to exit.  Thus for
 example, a sequencing command that turns an error triple @('(mv erp val
 state)') into @('(mv t val state)') would never cause an exit from the
 interactive loop.</p>

 <p>If the proof is not complete, then @('(exit event-name ...)') will not
 cause an exit from the interactive loop.  However, in that case it will print
 out the original user-supplied goal (the one that was supplied with the call
 to @('verify')) and the current list of instructions.</p>")

(defxdoc acl2-pc::expand
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(primitive)
expand the current function call without simplification"
  :long "@({
  Examples:
  expand -- expand and do not simplify.
 })

 <p>Also see @(see acl2-pc::x), which performs simplification, and see @(see
 acl2-pc::x-dumb), which provides a simple interface to
 @('acl2-pc::expand').</p>

 <p>For example, if the current subterm is @('(append a b)'), then after
 @('expand') the current subterm will be the term:</p>

 @({
 (if (consp a)
     (cons (car a) (append (cdr a) b))
   b)
 })

 <p>regardless of the top-level hypotheses and the governors.</p>

 @({
  General Form:
  (expand &optional do-not-expand-lambda-flg)
 })

 <p>Expand the function call at the current subterm, and do not simplify.  The
 options have the following meanings:</p>

 @({
  do-not-expand-lambda-flg:   default is nil; otherwise, the result
                              should be a lambda expression
 })")

(defxdoc acl2-pc::fail
  :parents (proof-builder-commands)
  :short "(macro)
cause a failure"
  :long "@({
  Examples:
  fail
  (fail t)

  General Form:
  (fail &optional hard)
 })

 <p>This is probably only of interest to writers of macro commands.  The only
 function of @('fail') is to fail to ``succeed''.</p>

 <p>The full story is that @('fail') and @('(fail nil)') simply return @('(mv
 nil nil state)'), while @('(fail hard)') returns @('(mv hard nil state)') if
 @('hard') is not @('nil').  Also see @(see acl2-pc::do-strict), @(see
 acl2-pc::do-all), and @(see acl2-pc::sequence).</p>")

(defxdoc acl2-pc::finish
  :parents (proof-builder-commands)
  :short "(macro) require completion of instructions; save error if inside
@(':')@(tsee hints)"
  :long "@({
  Example:
  (finish induct prove bash)

  General Form:
  (finish &rest instructions)
 })

 <p>Run the indicated instructions, stopping at the first failure.  If there is
 any failure, or if any new goals are created and remain at the end of the
 indicated instructions, then consider the call of @('finish') to be a failure.
 See @(see proof-builder-commands) and see @(see acl2-pc::sequence) for a
 discussion of the notion of ``failure'' for interactive @(see proof-builder)
 commands.</p>")

(defxdoc acl2-pc::forwardchain
  :parents (proof-builder-commands)
  :short "(atomic macro)
forward chain from an implication in the hyps"
  :long "@({
  Example:
  (forwardchain 2) ; Second hypothesis should be of the form
                   ; (IMPLIES hyp concl), and the result is to replace
                   ; that hypothesis with concl.

  General Forms:
  (forwardchain hypothesis-number)
  (forwardchain hypothesis-number hints)
  (forwardchain hypothesis-number hints quiet-flg)
 })

 <p>This command replaces the hypothesis corresponding to given index, which
 should be of the form @('(IMPLIES hyp concl)'), with its consequent
 @('concl').  In fact, the given hypothesis is dropped, and the replacement
 hypothesis will appear as the final hypothesis after this command is
 executed.</p>

 <p>The prover must be able to prove the indicated hypothesis from the other
 hypotheses, or else the command will fail.  The @(':hints') argument is used
 in this prover call, and should have the usual syntax of hints to the
 prover.</p>

 <p>Output is suppressed if @('quiet-flg') is supplied and not @('nil').</p>")

(defxdoc acl2-pc::free
  :parents (proof-builder-commands)
  :short "(atomic macro)
create a ``free variable''"
  :long "@({
  Example:
  (free x)

  General Form:
  (free var)
 })

 <p>Mark @('var') as a ``free variable''.  Free variables are only of interest
 for the @('put') command; see @(see acl2-pc::put).</p>")

(defxdoc acl2-pc::geneqv
  :parents (proof-builder-commands)
  :short "(macro)
show the generated equivalence relation maintained at the current subterm"
  :long "@({
  General Forms:
  geneqv     ; show list of equivalence relations being maintained
  (geneqv t) ; as above, but pair each relation with a justifying rune
 })

 <p>This is an advanced command, whose effect is to print the so-called
 ``generated equivalence relation'' (or ``geneqv'') that is maintained at the
 current subterm of the conclusion.  That structure is a list of equivalence
 relations, representing the transitive closure @('E') of the union of those
 relations, such that it suffices to maintain @('E') at the current subterm: if
 that subterm, @('u'), is replaced in the goal's conclusion, @('G'), by another
 term equivalent to @('u') with respect to @('E'), then the resulting
 conclusion is Boolean equivalent to @('G').  Also see @(see defcong).</p>

 <p>The command `@('geneqv')' prints the above list of equivalence relations,
 or more precisely, the list of function symbols for those relations.  If
 however @('geneqv') is given a non-@('nil') argument, then a list is printed
 whose elements are each of the form @('(s r)'), where @('s') is the symbol for
 an equivalence relation and @('r') is a @(':')@(tsee congruence) @(see rune)
 justifying the inclusion of @('s') in the list of equivalence relations being
 maintained at the current subterm.</p>")

(defxdoc acl2-pc::generalize
  :parents (proof-builder-commands)
  :short "(primitive)
perform a generalization"
  :long "@({
  Example:
  (generalize
   ((and (true-listp x) (true-listp y)) 0)
   ((append x y) w))

  General Form:
  (generalize &rest substitution)
 })

 <p>Generalize using the indicated substitution, which should be a non-empty
 list.  Each element of that list should be a two-element list of the form
 @('(term variable)'), where @('term') may use abbreviations.  The effect of
 the instruction is to replace each such term in the current goal by the
 corresponding variable.  This replacement is carried out by a parallel
 substitution, outside-in in each hypothesis and in the conclusion.  More
 generally, actually, the ``variable'' (second) component of each pair may be
 @('nil') or a number, which causes the system to generate a new name of the
 form @('_') or @('_n'), with @('n') a natural number; more on this below.
 However, when a variable is supplied, it must not occur in any goal of the
 current state of the interactive proof-builder.</p>

 <p>When the ``variable'' above is @('nil'), the system will treat it as the
 variable @('|_|') if that variable does not occur in any goal of the current
 proof-builder state.  Otherwise it treats it as @('|_0|'), or @('|_1|'), or
 @('|_2|'), and so on, until one of these is not among the variables of the
 current proof-builder state.  If the ``variable'' is a non-negative integer
 @('n'), then the system treats it as @('|_n|') unless that variable already
 occurs among the current goals, in which case it increments n just as above
 until it obtains a new variable.</p>

 <p><b>Remark:</b> The same variable may not occur as the variable component of
 two different arguments (though @('nil') may occur arbitrarily many times, as
 may a positive integer).</p>")

(defxdoc acl2-pc::goals
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
list the names of goals on the stack"
  :long "@({
  Example and General Form:
  goals
 })

 <p>@('Goals') lists the names of all goals that remain to be proved.  They are
 listed in the order in which they appear on the stack of remaining goals,
 which is relevant for example to the effect of a @('change-goal')
 instruction.</p>")

(defxdoc acl2-pc::help
  :parents (proof-builder-commands)
  :short "(macro)
proof-builder help facility"
  :long "@({
  Examples:

  (help rewrite)   -- documentation on the proof-builder rewrite command
  (help)           -- this help
  (help help)      -- same as (help) or simply, help
  (help all)       -- same as (doc proof-builder-commands)

  General Forms:
  (help) ; or, just: help
  (help command)
  (help all)
 })

 <p>For any interactive proof-builder command, @('C'), @('(help C)') prints
 documentation on @('C') to the terminal.  You can read that documentation
 online or in the Emacs @(see ACL2-Doc) browser by viewing topic
 @('acl2-pc::C'); see @(see documentation).</p>

 <p>To see a list of all interactive proof-builder commands, you can submit
 @('(help all)').  This is actually equivalent to @('(doc
 proof-builder-commands)'), which prints the documentation for topic @(see
 proof-builder-commands) (which, as discussed above, you can view online or
 with @(see ACL2-Doc)).</p>

 <p>Also see @(see acl2-pc::doc), which provides a direct interface to the ACL2
 @(':')@(tsee doc) command.  For example, submitting @('(help rewrite)') to the
 interactive proof-builder is equivalent to submitting @('(doc
 acl2-pc::rewrite)') to the proof-builder or submitting @(':doc
 acl2-pc::rewrite') directly to the ACL2 loop.</p>")

(defxdoc acl2-pc::hyps
  :parents (proof-builder-commands)
  :short "(macro)
print the hypotheses"
  :long "@({
  Examples:
  hyps               -- print all (top-level) hypotheses
  (hyps (1 3) (2 4)) -- print hypotheses 1 and 3 and governors 2 and 4
  (hyps (1 3) t)     -- print hypotheses 1 and 3 and all governors

  General Form:
  (hyps &optional hyps-indices govs-indices)
 })

 <p>Print the indicated top-level hypotheses and governors.  (The notion of
 ``governors'' is defined below.)  Here, @('hyps-indices') and
 @('govs-indices') should be lists of indices of hypotheses and governors
 (respectively), except that the atom @('t') may be used to indicate that one
 wants all hypotheses or governors (respectively).</p>

 <p>The list of ``governors'' is defined as follows.  Actually, we define here
 the notion of the governors for a pair of the form @('<term'), address&gt;];
 we're interested in the special case where the term is the conclusion and the
 address is the current address.  If the address is @('nil'), then there are no
 governors, i.e., the list of governors is @('nil').  If the term is of the
 form @('(if x y z)') and the address is of the form @('(2 . rest)') or @('(3
 . rest)'), then the list of governors is the result of @('cons')ing @('x') or
 its negation (respectively) onto the list of governors for the pair @('<y,
 rest>') or the pair @('<z, rest>') (respectively).  If the term is of the form
 @('(implies x y)') and the address is of the form @('(2 . rest)'), then the
 list of governors is the result of @('cons')ing @('x') onto the list of
 governors for the pair @('<y, rest>').  Otherwise, the list of governors for
 the pair @('<term, (n .  rest)>') is exactly the list of governors for the
 pair @('<argn, rest>') where @('argn') is the @('n')th argument of
 @('term').</p>

 <p>If all goals have been proved, a message saying so will be printed.  (as
 there will be no current hypotheses or governors!).</p>

 <p>The @('hyps') command never causes an error.  It ``succeeds'' (in fact its
 value is @('t')) if the arguments (when supplied) are appropriate, i.e.
 either @('t') or lists of indices of hypotheses or governors, respectively.
 Otherwise it ``fails'' (its value is @('nil')).</p>")

(defxdoc acl2-pc::illegal
  :parents (proof-builder-commands)
  :short "(macro)
illegal instruction"
  :long "@({
  Example:
  (illegal -3)

  General Form:
  (illegal instruction)
 })

 <p>Probably not of interest to most users; always ``fails'' since it expands
 to the @('fail') command.</p>

 <p>The @('illegal') command is used mainly in the implementation.  For
 example, the instruction @('0') is ``read'' as @('(illegal 0)'), since
 @('dive') expects positive integers.</p>")

(defxdoc acl2-pc::in-theory
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(primitive)
set the current proof-builder theory"
  :long "@({
  Example:
  (in-theory
     (union-theories (theory 'minimal-theory) '(true-listp binary-append)))

  General Form:
  (in-theory &optional atom-or-theory-expression)
 })

 <p>If the argument is not supplied, then this command sets the current
 interactive proof-builder theory (see below for explanation) to agree with the
 current ACL2 theory.  Otherwise, the argument should be a theory expression,
 and in that case the proof-builder theory is set to the value of that theory
 expression.</p>

 <p>The current interactive proof-builder theory is used in all calls to the
 ACL2 theorem prover and rewriter from inside the proof-builder.  Thus, the
 most recent @('in-theory') instruction in the current @('state-stack') has an
 effect in the proof-builder totally analogous to the effect caused by an
 @('in-theory') hint or event in ACL2.  All @('in-theory') instructions before
 the last are ignored, because they refer to the current theory in the ACL2
 @(tsee state), not to the existing proof-builder theory.  For example:</p>

 @({
     ACL2 !>:trans1 (enable bar)
      (UNION-THEORIES (CURRENT-THEORY :HERE)
                      '(BAR))
     ACL2 !>:trans1 (CURRENT-THEORY :HERE)
      (CURRENT-THEORY-FN :HERE WORLD)
     ACL2 !>
 })

 <p>Thus @('(in-theory (enable bar))') modifies the current theory of the
 current ACL2 world.  So for example, suppose that @('foo') is disabled outside
 the proof-builder and you execute the following instructions, in this
 order.</p>

 @({
     (in-theory (enable foo))
     (in-theory (enable bar))
 })

 <p>Then after the second of these, @('bar') will be enabled in the
 proof-builder, but @('foo') will be disabled.  The reason is that
 @('(in-theory (enable bar))') instructs the proof-builder to modify the
 current theory (from outside the proof-builder, not from inside the
 proof-builder) by enabling @('bar').</p>

 <p>Note that @('in-theory') instructions in the proof-builder have no effect
 outside the proof-builder's interactive loop.</p>

 <p>If the most recent @('in-theory') instruction in the current state of the
 proof-builder has no arguments, or if there is no @('in-theory') instruction
 in the current state of the proof-builder, then the proof-builder will use the
 current ACL2 theory.  This is true even if the user has interrupted the
 interactive loop by exiting and changing the global ACL2 theory.  However, if
 the most recent @('in-theory') instruction in the current state of the
 proof-builder had an argument, then global changes to the current theory will
 have no effect on the proof-builder state.</p>")

(defxdoc acl2-pc::induct
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
generate subgoals using induction"
  :long "@({
  Examples:
  induct, (induct t)
     -- induct according to a heuristically-chosen scheme, creating
        a new subgoal for each base and induction step
  (induct (append (reverse x) y))
     -- as above, but choose an induction scheme based on the term
        (append (reverse x) y) rather than on the current goal

  General Form:
  (induct &optional term)
 })

 <p>Induct as in the corresponding @(':induct') hint given to the theorem
 prover, creating new subgoals for the base and induction steps.  If term is
 @('t') or is not supplied, then use the current goal to determine the
 induction scheme; otherwise, use that term.</p>

 <p><b>Remark:</b> As usual, abbreviations are allowed in the term.</p>

 <p><b>Remark:</b> @('Induct') actually calls the @('prove') command with all
 processes turned off.  Thus, you must be at top of the goal for an @('induct')
 instruction.</p>")

(defxdoc acl2-pc::lemmas-used
  :parents (proof-builder-commands)
  :short "(macro)
print the runes (definitions, lemmas, ...) used"
  :long "<p>This is just an alias for @('runes').</p>

 ")

(defxdoc acl2-pc::lisp
  :parents (proof-builder-commands)
  :short "(meta)
evaluate the given form in Lisp"
  :long "@({
  Example:
  (lisp (assign xxx 3))

  General Form:
  (lisp form)
 })

 <p>Evaluate @('form').  The @('lisp') command is mainly of interest for side
 effects.  Also see @(see acl2-pc::print), @(see acl2-pc::skip), and @(see
 acl2-pc::fail).</p>

 <p>The rest of the documentation for @('lisp') is of interest only to those
 who use it in macro commands.  If the Lisp evaluation (by @('trans-eval')) of
 form returns an @(see error-triple) of the form @('(mv erp
 ((NIL NIL STATE) . (erp-1 val-1 &)) state)'), then the @('lisp') command
 returns the appropriate error triple</p>

 @({
  (mv (or erp erp-1)
      val-1
      state) .
 })

 <p>Otherwise, the @('trans-eval') of form must return an error triple of the
 form @('(mv erp (cons stobjs-out val) &)'), and the @('lisp') command returns
 the appropriate error triple</p>

 @({
  (mv erp
      val
      state).
 })

 <p>Note that the output signature of the form has been lost.  The user must
 know the signature in order to use the output of the @('lisp') command.
 Trans-eval, which is undocumented except by comments in the ACL2 source code,
 has replaced, in @('val'), any occurrence of the current state or the current
 values of stobjs by simple symbols such as @('REPLACED-STATE').  The actual
 values of these objects may be recovered, in principle, from the @('state')
 returned and the @('user-stobj-alist') within that state.  However, in
 practice, the stobjs cannot be recovered because the user is denied access to
 @('user-stobj-alist').  The moral is: do not try to write macro commands that
 manipulate stobjs.  Should the returned @('val') contain @('REPLACED-STATE')
 the value may simply be ignored and @('state') used, since that is what
 @('REPLACED-STATE') denotes.</p>")

(defxdoc acl2-pc::negate
  :parents (proof-builder-commands)
  :short "(macro)
run the given instructions, and ``succeed'' if and only if they ``fail''"
  :long "<p>Example:
 (negate prove)</p>

 @({
  General form:
  (negate &rest instruction-list)
 })

 <p>Run the indicated instructions exactly in the sense of @('do-all'), and
 ``succeed'' if and only if they ``fail''.</p>

 <p><b>Remark:</b> @('Negate') instructions will never produce hard
 ``failures''.</p>")

(defxdoc acl2-pc::nil
  :parents (proof-builder-commands)
  :short "(macro) used for interpreting @('control-d')"
  :long "@({
  Example and General form:
  nil
 })

 <p>(or, @('control-d')).</p>

 <p>The whole point of this command is that in some Lisps (including akcl), if
 you type @('control-d') then it seems, on occasion, to get interpreted as
 @('nil').  Without this command, one seems to get into an infinite loop.</p>")

(defxdoc acl2-pc::noise
  :parents (proof-builder-commands)
  :short "(meta)
run instructions with prover output"
  :long "@({
  Example:
  (noise induct prove)

  General Form:
  (noise &rest instruction-list)
 })

 <p>Run the @('instruction-list') through the top-level loop with prover
 output.</p>

 <p>In fact, having prover output is the default.  @('Noise') is useful inside
 a surrounding call of @('quiet'), when one temporarily wants output.  For
 example, if one wants to see output for a @('prove') command immediately
 following an @('induct') command but before an @('s') command, one may want to
 submit an instruction like @('(quiet induct (noise prove) s)').  Also see
 @(see acl2-pc::quiet) and @(see acl2-pc::noise!).</p>")

(defxdoc acl2-pc::noise!
  :parents (proof-builder-commands)
  :short "(meta)
run instructions with prover and proof-tree output"
  :long "@({
  Example:
  (noise! induct prove)

  General Form:
  (noise! &rest instruction-list)
 })

 <p>Run the @('instruction-list') through the top-level loop with prover output
 and @(see proof-tree) output.  See @(see acl2-pc::noise); the @('noise!')
 command is the same, except for adding proof-tree output.</p>")

(defxdoc acl2-pc::nx
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
move forward one argument in the enclosing term"
  :long "@({
  Example and General Form:
  nx
 })

 <p>For example, if the conclusion is @('(= x (* (- y) z))') and the current
 subterm is @('x'), then after executing @('nx'), the current subterm will be
 @('(* (- y) z)').</p>

 <p>This is the same as @('up') followed by @('(dive n+1)'), where @('n') is
 the position of the current subterm in its parent term in the conclusion.
 Thus in particular, the @('nx') command fails if one is already at the top of
 the conclusion.</p>

 <p>Also see @(see acl2-pc::up), @(see acl2-pc::dive), @(see acl2-pc::top), and
 @(see acl2-pc::bk).</p>")

(defxdoc acl2-pc::orelse
  :parents (proof-builder-commands)
  :short "(macro)
run the first instruction; if (and only if) it ``fails'', run the
second"
  :long "@({
  Example:
  (orelse top (print \"Couldn't move to the top\"))

  General form:
  (orelse instr1 instr2)
 })

 <p>Run the first instruction.  Then if it ``fails'', run the second
 instruction also; otherwise, stop after the first.</p>

 <p>This instruction ``succeeds'' if and only if either @('instr1')
 ``succeeds'', or else @('instr2') ``succeeds''.  If it ``fails'', then the
 failure is soft.</p>")

(defxdoc acl2-pc::p
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
prettyprint the current term"
  :long "@({
  Example and General Form:
  p
 })

 <p>Prettyprint the current term.  The usual user syntax is used, so that for
 example one would see @('(and x y)') rather than @('(if x y 'nil)').  (See
 also @('pp').)  Also, abbreviations are inserted where appropriate; see
 @(see acl2-pc::add-abbreviation).</p>

 <p>The ``current term'' is the entire conclusion unless @('dive') commands
 have been given, in which case it may be a subterm of the conclusion.</p>

 <p>If all goals have been proved, a message saying so will be printed (as
 there will be no current @('term')!).</p>")

(defxdoc acl2-pc::p-top
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
prettyprint the conclusion, highlighting the current term"
  :long "@({
  Example and General Form:
  p-top
 })

 <p>For example, if the conclusion is @('(equal (and x (p y)) (foo z))') and
 the current subterm is @('(p y)'), then @('p-top') will print @('(equal (and x
 (*** (p y) ***)) (foo z))').</p>

 <p>Prettyprint the the conclusion, highlighting the current term.  The usual
 user syntax is used, as with the command @('p') (as opposed to @('pp')).  This
 is illustrated in the example above, where one would <it>*not*</it> see
 @('(equal (if x (*** (p y) ***) 'nil) (foo z))').</p>

 <p><b>Remark</b> (obscure): In some situations, a term of the form @('(if x t
 y)') occurring inside the current subterm will not print as @('(or x y)'),
 when @('x') isn't a call of a boolean primitive.  There's nothing incorrect
 about this, however.</p>")

(defxdoc acl2-pc::pl
  :parents (proof-builder-commands)
  :short "(macro)
print the rules for a given name"
  :long "@({
  Examples:
  pl
  (pl foo)

  General Form:
  (pl &optional x)
 })

 <p>This command simply invokes the corresponding command of the top-level ACL2
 loop; see @(see pl).  If no argument is given, or if the argument is @('nil'),
 then the current subterm should be a call of a function symbol, and the
 argument is taken to be that symbol.</p>

 <p>If you want information about applying rewrite rules to the current
 subterm, consider the @('show-rewrites') (or equivalently, @('sr'))
 command.</p>")

(defxdoc acl2-pc::pp
  :parents (proof-builder-commands)
  :short "(macro)
prettyprint the current term"
  :long "@({
  Example and General Form:
  pp
 })

 <p>This is the same as @('p') (see its documentation), except that raw syntax
 (internal form) is used.  So for example, one would see @('(if x y 'nil)')
 rather than @('(and x y)').  Abbreviations are however still inserted, as with
 @('p').</p>")

(defxdoc acl2-pc::pr
  :parents (proof-builder-commands)
  :short "(macro)
print the rules for a given name"
  :long "@({
  Examples:
  pr
  (pr foo)

  General Form:
  (pr &optional x)
 })

 <p>This command simply invokes the corresponding command of the top-level ACL2
 loop; see @(see pr).  If no argument is given, or if the argument is @('nil'),
 then the current subterm should be a call of a function symbol, and the
 argument is taken to be that symbol.</p>

 <p>If you want information about applying rewrite rules to the current
 subterm, consider the @('show-rewrites') (or equivalently, @('sr'))
 command.</p>")

(defxdoc acl2-pc::print
  :parents (proof-builder-commands)
  :short "(macro)
print the result of evaluating the given form"
  :long "@({
  Example:
  (print (append '(a b) '(c d)))
  Print the list (a b c d) to the terminal

  General Forms:
  (print form)
  (print form t)
 })

 <p>Prettyprints the result of evaluating form.  The evaluation of @('form')
 should return a single value that is not @(tsee state) or a single-threaded
 object (see @(see stobj)).  The optional second argument causes printing to be
 done without elision (so-called ``evisceration''; see @(see evisc-tuple)).</p>

 <p>If the form you want to evaluate does not satisfy the criterion above, you
 should create an appropriate call of the @('lisp') command instead.  Notice
 that this command always returns @('(mv nil nil state)') where the second
 result will always be @('REPLACED-STATE').</p>")

(defxdoc acl2-pc::print-all-concs
  :parents (proof-builder-commands)
  :short "(macro)
print all the conclusions of (as yet unproved) goals"
  :long "<p>Example and General Form: print-all-concs</p>

 <p>Prints all the conclusions of goals that remain to be proved, in a pleasant
 format.  Also see @(see acl2-pc::print-all-goals).</p>")

(defxdoc acl2-pc::print-all-goals
  :parents (proof-builder-commands)
  :short "(macro)
print all the (as yet unproved) goals"
  :long "<p>Example and General Form: print-all-goals</p>

 <p>Prints all the goals that remain to be proved, in a pleasant format.  Also
 see @(see acl2-pc::print-all-concs).</p>")

(defxdoc acl2-pc::print-main
  :parents (proof-builder-commands)
  :short "(macro)
print the original goal"
  :long "@({
  Example and General Form:
  print-main
 })

 <p>Print the goal as originally entered.</p>")

(defxdoc acl2-pc::pro
  :parents (proof-builder-commands)
  :short "(atomic macro)
repeatedly apply promote"
  :long "@({
  Example and General Form:
  pro
 })

 <p>Apply the @('promote') command until there is no change.  This command
 ``succeeds'' exactly when at least one call of @('promote') ``succeeds''.  In
 that case, only a single new proof-builder state will be created.</p>

 <p>Note: The @('split') command is probably more helpful in many cases than
 @('pro').</p>")

(defxdoc acl2-pc::promote
  :parents (proof-builder-commands)
  :short "(primitive) move antecedents of conclusion's @('implies') term to
top-level hypotheses"
  :long "@({
  Examples:
  promote
  (promote t)
 })

 <p>For example, if the conclusion is @('(implies (and x y) z)'), then after
 execution of @('promote'), the conclusion will be @('z') and the terms @('x')
 and @('y') will be new top-level hypotheses.</p>

 @({
  General Form:
  (promote &optional do-not-flatten-flag)
 })

 <p>Replace conclusion of @('(implies hyps exp)') or @('(if hyps exp t)') with
 simply @('exp'), adding @('hyps') to the list of top-level hypotheses.
 Moreover, if @('hyps') is viewed as a conjunction then each conjunct will be
 added as a separate top-level hypothesis.  An exception is that if
 @('do-not-flatten-flag') is supplied and not @('nil'), then only one top-level
 hypothesis will be added, namely @('hyps').</p>

 <p><b>Remark</b>: You must be at the top of the conclusion in order to use
 this command.  Otherwise, first invoke @('top').</p>")

(defxdoc acl2-pc::protect
  :parents (proof-builder-commands)
  :short "(macro)
run the given instructions, reverting to existing state upon
failure"
  :long "@({
  Example:
  (protect induct p prove)

  General Form:
  (protect &rest instruction-list)
 })

 <p>@('Protect') is the same as @('do-strict'), except that as soon as an
 instruction ``fails'', the state-stack reverts to what it was before the
 @('protect') instruction began, and @('restore') is given the same meaning
 that it had before the @('protect') instruction began.  See @(see
 acl2-pc::do-strict).</p>")

(defxdoc acl2-pc::prove
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(primitive)
call the ACL2 theorem prover to prove the current goal"
  :long "@({
  Examples:
  prove -- attempt to prove the current goal
  (prove :otf-flg t
         :hints ((\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar)))
        -- attempt to prove the current goal, with the indicated hints
           and with OTF-FLG set

  General Form:
  (prove &rest rest-args)
 })

 <p>Attempt to prove the current goal, where @('rest-args') is as in the
 keyword arguments to @('defthm') except that only @(':hints') and
 @(':otf-flg') are allowed.  The command succeeds exactly when the
 corresponding @('defthm') would succeed, except that it is all right for some
 goals to be given ``bye''s.  Each goal given a ``bye'' will be turned into a
 new subgoal.  (See @(see hints) for an explanation of @(':by') hints.)</p>

 <p><b>Remark:</b> Use @('(= t)') instead if you are not at the top of the
 conclusion.  Also note that if there are any hypotheses in the current goal,
 then what is actually attempted is a proof of @('(implies hyps conc)'), where
 @('hyps') is the conjunction of the top-level hypotheses and @('conc') is the
 goal's conclusion.</p>

 <p><b>Remark:</b> It is allowed to use abbreviations in the hints.</p>")

(defxdoc acl2-pc::pso
  :parents (proof-builder-commands)
  :short "(macro)
print the most recent proof attempt from inside the proof-builder"
  :long "@({
  Example and General Form:
  pso
 })

 <p>Print the most recent proof attempt from inside the interactive
 proof-builder assuming you are in @(tsee gag-mode) or have saved output (see
 @(see set-saved-output)).  This includes all calls to the prover, including
 for example @(see proof-builder) commands @('induct'), @('split'), and
 @('bash'), in addition to @('prove').  So for example, you can follow
 @('(quiet prove)') with @('pso') to see the proof, including @(see proof-tree)
 output, if it failed.</p>

 <p>Related @(see proof-builder) commands are @('psog') and @('pso!'); see @(see
 acl2-pc::psog) and @(see acl2-pc::pso!).</p>")

(defxdoc acl2-pc::pso!
  :parents (proof-builder-commands)
  :short "(macro)
print the most recent proof attempt from inside the proof-builder"
  :long "@({
  Example and General Form:
  pso!
 })

 <p>Print the most recent proof attempt from inside the interactive
 proof-builder, including @(see proof-tree) output, assuming you are in @(tsee
 gag-mode) or have saved output (see @(see set-saved-output)).  This includes
 all calls to the prover, including for example @(see proof-builder) commands
 @('induct'), @('split'), and @('bash'), in addition to @('prove').  So for
 example, you can follow @('(quiet prove)') with @('pso!') to see the proof,
 including @(see proof-tree) output, if it failed.</p>

 <p>Related @(see proof-builder) commands are @('pso') and @('psog'); see @(see
 acl2-pc::pso) and @(see acl2-pc::psog).</p>")

(defxdoc acl2-pc::psog
  :parents (proof-builder-commands)
  :short "(macro)
print the most recent proof attempt from inside the proof-builder"
  :long "@({
  Example and General Form:
  psog
 })

 <p>Print the most recent proof attempt from inside the interactive
 proof-builder, including goal names, assuming you are in @(tsee gag-mode) or
 have saved output (see @(see set-saved-output)).  This includes all calls to
 the prover, including for example @(see proof-builder) commands @('induct'),
 @('split'), and @('bash'), in addition to @('prove').  So for example, you can
 follow @('(quiet prove)') with @('psog') to see the proof, including @(see
 proof-tree) output, if it failed.</p>

 <p>Related @(see proof-builder) commands are @('pso') and @('pso!'); see @(see
 acl2-pc::pso) and @(see acl2-pc::pso!).</p>")

(defxdoc acl2-pc::put
  :parents (proof-builder-commands)
  :short "(macro)
substitute for a ``free variable''"
  :long "@({
  Example:
  (put x 17)

  General Form:
  (put var expr)
 })

 <p>Substitute @('expr') for the ``free variable'' @('var'), as explained
 below.</p>

 <p>A ``free variable'' is, for our purposes, a variable @('var') such that the
 instruction @('(free var)') has been executed earlier in the state-stack.
 What @('(free var)') really does is to let @('var') be an abbreviation for the
 term @('(hide var)') (see @(see acl2-pc::add-abbreviation)).  What @('(put var
 expr)') really does is to unwind the state-stack, replacing that @('free')
 instruction with the instruction @('(add-abbreviation var expr)'), so that
 future references to @('(? var)') become reference to @('expr') rather than to
 @('(hide var)'), and then to replay all the other instructions that were
 unwound.  Because @('hide') was used, the expectation is that in most cases,
 the instructions will replay successfully and @('put') will ``succeed''.
 However, if any replayed instruction ``fails'', then the entire replay will
 abort and ``fail'', and the state-stack will revert to its value before the
 @('put') instruction was executed.</p>

 <p>If @('(put var expr)') ``succeeds'', then @('(remove-abbreviation var)')
 will be executed at the end.</p>

 <p><b>Remark</b>: The @('restore') command will revert the state-stack to its
 value present before the @('put') instruction was executed.</p>")

(defxdoc acl2-pc::quiet
  :parents (proof-builder-commands)
  :short "(meta)
run instructions without prover output"
  :long "@({
  Example:
  (quiet induct prove)

  General Form:
  (quiet &rest instruction-list)
 })

 <p>Run the @('instruction-list') through the top-level loop with no
 output.</p>

 <p>Also see @(see acl2-pc::noise) and @(see acl2-pc::quiet!).</p>")

(defxdoc acl2-pc::quiet!
  :parents (proof-builder-commands)
  :short "(meta)
run instructions without prover output"
  :long "@({
  Example:
  (quiet induct prove)

  General Form:
  (quiet &rest instruction-list)
 })

 <p>Run the @('instruction-list') through the top-level loop with no output.
 See @(see acl2-pc::quiet); the two commands are equivalent, except that the
 @('quiet!') command additionally suppresses the printing of goal
 identifiers (as with @(tsee set-print-clause-ids)).</p>")

(defxdoc acl2-pc::r
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
same as rewrite"
  :long "@({
  Example:
  (r 3)
 })

 <p>See @(see acl2-pc::rewrite).</p>")

(defxdoc acl2-pc::reduce
  :parents (proof-builder-commands)
  :short "(atomic macro)
call the ACL2 theorem prover's simplifier"
  :long "@({
  Examples:
  reduce -- attempt to prove the current goal without using induction
  (reduce (\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar))
         -- attempt to prove the current goal without using
            induction, with the indicated hints

  General Form:
  (reduce &rest hints)
 })

 <p>Attempt to prove the current goal without using induction, using the
 indicated hints (if any).  A subgoal will be created for each goal that would
 have been pushed for proof by induction in an ordinary proof.</p>

 <p>Notice that unlike @('prove'), the arguments to @('reduce') are spread out,
 and are all hints.</p>

 <p>@('Reduce') is similar to @('bash') in that neither of these allows
 induction.  But @('bash') only allows simplification, while @('reduce') allows
 processes @('eliminate-destructors'), @('fertilize'), @('generalize'), and
 @('eliminate-irrelevance').</p>

 <p><b>Remark:</b> Induction will be used to the extent that it is ordered
 explicitly in the hints.</p>")

(defxdoc acl2-pc::reduce-by-induction
  :parents (proof-builder-commands)
  :short "(macro)
call the ACL2 prover without induction, after going into
induction"
  :long "@({
  Examples:
  reduce-by-induction
    -- attempt to prove the current goal after going into induction,
       with no further inductions

  (reduce-by-induction (\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar))
    -- attempt to prove the current goal after going into induction,
       with no further inductions, using the indicated hints

  General Form:
  (reduce-by-induction &rest hints)
 })

 <p>A subgoal will be created for each goal that would have been pushed for
 proof by induction in an ordinary proof, except that the proof begins with a
 top-level induction.</p>

 <p>Notice that unlike @('prove'), the arguments to @('reduce-by-induction')
 are spread out, and are all hints.  Also see @(see acl2-pc::prove), @(see
 acl2-pc::reduce), and @(see acl2-pc::bash).</p>

 <p><b>Remark</b>: Induction and the various processes will be used to the
 extent that they are specified explicitly in the @(':induct') and @(':do-not')
 @(see hints).</p>")

(defxdoc acl2-pc::remove-abbreviations
  :parents (proof-builder-commands)
  :short "(primitive)
remove one or more abbreviations"
  :long "@({
  Examples:
  remove-abbreviations -- remove all abbreviations
  (remove-abbreviations v w)
                       -- assuming that V and W currently abbreviate
                          terms, then they are ``removed'' in the
                          sense that they are no longer considered to
                          abbreviate those terms

  General Forms:
  (remove-abbreviations &rest vars)
 })

 <p>If vars is not empty (i.e., not @('nil')), remove the variables in
 @('vars') from the current list of abbreviations, in the sense that each
 variable in @('vars') will no longer abbreviate a term.</p>

 <p><b>Remark:</b> The instruction fails if at least one of the arguments fails
 to be a variable that abbreviates a term.</p>

 <p>Also see @(see acl2-pc::add-abbreviation) for a discussion of abbreviations
 in general, and see @(see acl2-pc::show-abbreviations).</p>")

(defxdoc acl2-pc::repeat
  :parents (proof-builder-commands)
  :short "(macro)
repeat the given instruction until it ``fails''"
  :long "@({
  Example:
  (repeat promote)

  General Form:
  (repeat instruction)
 })

 <p>The given @('instruction') is run repeatedly until it ``fails''.</p>

 <p><b>Remark:</b> There is nothing here in general to prevent the instruction
 from being run after all goals have been proved, though this is indeed the
 case for primitive instructions.</p>")

(defxdoc acl2-pc::repeat-rec
  :parents (proof-builder-commands)
  :short "(macro) auxiliary to @('repeat')"
  :long "<p>See @(see acl2-pc::repeat).</p>")

(defxdoc acl2-pc::replay
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
replay one or more instructions"
  :long "@({
  Examples:
  REPLAY     -- replay all instructions in the current session
                (i.e., state-stack)
  (REPLAY 5) -- replay the most recent 5 instructions
  (REPLAY 5
          (COMMENT deleted dive command here))
             -- replace the 5th most recent instruction with the
                indicated comment instruction, and then replay it
                followed by the remaining 4 instructions

  General Form:
  (REPLAY &OPTIONAL n replacement-instruction)
 })

 <p>Replay the last @('n') instructions if @('n') is a positive integer; else
 @('n') should be @('nil') or not supplied, and replay all instructions.
 However, if @('replacement-instruction') is supplied and not @('nil'), then
 before the replay, replace the @('nth') instruction (from the most recent, as
 shown by @('commands')) with @('replacement-instruction').</p>

 <p>If this command ``fails'', then the @('restore') command will revert the
 state-stack to its value present before the @('replay') instruction was
 executed.</p>")

(defxdoc acl2-pc::restore
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(meta)
remove the effect of an UNDO command"
  :long "@({
  Example and General Form:
  restore
 })

 <p>@('Restore') removes the effect of an @('undo') command.  This always works
 as expected if @('restore') is invoked immediately after @('undo'), without
 intervening instructions.  However, other commands may also interact with
 @('restore'), notably ``sequencing'' commands such as @('do-all'),
 @('do-strict'), @('protect'), and more generally, @('sequence').</p>

 <p><b>Remark:</b> Another way to control the saving of proof-builder state is
 with the @('save') command; see @(see acl2-pc::save).</p>

 <p>The @('restore') command always ``succeeds''; it returns @('(mv nil t
 state)').</p>")

(defxdoc acl2-pc::retain
  :parents (proof-builder-commands)
  :short "(atomic macro)
drop all <b>but</b> the indicated top-level hypotheses"
  :long "@({
  Example:
  (RETAIN 2 3) -- keep the second and third hypotheses, and drop
                  the rest

  General Form:
  (retain &rest args)
 })

 <p>Drop all top-level hypotheses <b>except</b> those with the indicated
 indices.</p>

 <p>There must be at least one argument, and all must be in range (i.e.
 integers between one and the number of top-level hypotheses, inclusive).</p>")

(defxdoc acl2-pc::retrieve
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
re-enter the proof-builder"
  :long "@({
  Examples:
  (retrieve associativity-of-permutationp)
  retrieve

  General Form:
  (retrieve &optional name)
 })

 <p>Must be used from @('outside') the interactive proof-builder loop.  If name
 (which must be a symbol) is supplied and not @('nil'), this causes re-entry to
 the interactive proof-builder loop in the state at which @('save') was last
 executed for the indicated name.  (See @(see acl2-pc::save).)  If @('name') is
 @('nil') or is not supplied, then the user is queried regarding which
 proof-builder state to re-enter.  The query is omitted, however, if there only
 one proof-builder state is present that was saved with @('save'), in which
 case that is the one that is used.  Also see @(see acl2-pc::unsave).</p>")

(defxdoc acl2-pc::rewrite
  :parents (proof-builder-commands)
  :short "(primitive)
apply a rewrite rule"
  :long "@({
  Examples:
  (rewrite reverse-reverse)
     -- apply the rewrite rule `reverse-reverse'
  (rewrite (:rewrite reverse-reverse))
     -- same as above
  (rewrite 2)
     -- apply the second rewrite rule, as displayed by show-rewrites
  rewrite
     -- apply the first rewrite rule, as displayed by show-rewrites
  (rewrite transitivity-of-< ((y 7)))
     -- apply the rewrite rule transitivity-of-< with the substitution
        that associates 7 to the ``free variable'' y
  (rewrite foo ((x 2) (y 3)) t)
     -- apply the rewrite rule foo by substituting 2 and 3 for free
        variables x and y, respectively, and also binding all other
        free variables possible by using the current context
        (hypotheses and governors)

  General Form:
  (rewrite &optional rule-id substitution instantiate-free)
 })

 <p>Replace the current subterm with a new term by applying a @(see rewrite) or
 @(see definition) rule.  The replacement will be done according to the
 information provided by the @('show-rewrites') (@('sr')) command.</p>

 <p>If @('rule-id') is a positive integer @('n'), then the @('n')th rule as
 displayed by @('show-rewrites') is the one that is applied.  If @('rule-id')
 is @('nil') or is not supplied, then it is treated as the number 1.
 Otherwise, @('rule-id') should be either a symbol or else a @(':rewrite') or
 @(':definition') @(see rune).  If a symbol is supplied, then any
 (@(':rewrite') or @(':definition')) rule of that name may be used.  We say
 more about this, and describe the other optional arguments, below.</p>

 <p>Consider first the following example.  Suppose that the current subterm is
 @('(reverse (reverse y))') and that there is a @(see rewrite) rule called
 @('reverse-reverse') of the form</p>

 @({
  (implies (true-listp x)
           (equal (reverse (reverse x)) x)) .
 })

 <p>Then the instruction @('(rewrite reverse-reverse)') causes the current
 subterm to be replaced by @('y') and creates a new goal with conclusion
 @('(true-listp y)').  An exception is that if the top-level hypotheses imply
 @('(true-listp y)') using only ``trivial reasoning'' (more on this below),
 then no new goal is created.</p>

 <p>If the @('rule-id') argument is a number or is not supplied, then the
 system will store an instruction of the form @('(rewrite name ...)'), where
 @('name') is the name of a rewrite rule; this is in order to make it easier to
 replay instructions when there have been changes to the history.  Except:
 instead of the name (whether the name is supplied or calculated), the system
 stores the @(see rune) if there is any chance of ambiguity.  (Formally,
 ``ambiguity'' here means that the rune being applied is of the form
 @('(:rewrite name . index)'), where index is not @('nil').)</p>

 <p>Speaking in general, then, a @('rewrite') instruction works as follows:</p>

 <p>First, a @(see rewrite) or @(see definition) rule is selected according to
 the arguments of the @('rewrite') instruction.  The selection is made as
 explained under ``General Form'' above.</p>

 <p>Next, the left-hand side of the rule is matched with the current subterm,
 i.e., a substitution @('unify-subst') is found such that if one instantiates
 the left-hand side of the rule with @('unify-subst'), then one obtains the
 current subterm.  If this match fails, then the instruction fails.</p>

 <p>Next, an attempt is made to relieve (discharge) the hypotheses, much as the
 theorem prover relieves hypotheses except that there is no call to the
 rewriter.  First, the substitution @('unify-subst') is extended with the
 @('substitution') argument, which may bind free variables (see @(see
 free-variables)).  Each hypothesis of the rule is then considered in turn,
 from first to last.  For each hypothesis, first the current substitution is
 applied, and then the system checks whether the hypothesis is ``clearly'' true
 in the current context.  If there are variables in the hypotheses of the rule
 that are not bound by the current substitution, then a weak attempt is made to
 extend that substitution so that the hypothesis is present in the current
 context (see @(see acl2-pc::hyps)), much as would be done by the theorem
 prover's rewriter.</p>

 <p>If in the process above there are free variables (see @(see
 free-variables)), but the interactive proof-builder can see how to bind them
 to relieve all hypotheses, then it will do so in both the
 @('show-rewrites') (@('sr')) and @('rewrite') commands.  But normally, if even
 one hypothesis remains unrelieved, then no automatic extension of the
 substitution is made.  Except, if @('instantiate-free') is not @('nil'), then
 that extension to the substitution is kept.  (Technical note: in the case of
 an unrelieved hypothesis and a non-@('nil') value of @('instantiate-free'), if
 a @(tsee bind-free) hypothesis produces a list of binding alists, then the
 last of those alists is the one that is used to extend the substitution.)</p>

 <p>Finally, the instruction is applied as follows.  The current subterm is
 replaced by applying the final substitution described above to the right-hand
 side of the selected rule.  And, one new subgoal is created for each
 unrelieved hypothesis of the rule, whose top-level hypotheses are the
 governors and top-level hypotheses of the current goal and whose conclusion
 and current subterm are the instance, by that same final substitution, of that
 unrelieved hypothesis.</p>

 <p><b>Remark:</b> The substitution argument should be a list whose elements
 have the form @('(variable term)'), where @('term') may contain
 abbreviations.</p>")

(defxdoc acl2-pc::run-instr-on-goal
  :parents (proof-builder-commands)
  :short "(macro)
auxiliary to THEN"
  :long "<p>See @(see acl2-pc::then).</p>")

(defxdoc acl2-pc::run-instr-on-new-goals
  :parents (proof-builder-commands)
  :short "(macro) auxiliary to @('then')"
  :long "<p>See @(see acl2-pc::then).</p>")

(defxdoc acl2-pc::runes
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
print the runes (definitions, lemmas, ...) used"
  :long "<code>
 Examples and general forms:
 (runes t)   ; print all @(see rune)s used during this interactive proof
 (runes nil) ; print all @(see rune)s used by the most recent command
 (runes)     ; same as (runes nil)
 runes       ; same as (runes nil)
 </code>

 <p>This command does not change the state of the interactive @(see
 proof-builder).  Rather, it simply reports runes (see @(see rune)) that have
 participated in the interactive proof.</p>

 <p>Note that @('(runes nil)') will show the @(see rune)s used by the most
 recent primitive or macro command (as displayed by @(':comm')).</p>")

(defxdoc acl2-pc::s
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(primitive)
simplify the current subterm"
  :long "@({
  Examples:
  S  -- simplify the current subterm
  (S :backchain-limit 2 :normalize t :expand (append x z))
     -- simplify the current subterm, but during the rewriting
        process, normalization, which will push IFs to the
        top-level, and also force the term (append x z) to be
        expanded during the rewriting process

  General Form:
  (s &key rewrite linear normalize backchain-limit repeat in-theory hands-off
          expand)
 })

 <p>Simplify the current subterm according to the keyword parameters supplied.
 First @(see normalization) is applied (unless the @(':normalize') argument is
 @('nil')), so that for example, each subterm of the form @('(f ... (if test x
 y) ...)')  is replaced by the term @('(if test (f ... x ...) (f ... y ...))')
 &mdash; except, of course, when @('f') is @('if') and the indicated @('if')
 subterm is in the second or third argument position.  See @(see normalize) for
 details.  Then rewriting is applied (unless the rewrite argument is @('nil')).
 Finally this pair of actions is repeated &mdash; until the rewriting step
 causes no change in the term.  A description of each parameter follows.</p>

 @({
  :rewrite -- default t
 })

 <p>When non-@('nil'), instructs the system to use ACL2's rewriter (or,
 something close to it) during simplification.</p>

 @({
  :linear -- default t (except, default nil if :rewrite has value nil)
 })

 <p>When non-@('nil'), instructs the system to use ACL2's <see topic='@(url
 linear-arithmetic)'>linear arithmetic</see> to build a suitable context (a
 ``linear pot list'') from the assumptions
 (the top-level hypotheses and the <see topic='@(url
 acl2-pc::hyps)'>governors</see>).  Note that linear arithmetic is used by the
 rewriter regardless; by default, when @(':s') invokes the rewriter then linear
 arithmetic can take advantage of the information in the top-level hypotheses
 and the governors.</p>

 @({
  :normalize -- default t
 })

 <p>When non-@('nil'), instructs the system to use @(see normalization) (as
 described above) during simplification.</p>

 @({
  :backchain-limit -- default 0
 })

 <p>Sets the number of recursive calls to the rewriter that are allowed for
 backchaining.  Even with the default of 0, some reasoning is allowed
 (technically speaking, type-set reasoning is allowed) in the relieving of
 hypotheses.  The value should be @('nil') or a non-negative integer, and
 limits backchaining only for rewriting, not for type-set reasoning.</p>

 @({
  :repeat -- default 0
 })

 <p>Sets the number of times the current term is to be rewritten.  If this
 value is @('t'), then the default is used (as specified by the constant
 @('*default-s-repeat-limit*')).</p>

 @({
  :in-theory, :hands-off, :expand
 })

 <p>These have their usual meaning; see @(see hints).</p>

 <p><b>Remark:</b> if conditional rewrite rules are used that cause case splits
 because of the use of @('force'), then appropriate new subgoals will be
 created, i.e., with the same current subterm (and address) but with each new
 (forced) hypothesis being negated and then used to create a corresponding new
 subgoal.  In that case, the current goal will have all such new hypotheses
 added to the list of top-level hypotheses.</p>")

(defxdoc acl2-pc::s-prop
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
simplify propositionally"
  :long "@({
  Example:
  s-prop

  General Form:
  (s-prop &rest names)
 })

 <p>Simplify, using the default settings for @('s') (which include @(see
 normalization) and rewriting without real backchaining), but with respect to a
 theory in which only basic functions and rules (the ones in @('(theory
 'minimal-theory)')), together with the names (or parenthesized names) in the
 @('&rest') argument @('names'), are enabled.</p>

 <p>Also see @(see acl2-pc::s).</p>")

(defxdoc acl2-pc::save
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
save the proof-builder state (state-stack)"
  :long "@({
  Example:
  (save lemma3-attempt)

  General Form:
  (save &optional name do-it-flg)
 })

 <p>Saves the current state of the interactive proof-builder by ``associating''
 it with the given name, which must be a symbol.  Submit @('(retrieve name)')
 to Lisp to get back to this proof-builder state.  If @('verify') was
 originally supplied with an event name, then the argument can be omitted in
 favor of that name as the default.</p>

 <p><b>Remark</b> that if a @('save') has already been done with the indicated
 name (or the default event name), then the user will be queried regarding
 whether to go ahead with the save &mdash; except, if @('do-it-flg') is
 supplied and not @('nil'), then there will be no query and the @('save') will
 be effected.</p>

 <p>Also see @(see acl2-pc::retrieve) and @(see acl2-pc::unsave).</p>")

(defxdoc acl2-pc::sequence
  :parents (proof-builder-commands)
  :short "(meta)
run the given list of instructions according to a multitude of
options"
  :long "@({
  Example:
  (sequence (induct p prove) t)
 })

 <p>This is a very general command that is used to define other sequencing
 commands; see @(see acl2-pc::do-all), @(see acl2-pc::do-strict), @(see
 acl2-pc::protect), and @(see acl2-pc::succeed).</p>

 @({
  General Form:
  (sequence
   instruction-list
   &optional
   strict-flg protect-flg success-expr no-prompt-flg no-restore-flg)
 })

 <p>Each instruction in the list @('instruction-list') is run, and the
 instruction ``succeeds'' if every instruction in @('instruction-list')
 ``succeeds''.  However, it might ``succeed'' even if some instructions in the
 list ``fail''; more generally, the various arguments control a number of
 aspects of the running of the instructions.  All this is explained in the
 paragraphs below.  First we embark on a general discussion of the instruction
 interpreter, including the notions of ``succeed'' and ``fail''.</p>

 <p><b>Remark:</b> The arguments are <b>not</b> evaluated, except (in a sense)
 for @('success-expr'), as described below.</p>

 <p>Each primitive and meta instruction can be thought of as returning an @(see
 error-triple), say @('(erp val state)').  An instruction (primitive or meta)
 ``succeeds'' if @('erp') is @('nil') and @('val') is not @('nil'); otherwise
 it ``fails''.  (When we use the words ``succeed'' or ``fail'' in this
 technical sense, we'll always include them in double quotes.)  If an
 instruction ``fails,'' we say that that the failure is ``soft'' if @('erp') is
 @('nil'); otherwise the failure is ``hard''.  The @('sequence') command gives
 the user control over how to treat ``success'' and ``failure'' when sequencing
 instructions, though we have created a number of handy macro commands for this
 purpose, notably @('do-all'), @('do-strict') and @('protect').</p>

 <p>Here is precisely what happens when a @('sequence') instruction is run.
 The instruction interpreter is run on the instructions supplied in the
 argument @('instruction-list') (in order).  The interpreter halts the first
 time there is a hard ``failure.'' except that if @('strict-flg') is supplied
 and not @('nil'), then the interpreter halts the first time there is any
 ``failure.''  The error triple @('(erp val state)') returned by the
 @('sequence') instruction is the triple returned by the last instruction
 executed (or, the triple @('(nil t state)') if @('instruction-list') is
 @('nil')), except for the following provision.  If @('success-expr') is
 supplied and not @('nil'), then it is evaluated with the state global
 variables @('pc-erp') and @('pc-val') (in the \"ACL2\" package) bound to the
 corresponding components of the error triple returned (as described above).
 At least two values should be returned, and the first two of these will be
 substituted for @('erp') and @('val') in the triple finally returned by
 @('sequence').  For example, if @('success-expr') is @('(mv erp val)'), then
 no change will be made to the error triple, and if instead it is @('(mv nil
 t)'), then the @('sequence') instruction will ``succeed''.</p>

 <p>That concludes the description of the error triple returned by a
 @('sequence') instruction, but it remains to explain the effects of the
 arguments @('protect-flg') and @('no-prompt-flg').</p>

 <p>If @('protect-flg') is supplied and not @('nil') and if also the
 instruction ``fails'' (i.e., the error component of the triple is not @('nil')
 or the value component is @('nil')), then the state is reverted so that the
 interactive proof-builder's state (including the behavior of @('restore')) is
 set back to what it was before the @('sequence') instruction was executed.
 Otherwise, unless @('no-restore-flg') is set, the state is changed so that the
 @('restore') command will now undo the effect of this @('sequence')
 instruction (even if there were nested calls to @('sequence')).</p>

 <p>Finally, as each instruction in @('instruction-list') is executed, the
 prompt and that instruction will be printed, unless the global state variable
 @('pc-print-prompt-and-instr-flg') is unbound or @('nil') and the parameter
 @('no-prompt-flg') is supplied and not @('nil').</p>")

(defxdoc acl2-pc::show-abbreviations
  :parents (proof-builder-commands)
  :short "(macro)
display the current abbreviations"
  :long "@({
  Examples:
  (show-abbreviations v w)
     -- assuming that v and w currently abbreviate terms,
        then this instruction displays them together with
        the terms they abbreviate
  show-abbreviations
     -- display all abbreviations
 })

 <p>Also see @(see acl2-pc::add-abbreviation) for a general discussion of
 abbreviations and see @(see acl2-pc::remove-abbreviations).</p>

 @({
  General Form:
  (show-abbreviations &rest vars)
 })

 <p>Display each argument in @('vars') together with the term it abbreviates
 (if any).  If there are no arguments, i.e. the instruction is simply
 @('show-abbreviations'), then display all abbreviations together with the
 terms they abbreviate.</p>

 <p>If the term abbreviated by a variable, say @('v'), contains a proper
 subterm that is also abbreviate by (another) variable, then both the
 unabbreviated term and the abbreviated term (but not using @('(? v)') to
 abbreviate the term) are displayed with together with @('v').</p>")

(defxdoc acl2-pc::show-linears
  :parents (proof-builder-commands)
  :short "(macro)
display the applicable @(see linear) rules"
  :long "@({
  Example:
  show-linears

  General Form:
  (show-linears &optional rule-id enabled-only-flg)
 })

 <p>This command displays @(see linear) rules with a trigger term that matches
 the current subterm, and shows how they can be applied.  This command is
 analogous to the @('show-rewrites') @(see proof-builder) command; see @(see
 acl2-pc::show-rewrites).  Also see @(see acl2-pc::apply-linear) for how to
 apply @(see linear) rules.</p>")

(defxdoc acl2-pc::show-rewrites
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
display the applicable @(see rewrite) rules"
  :long "@({
  Example:
  show-rewrites

  General Form:
  (show-rewrites &optional rule-id enabled-only-flg)
 })

 <p>This command displays @(see rewrite) rules whose left-hand side matches the
 current subterm, and shows how that command can be applied.  For each rule
 displayed, hypotheses are shown that would need to be proved after the rule is
 applied.  Note that hypotheses are omitted from the display when the system
 can trivially verify that they hold; to see all hypotheses for each rule in a
 display that is independent of the arguments of the current subterm, use the
 @('pl') or @('pr') command.</p>

 <p>Here are details on the arguments and the output.  If @('rule-id') is
 supplied and is a name (non-@('nil') symbol) or a @(':')@(tsee rewrite) or
 @(':')@(tsee definition) @(see rune), then only the corresponding rewrite
 rule(s) will be displayed, while if @('rule-id') is a positive integer @('n'),
 then only the @('n')th rule that would be in the list is displayed.  In each
 case, the display will point out when a rule is currently disabled (in the
 interactive environment), except that if @('enabled-only-flg') is supplied and
 not @('nil'), then disabled rules will not be displayed at all.  Finally,
 among the free variables of any rule (see @(see free-variables)), those that
 would remain free if the rule were applied will be displayed.  Also see @(see
 rewrite).</p>")

(defxdoc acl2-pc::show-type-prescriptions
  :parents (proof-builder-commands)
  :short "(macro)
display the applicable @(see type-prescription) rules"
  :long "@({
  Example:
  show-type-prescriptions

  General Form:
  (show-type-prescriptions &optional rule-id)
 })

 <p>Display @(see type-prescription) rules that apply to the current subterm.
 If @('rule-id') is supplied and is a name (non-@('nil') symbol) or a
 @(':')@(tsee rewrite) or @(':')@(tsee definition) @(see rune), then only the
 corresponding rewrite rule(s) will be displayed.  In each case, the display
 will point out when a rule is currently disabled (in the interactive
 environment).  Also see @(see type-prescription).</p>")

(defxdoc acl2-pc::skip
  :parents (proof-builder-commands)
  :short "(macro)
``succeed'' without doing anything"
  :long "@({
  Example and General Form:
  skip
 })

 <p>Make no change in the state-stack, but ``succeed''.  Same as @('(sequence
 nil)').</p>")

(defxdoc acl2-pc::sl
  :parents (proof-builder-commands)
  :short "(atomic macro)
simplify with lemmas"
  :long "@({
  Examples:
  sl
  (sl 3)

  General Form:
  (sl &optional backchain-limit)
 })

 <p>Simplify, but with all function definitions disabled (see @(see
 function-theory) in the top-level ACL2 loop), except for a few basic functions
 (the ones in @('(theory 'minimal-theory)')).  The @('backchain-limit') has a
 default of 0, but if is supplied and not @('nil'), then it should be a
 nonnegative integer; see @(see acl2-pc::s).</p>

 <p>WARNING: This command completely ignores @('in-theory') commands that are
 executed inside the interactive @(see proof-builder).</p>")

(defxdoc acl2-pc::sls
  :parents (proof-builder-commands)
  :short "(macro)
same as SHOW-LINEARS"
  :long "@({
  Example:
  sls

  General Form:
  (sls &optional rule-id enabled-only-flg)
 })

 <p>See @('show-linears').  NOTE: In analogy to the @('sr') abbreviation for
 @('show-rewrites'), one might expect this command to be @('sl'); but that name
 was taken (``simplify with lemmas'') before @('sls') was implemented.</p>")

(defxdoc acl2-pc::split
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
split the current goal into cases"
  :long "@({
  Example:
  split
 })

 <p>For example, if the current goal has one hypothesis @('(or x y)') and a
 conclusion of @('(and a b)'), then @('split') will create four new goals:</p>

 @({
  one with hypothesis X and conclusion A
  one with hypothesis X and conclusion B
  one with hypothesis Y and conclusion A
  one with hypothesis Y and conclusion B.

  General Form:
  SPLIT
 })

 <p>Replace the current goal by subgoals whose conjunction is equivalent
 (primarily by propositional reasoning) to the original goal, where each such
 goal cannot be similarly split.</p>

 <p><b>Remark:</b> The new goals will all have their hypotheses promoted; in
 particular, no conclusion will have a top function symbol of @('implies').
 Also note that @('split') will fail if there is exactly one new goal created
 and it is the same as the existing current goal.</p>

 <p>The way @('split') really works is to call the ACL2 theorem prover with
 only simplification (and preprocessing) turned on, and with only a few
 built-in functions (especially, propositional ones) enabled, namely, the ones
 in the list @('(theory 'minimal-theory)').  However, because the prover is
 called, type-set reasoning can be used to eliminate some cases.  For example,
 if @('(true-listp x)') is in the hypotheses, then probably @('(true-listp (cdr
 x))') will be reduced to @('t').</p>")

(defxdoc acl2-pc::sr
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
same as SHOW-REWRITES"
  :long "@({
  Example:
  sr

  General Form:
  (sr &optional rule-id enabled-only-flg)
 })

 <p>See @(see acl2-pc::show-rewrites).</p>")

(defxdoc acl2-pc::st
  :parents (proof-builder-commands)
  :short "(macro)
same as SHOW-TYPE-PRESCRIPTIONS"
  :long "@({
  Example:
  sr

  General Form:
  (st &optional rule-id)
 })

 <p>See @(see acl2-pc::show-type-prescriptions).</p>")

(defxdoc acl2-pc::succeed
  :parents (proof-builder-commands)
  :short "(macro)
run the given instructions, and ``succeed''"
  :long "@({
  Example:
  (succeed induct p prove)

  General Form:
  (succeed &rest instruction-list)
 })

 <p>Run the indicated instructions until there is a hard ``failure'', and
 ``succeed''.  (See @(see acl2-pc::sequence) for an explanation of ``success''
 and ``failure''.)</p>")

(defxdoc acl2-pc::th
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(macro)
print the top-level hypotheses and the current subterm"
  :long "@({
  Examples:
  th               -- print all (top-level) hypotheses and the current
                      subterm
  (th (1 3) (2 4)) -- print hypotheses 1 and 3 and governors 2 and 4,
                      and the current subterm
  (th (1 3) t)     -- print hypotheses 1 and 3 and all governors, and
                      the current subterm

  General Form:
  (th &optional hyps-indices govs-indices)
 })

 <p>Print hypotheses and the current subterm.  The printing of hypotheses (and
 perhaps governors) are controlled as in the @('hyps') command; see @(see
 acl2-pc::hyps).</p>

 <p>Historical note: The name @('th') is adapted from the Gypsy Verification
 Environment, where @('th') abbreviates the command @('theorem'), which says to
 print information on the current goal.</p>")

(defxdoc acl2-pc::then
  :parents (proof-builder-commands)
  :short "(macro)
apply one instruction to current goal and another to new subgoals"
  :long "@({
  Example:
  (then induct prove)

  General Form:
  (then first-instruction &optional completion must-succeed-flg)
 })

 <p>Run @('first-instruction'), and then run @('completion') (another
 instruction) on each subgoal created by @('first-instruction').  If
 @('must-succeed-flg') is supplied and not @('nil'), then halt at the first
 ``failure'' and remove the effects of the invocation of @('completion') that
 ``failed''.</p>

 <p>The default for completion is @('reduce').</p>")

(defxdoc acl2-pc::top
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
move to the top of the goal"
  :long "@({
  Example and General Form:
  top
 })

 <p>For example, if the conclusion is @('(= x (* (- y) z))') and the current
 subterm is @('y'), then after executing @('top'), the current subterm will be
 the same as the conclusion, i.e., @('(= x (* (- y) z))').</p>

 <p>@('Top') is the same as @('(up n)'), where @('n') is the number of times
 one needs to execute @('up') in order to get to the top of the conclusion.
 The @('top') command fails if one is already at the top of the conclusion.</p>

 <p>Also see @(see acl2-pc::up), @(see acl2-pc::dive), @(see acl2-pc::nx), and
 @(see acl2-pc::bk).</p>")

(defxdoc acl2-pc::type-alist
  :parents (proof-builder-commands)
  :short "(macro)
display the @(see type-alist) from the current context"
  :long "@({
  Examples:
  (type-alist t t)     ; display type-alist based on conclusion and governors
  (type-alist t t t)   ; as above, but also display forward-chaining report
  type-alist           ; same as (type-alist nil t) -- governors only
  (type-alist nil)     ; same as (type-alist nil t) -- governors only
  (type-alist t)       ; same as (type-alist t nil) -- conclusion only
  (type-alist nil nil) ; display type-alist without considering
                       ; conclusion or governors

  General Form:
  (type-alist &optional concl-flg govs-flg fc-report-flg)
 })

 <p>where if @('govs-flg') is omitted then it defaults to @('(not concl-flg)'),
 and @('concl-flg') and @('fc-report-flg') default to @('nil').</p>

 <p>Display the current assumptions as a @(see type-alist).  Note that this
 display includes the result of forward chaining.  When @('fc-report-flg') is
 supplied a non-@('nil') value, the display also includes a forward-chaining
 report; otherwise,the presence or absence of such a report is controlled by
 the usual global settings (see @(see forward-chaining-reports)).</p>

 <p>There are two basic reasons contemplated for using this command.</p>

 <p>1. The theorem prover has failed (either outside the interactive
 proof-builder or using a proof-builder command such as @('bash') or
 @('reduce') and you want to debug by getting an idea of what the prover knows
 about the context.</p>

 <blockquote>

 <p>a. You really are interested in the context for the current term.  Include
 hypotheses and governors (i.e., accounting for tests of surrounding
 @('if')-expressions that must be true or false) but not the current conclusion
 (which the theorem prover's heuristics would generally ignore for contextual
 information).  Command:<br></br>

 @('(type-alist nil t)') ; equivalently, @('type-alist') or @('(type-alist
 nil)')</p>

 <p>b. You are not thinking in particular about the current term; you just want
 to get an idea of the context that the prover would build at the top-level,
 for forward-chaining.  Incorporate the conclusion but not the governors.
 Command:<br></br>

 @('(type-alist t nil)') ; equivalently, @('(type-alist t)')</p></blockquote>

 <p>2. You intend to use one of the interactive @(see proof-builder-commands)
 that does simplification, such as @('s') or @('x'), and you want to see the
 context.  Then include the surrounding @('if')-term governors but not the
 goal's conclusion.  Command:<br></br>

 @('(type-alist nil t)') ; equivalently, @('type-alist') or @('(type-alist
 nil)')</p>

 <p>See @(see type-set) (also see @(see type-prescription)) for information
 about ACL2's type system, which can assist in understanding the output of the
 @('type-alist') command.</p>")

(defxdoc acl2-pc::undo
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(meta)
undo some instructions"
  :long "@({
  Examples:
  (undo 7)
  undo

  General Forms:

  (undo n) -- Undo the last n instructions.  The argument n should be
              a positive integer.

  undo     -- Same as (undo 1).
 })

 <p><b>Remark:</b> To remove the effect of an @('undo') command, use
 @('restore'); see @(see acl2-pc::restore).</p>

 <p><b>Remark:</b> If the argument @('n') is greater than the total number of
 interactive instructions in the current session, then @('(undo n)') will
 simply take you back to the start of the session.</p>

 <p>The @('undo') meta command always ``succeeds''; it returns @('(mv nil t
 state)') unless its optional argument is supplied and of the wrong type
 (i.e. not a positive integer) or there are no instructions to undo.</p>")

(defxdoc acl2-pc::unsave
  :parents (proof-builder-commands)
  :short "(macro)
remove a proof-builder state"
  :long "@({
  Example:
  (unsave assoc-of-append)

  General Form:
  (unsave &optional name)
 })

 <p>Eliminates the association of an interactive proof-builder state with
 @('name'), if @('name') is supplied and not @('nil').  The name may be
 @('nil') or not supplied, in which case it defaults to the event name supplied
 with the original call to @('verify') (if there is one &mdash; otherwise, the
 instruction ``fails'' and there is no change).  The ACL2 function @('unsave')
 may also be executed outside the interactive loop, with the same syntax.</p>

 <p>Also see @(see acl2-pc::save) and @(see acl2-pc::retrieve).</p>")

(defxdoc acl2-pc::up
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(primitive)
move to the parent (or some ancestor) of the current subterm"
  :long "@({
  Examples:  if the conclusion is (= x (* (- y) z)) and the
             current subterm is y, then we have:
  up or (up 1) -- the current subterm becomes (- y)
  (up 2)       -- the current subterm becomes (* (- y) z)
  (up 3)       -- the current subterm becomes the entire conclusion
  (up 4)       -- no change; can't go up that many levels

  General Form:
  (up &optional n)
 })

 <p>Move up @('n') levels in the conclusion from the current subterm, where
 @('n') is a positive integer.  If @('n') is not supplied or is @('nil'), then
 move up one level, i.e., treat the instruction as @('(up 1)').</p>

 <p>Also see @(see acl2-pc::dive), @(see acl2-pc::top), @(see acl2-pc::nx), and
 @(see acl2-pc::bk).</p>")

(defxdoc acl2-pc::use
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
use a lemma instance"
  :long "@({
  Example:
  (USE true-listp-append
       (:instance assoc-of-append (x a) (y b) (z c)))
  -- Add two top-level hypotheses, one the lemma called
     true-listp-append, and the other an instance of the lemma called
     assoc-of-append by the substitution in which x is assigned a, y
     is assigned b, and z is assigned c.

  General Form:
  (use &rest args)
 })

 <p>Add the given lemma instances to the list of top-level hypotheses.  See
 @(see hints) for the syntax of @(':use') hints in @('defthm'), which is
 essentially the same as the syntax here (see the example above).</p>

 <p>This command calls the @('prove') command, and hence should only be used at
 the top of the conclusion.</p>")

(defxdoc acl2-pc::wrap
  :parents (proof-builder-commands)
  :short "(atomic macro)
execute the indicated instructions and combine all the new goals"
  :long "@({
  Example:
  (wrap induct) ; induct, then replace first new goal by the conjunction of all
                ; the new goals, and drop all new goals after the first

  General Form:
  (wrap &rest instrs)
 })

 <p>First the instructions in @('instrs') are executed, as in @('do-all').  If
 this ``fails'' then no additional action is taken.  Otherwise, the current
 goal after execution of @('instrs') is conjoined with all ``new'' goals, in
 the sense that their names are not among the names of goals at the time
 @('instrs') was begun.  This conjunction becomes the new current goal and
 those ``new'' goals are dropped.</p>

 <p>See the code for the interactive @(see proof-builder) command,
 @('wrap-induct'), for an example of the use of @('wrap').</p>")

(defxdoc acl2-pc::wrap-induct
  :parents (proof-builder-commands)
  :short "(atomic macro)
same as induct, but create a single goal"
  :long "@({
  Examples:
  wrap-induct
  (wrap-induct t)
  (wrap-induct (append (reverse x) y))

  General Form:
  (wrap-induct &optional term)
 })

 <p>The @('wrap-induct') command is identical to the interactive @(tsee
 proof-builder)'s @('induct') command (see @(see acl2-pc::induct)), except that
 only a single goal is created: the conjunction of the base and induction
 steps.</p>

 <p>Note: The output will generally indicate that more than goal has been
 created, e.g.:</p>

 @({
  Creating two new goals:  (MAIN . 1) and (MAIN . 2).
 })

 <p>However, @('wrap-induct') always creates a unique goal (when it succeeds).
 A subsequent message clarifies this, for example:</p>

 @({
  NOTE: Created ONLY one new goal, which is the current goal:
    (MAIN . 1)
 })

 ")

(defxdoc acl2-pc::wrap1
  :parents (proof-builder-commands)
  :short "(primitive)
combine goals into a single goal"
  :long "@({
  Examples:
  ; Keep (main . 1) and (main . 2) if they exist, as well as the current goal;
  ; and for each other goal, conjoin it into the current goal and delete it:
  (wrap1 ((main . 1) (main . 2)))

  ; As explained below, conjoin all subsequent siblings of the current goal
  ; into the current goal, and then delete them:
  (wrap1)

  General Form:
  (wrap1 &optional kept-goal-names)
 })

 <p>If @('kept-goal-names') is not @('nil'), the current goal is replaced by
 conjoining it with all goals other than the current goal and those indicated
 by @('kept-goal-names'), and those other goals are deleted.  If
 @('kept-goal-names') is omitted, then the the current goal must be of the form
 @('(name . n)'), and the goals to conjoin into the current goal (and delete)
 are those with names of the form @('(name . k)') for @('k') &gt;= @('n').</p>

 <p>NOTE: @('Wrap1') always ``succeeds'', even if there are no other goals to
 conjoin into the current goal (a message is printed in that case), and it
 always leaves you with no hypotheses at the top of the current goal's
 conclusion (as though @('top') and @('demote') had been executed, if
 necessary).</p>

 <p>Also see @(see acl2-pc::wrap).</p>")

(defxdoc acl2-pc::x
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
expand and (maybe) simplify function call at the current subterm"
  :long "@({
  Examples:
  x --  expand and simplify.
 })

 <p>Also see @(see acl2-pc::expand) and see @(see acl2-pc::x-dumb), which do
 not perform simplification.</p>

 <p>For example, if the current subterm is (append a b), then after @('x') the
 current subterm will probably be (cons (car a) (append (cdr a) b)) if (consp
 a) and (true-listp a) are among the top-level hypotheses and governors.  If
 there are no top-level hypotheses and governors, then after @('x') the current
 subterm will probably be:</p>

 @({
  (if (true-listp x)
      (if x
          (cons (car x) (append (cdr x) y))
        y)
    (apply 'binary-append (list x y))).

  General Form:
  (X &key
     rewrite normalize backchain-limit in-theory hands-off expand)
 })

 <p>Expand the function call at the current subterm, and simplify using the
 same conventions as with the @('s') command (see @(see acl2-pc::s)).</p>

 <p>Unlike @('s'), it is permitted to set both @(':rewrite') and
 @(':normalize') to @('nil'), which will result in no simplification; see
 @(see acl2-pc::x-dumb).</p>

 <p><b>Remark</b> (obscure): On rare occasions the current address may be
 affected by the use of @('x').  For example, suppose we have the
 definition</p>

 @({
  (defun g (x) (if (consp x) x 3))
 })

 <p>and then we enter the interactive proof-builder with</p>

 @({
  (verify (if (integerp x) (equal (g x) 3) t)) .
 })

 <p>Then after invoking the instruction @('(dive 2 1)'), so that the current
 subterm is @('(g x)'), followed by the instruction @('x'), we would expect the
 conclusion to be @('(if (integerp x) (equal 3 3) t)').  However, the system
 actually replaces @('(equal 3 3)') with @('t') (because we use the ACL2
 term-forming primitives), and hence the conclusion is actually @('(if
 (integerp x) t t)').  Therefore, the current address is put at @('(2)') rather
 than @('(2 1)').  In such cases, a warning ``@('NOTE')'' will be printed to
 the terminal.</p>

 <p>The other primitive commands to which the above ``truncation'' note applies
 are @('equiv'), @('rewrite'), and @('s').</p>")

(defxdoc acl2-pc::x-dumb
  :parents (proof-builder-commands proof-builder-commands-short-list)
  :short "(atomic macro)
expand function call at the current subterm, without simplifying"
  :long "@({
  General Form:
  x-dumb:  expand without simplification.
 })

 <p>Same as @('(expand t)').  See @(see acl2-pc::expand).</p>

 <p>Also see @(see acl2-pc::x), which performs simplification.</p>")

; The following would be nice but it causes a read error without the |..|, of
; course.  But even with |#.|, then acl2-doc has problems.
; (defpointer |#.| sharp-dot-reader)
(defpointer &allow-other-keys macro-args)
(defpointer &body macro-args)
(defpointer &key macro-args)
(defpointer &optional macro-args)
(defpointer &rest macro-args)
(defpointer &whole macro-args)
(defpointer abstract-stobj defabsstobj)
(defpointer accumulated-persistence-oops accumulated-persistence)
(defpointer acl2s acl2-sedan)
(defpointer add-ld-keyword-alias ld-keyword-aliases)
(defpointer add-ld-keyword-alias! ld-keyword-aliases)
(defpointer add-to-set-eq add-to-set)
(defpointer add-to-set-eql add-to-set) ; pre-v4-3 compatibility
(defpointer add-to-set-equal add-to-set)
(defpointer all-calls system-utilities)
(defpointer all-vars system-utilities)
(defpointer apropos finding-documentation)
(defpointer arglistp system-utilities)
(defpointer array arrays)
(defpointer assoc-eq assoc)
(defpointer assoc-equal assoc)
(defpointer backchain-limit-rw hints t)
(defpointer backtrack hints t)
(defpointer body system-utilities)
(defpointer book-makefiles books-certification)
(defpointer by hints t)
(defpointer cases hints t)
(defpointer certifying-books books-certification)
(defpointer check-invariant-risk set-check-invariant-risk)
(defpointer close-input-channel io)
(defpointer close-output-channel io)
(defpointer check-sum checksum)
(defpointer community-book community-books)
(defpointer computed-hint computed-hints)
(defpointer conjoin system-utilities)
(defpointer cons-count-bounded system-utilities)
(defpointer cons-term system-utilities)
(defpointer cons-term* system-utilities)
(defpointer context ctx)
(defpointer default-state-vars system-utilities)
(defpointer default-verify-guards-eagerness set-verify-guards-eagerness)
(defpointer defined-constant system-utilities)
(defpointer delete-assoc-eq delete-assoc)
(defpointer delete-assoc-equal delete-assoc)
(defpointer disjoin system-utilities)
(defpointer disjoin2 system-utilities)
(defpointer do-not-induct hints t)
(defpointer dynamically-monitor-rewrites dmr)
(defpointer enabled-numep system-utilities)
(defpointer enabled-runep system-utilities)
(defpointer er-let* programming-with-state)
(defpointer error hints t)
(defpointer ev$ apply$)
(defpointer ev$-list apply$)
(defpointer execution evaluation)
(defpointer expand hints t)
(defpointer extended-syntaxp syntaxp)
(defpointer external-format character-encoding)
(defpointer fake-rune rune)
(defpointer fargn system-utilities)
(defpointer fargs system-utilities)
(defpointer fast-alist fast-alists)
(defpointer fast-alist-discipline slow-alist-warning)
(defpointer fcons-term system-utilities)
(defpointer fcons-term* system-utilities)
(defpointer fdefun-mode system-utilities)
(defpointer ffn-symb system-utilities)
(defpointer ffn-symb-p system-utilities)
(defpointer ffnnamep system-utilities)
(defpointer ffnnamep-lst system-utilities)
(defpointer flambda-applicationp system-utilities)
(defpointer flambdap system-utilities)
(defpointer fms!-to-string printing-to-strings)
(defpointer fms-to-string printing-to-strings)
(defpointer fmt!-to-string printing-to-strings)
(defpointer fmt-to-string printing-to-strings)
(defpointer fmt1!-to-string printing-to-strings)
(defpointer fmt1-to-string printing-to-strings)
(defpointer fn-symb system-utilities)
(defpointer fncall-term meta-extract)
(defpointer forced force)
(defpointer formals system-utilities)
(defpointer fquotep system-utilities)
(defpointer fsubcor-var system-utilities)
(defpointer function-symbolp system-utilities)
(defpointer gcs get-command-sequence)
(defpointer genvar system-utilities)
(defpointer get-brr-local system-utilities)
(defpointer get-check-invariant-risk set-check-invariant-risk)
(defpointer get-event system-utilities)
(defpointer get-output-stream-string$ io)
(defpointer get-register-invariant-risk set-register-invariant-risk)
(defpointer get-skipped-proofs-p system-utilities)
(defpointer getting-started acl2-tutorial)
(defpointer guards guard)
(defpointer guard-hints xargs t)
(defpointer guard-msg-table set-guard-msg)
(defpointer hands-off hints t)
(defpointer if-intro splitter)
(defpointer ignorable declare)
(defpointer ignore declare)
(defpointer immed-forced splitter)
(defpointer implicate system-utilities)
(defpointer induct hints t)
(defpointer inline defun-inline)
(defpointer intersection-eq intersection$)
(defpointer intersection-equal intersection$)
(defpointer intersectp-eq intersectp)
(defpointer intersectp-equal intersectp)
(defpointer iprint set-iprint)
(defpointer iprinting set-iprint)
(defpointer keyword keywordp)
(defpointer lambda term)
(defpointer lambda-applicationp system-utilities)
(defpointer lambda-body system-utilities)
(defpointer lambda-formals system-utilities)
(defpointer let-mbe equality-variants-details)
(defpointer logicp system-utilities)
(defpointer make-lambda system-utilities)
(defpointer match-free free-variables)
(defpointer measure-theorem termination-theorem)
(defpointer member-eq member)
(defpointer member-equal member)
(defpointer memoization memoize)
(defpointer merge-sort-lexorder system-utilities)
(defpointer meta-extract-contextual-fact meta-extract)
(defpointer meta-extract-formula meta-extract)
(defpointer meta-extract-global-fact meta-extract)
(defpointer meta-extract-global-fact+ meta-extract)
(defpointer meta-extract-rw+-term meta-extract)
(defpointer mfc metafunction-context)
(defpointer mfc-ancestors extended-metafunctions)
(defpointer mfc-ap extended-metafunctions)
(defpointer mfc-clause extended-metafunctions)
(defpointer mfc-rdepth extended-metafunctions)
(defpointer mfc-relieve-hyp extended-metafunctions)
(defpointer mfc-rw extended-metafunctions)
(defpointer mfc-rw+ extended-metafunctions)
(defpointer mfc-ts extended-metafunctions)
(defpointer mfc-type-alist extended-metafunctions)
(defpointer mfc-unify-subst extended-metafunctions)
(defpointer mfc-world extended-metafunctions)
(defpointer mode xargs t)
(defpointer no-duplicatesp-eq no-duplicatesp)
(defpointer no-duplicatesp-equal no-duplicatesp)
(defpointer no-op hints t)
(defpointer no-thanks hints t)
(defpointer non-executable xargs t)
(defpointer nonlinearp hints t)
(defpointer normalization normalize)
(defpointer nvariablep system-utilities)
(defpointer observation-cw observation)
(defpointer open-input-channel io)
(defpointer open-input-channel-p io)
(defpointer open-output-channel io)
(defpointer open-output-channel-p io)
(defpointer optimize declare)
(defpointer package packages)
(defpointer pe-table extend-pe-table)
(defpointer peek-char$ io)
(defpointer plist-worldp system-utilities)
(defpointer position-eq position)
(defpointer position-equal position)
(defpointer pound-bang-reader sharp-bang-reader)
(defpointer pound-dot-reader sharp-dot-reader)
(defpointer pound-u-reader sharp-u-reader)
(defpointer prettyify-clause system-utilities)
(defpointer print-object$ io)
(defpointer print-object$-preserving-case io)
(defpointer print-summary-user finalize-event-user)
(defpointer programp system-utilities)
(defpointer proof-supporters-alist dead-events)
(defpointer put-assoc-eq put-assoc)
(defpointer put-assoc-eql put-assoc) ; pre-v4-3 compatibility
(defpointer put-assoc-equal put-assoc)
(defpointer quotep system-utilities)
(defpointer rassoc-eq rassoc)
(defpointer rassoc-equal rassoc)
(defpointer read-byte$ io)
(defpointer read-char$ io)
(defpointer read-object io)
(defpointer read-object-suppress io)
(defpointer read-object-with-case io)
(defpointer recursivep system-utilities)
(defpointer redefine ld-redefinition-action)
(defpointer redefining ld-redefinition-action)
(defpointer regression books-certification)
(defpointer remove-duplicates-eq remove-duplicates)
(defpointer remove-duplicates-equal remove-duplicates)
(defpointer remove-eq remove)
(defpointer remove-equal remove)
(defpointer remove-guard-holders guard-holders)
(defpointer remove1-eq remove1)
(defpointer remove1-equal remove1)
(defpointer reorder hints t)
(defpointer reset-print-control print-control)
(defpointer restrict hints t)
(defpointer ruler-extenders rulers)
(defpointer ruler rulers)
(defpointer rw-cache set-rw-cache-state)
(defpointer rw-cache-state hints t)
(defpointer saving-and-restoring save-exec)
(defpointer set-accumulated-persistence accumulated-persistence)
(defpointer set-difference-eq set-difference$)
(defpointer set-difference-equal set-difference$)
(defpointer set-ld-keyword-aliases ld-keyword-aliases)
(defpointer set-ld-keyword-aliases! ld-keyword-aliases)
(defpointer set-ld-prompt ld-prompt)
(defpointer set-ld-redefinition-action ld-redefinition-action)
(defpointer set-ld-skip-proofs ld-skip-proofsp)
(defpointer set-ld-skip-proofsp ld-skip-proofsp)
(defpointer set-let*-abstraction set-let*-abstractionp)
(defpointer set-non-linear set-non-linearp)
(defpointer set-print-circle print-control)
(defpointer set-print-escape print-control)
(defpointer set-print-length print-control)
(defpointer set-print-level print-control)
(defpointer set-print-lines print-control)
(defpointer set-print-readably print-control)
(defpointer set-print-right-margin print-control)
(defpointer set-ruler-extenders rulers)
(defpointer set-serialize-character with-serialize-character)
(defpointer set-slow-alist-action slow-alist-warning)
(defpointer set-temp-touchable-fns remove-untouchable)
(defpointer set-temp-touchable-vars remove-untouchable)
(defpointer show-accumulated-persistence accumulated-persistence)
(defpointer single-threaded-objects stobj)
(defpointer split-types xargs t)
(defpointer stable-under-simplificationp computed-hints)
(defpointer stobj-let nested-stobjs)
(defpointer stobjs xargs t)
(defpointer stobjs-in system-utilities)
(defpointer stobjs-out system-utilities)
(defpointer subcor-var system-utilities)
(defpointer sublis-fn system-utilities)
(defpointer sublis-fn-lst-simple system-utilities)
(defpointer sublis-fn-simple system-utilities)
(defpointer sublis-var system-utilities)
(defpointer subsetp-eq subsetp)
(defpointer subsetp-equal subsetp)
(defpointer subst-expr system-utilities)
(defpointer subst-var system-utilities)
(defpointer symbol-class system-utilities)
(defpointer tag-tree ttree)
(defpointer translate system-utilities)
(defpointer translate1 system-utilities)
(defpointer translate11 system-utilities)
(defpointer translate-cmp system-utilities)
(defpointer translate1-cmp system-utilities)
(defpointer ttag defttag)
(defpointer trust-tag defttag)
(defpointer typespec-check meta-extract)
(defpointer undoing undo)
(defpointer union-eq union$)
(defpointer union-equal union$)
(defpointer untranslate-preprocess user-defined-functions-table)
(defpointer use hints t)
(defpointer value system-utilities)
(defpointer variablep system-utilities)
(defpointer verify-guards-eagerness set-verify-guards-eagerness)
(defpointer waterfall hints-and-the-waterfall)
(defpointer with-output! with-output)
(defpointer write-byte$ io)

#||

;; See the documentation for SET-MAX-MEM and cert.pl.  This overrides
;; the previous occurrence of set-max-mem in the documentation for HONS-NOTE,
;; which fools cert.pl into thinking this book takes tons of memory to
;; certify.  (This is probably relevant only for folks at Centaur or for
;; other folks who are using clustering software that understands PBS
;; directives.)

 (value-triple (set-max-mem (* 2 (expt 2 30))))
||#
